本文整理自工做多年以來遇到的全部 Git 問題彙總,以前都是遺忘的時候去看一遍操做,此次從新整理了一下,發出來方便你們收藏以及須要的時候查找答案。html
通常代碼提交流程爲:工做區 -> git status
查看狀態 -> git add .
將全部修改加入暫存區-> git commit -m "提交描述"
將代碼提交到 本地倉庫 -> git push
將本地倉庫代碼更新到 遠程倉庫前端
當你改亂了工做區某個文件的內容,想直接丟棄工做區的修改時,用命令git checkout -- file
。git
// 丟棄工做區的修改 git checkout -- <文件名> 複製代碼
當你不但改亂了工做區某個文件的內容,還 git add
添加到了暫存區時,想丟棄修改,分兩步,第一步用命令 git reset HEAD <file>
,就回到了場景1,第二步按場景1操做。github
// 把暫存區的修改撤銷掉(unstage),從新放回工做區。 git reset HEAD <文件名> 複製代碼
更改 commit 信息緩存
git commit --amend -m「新提交消息」
複製代碼
commit 時,遺漏提交部分更新,有兩種解決方案:bash
方案一:再次 commitmarkdown
git commit -m「提交消息」
複製代碼
此時,git 上會出現兩次 commitapp
方案二:遺漏文件提交到以前 commit 上dom
git add missed-file // missed-file 爲遺漏提交文件 git commit --amend --no-edit 複製代碼
--no-edit
表示提交消息不會更改,在 git 上僅爲一次提交ssh
刪除指定的 commit
// 修改版本庫,保留暫存區,保留工做區 // 將版本庫軟回退1個版本,軟回退表示將本地版本庫的頭指針所有重置到指定版本,且將此次提交以後的全部變動都移動到暫存區。 git reset --soft HEAD~1 // 修改版本庫,修改暫存區,修改工做區 //將版本庫回退1個版本,不只僅是將本地版本庫的頭指針所有重置到指定版本,也會重置暫存區,而且會將工做區代碼也回退到這個版本 git reset --hard HEAD~1 // git版本回退,回退到特定的commit_id版本,能夠經過git log查看提交歷史,以便肯定要回退到哪一個版本(commit 以後的即爲ID); git reset --hard commit_id 複製代碼
撤銷 某次操做,這次操做以前和以後的commit和history都會保留,而且把此次撤銷
做爲一次最新的提交
// 撤銷前一次 commit git revert HEAD // 撤銷前前一次 commit git revert HEAD^ // (好比:fa042ce57ebbe5bb9c8db709f719cec2c58ee7ff)撤銷指定的版本,撤銷也會做爲一次提交進行保存。 git revert commit 複製代碼
git revert
是提交一個新的版本,將須要revert
的版本的內容再反向修改回去, 版本會遞增,不影響以前提交的內容
git revert
和 git reset
的區別git revert
是用一次新的commit來回滾以前的commit,git reset
是直接刪除指定的commit。git revert
是用一次逆向的commit「中和」以前的提交,所以往後合併老的branch時,致使這部分改變不會再次出現,可是git reset
是之間把某些commit在某個branch上刪除,於是和老的branch再次merge時,這些被回滾的commit應該還會被引入。git reset
是把HEAD向後移動了一下,而git revert
是HEAD繼續前進,只是新的commit的內容和要revert的內容正好相反,可以抵消要被revert的內容。git clone 地址
git branch 分支名
git branch
git branch -a
git checkout 分支名
(通常修改未提交則沒法切換,大小寫問題常常會有,可強制切換 git checkout 分支名 -f
非必須慎用)git push <遠程倉庫> <本地分支>:<遠程分支>
將某個遠程主機的更新,所有/分支 取回本地(此時之更新了Repository)它取回的代碼對你本地的開發代碼沒有影響,如需完全更新需合併或使用git pull
拉取遠程主機某分支的更新,再與本地的指定分支合併(至關與fetch加上了合併分支功能的操做)
將本地分支的更新,推送到遠程主機,其命令格式與git pull
類似
git clone -b 分支名倉庫地址
git checkout -b serverfix origin/serverfix
git merge hotfix
:(將 hotfix 分支合併到當前分支)git merge origin/serverfix
git branch -d hotfix
:(刪除本地 hotfix 分支)git push origin --delete serverfix
git push origin newName
;git branch branchName
:(建立名爲 branchName 的本地分支)git checkout branchName
:(切換到 branchName 分支)git checkout -b branchName
:(至關於以上兩條命令的合併)git branch
git branch -a
git branch -m oldName newName
git branch -m oldName newName
git branch --set-upstream-to origin/newName
在團隊協做過程當中,假設你和你的同伴在本地中分別有各自的新提交,而你的同伴先於你 push
了代碼到遠程分支上,因此你必須先執行 git pull
來獲取同伴的提交,而後才能push
本身的提交到遠程分支。
而按照 Git 的默認策略,若是遠程分支和本地分支之間的提交線圖有分叉的話(即不是 fast-forwarded),Git 會執行一次 merge
操做,所以產生一次沒意義的提交記錄,從而形成了像上圖那樣的混亂。
其實在 pull 操做的時候,,使用 git pull --rebase
選項便可很好地解決上述問題。 加上 --rebase
參數的做用是,提交線圖有分叉的話,Git 會 rebase 策略來代替默認的 merge 策略。
假設提交線圖在執行 pull 前是這樣的:
A---B---C remotes/origin/master
/
D---E---F---G master
複製代碼
若是是執行 git pull
後,提交線圖會變成這樣:
A---B---C remotes/origin/master
/ \
D---E---F---G---H master
複製代碼
結果多出了 H
這個不必的提交記錄。若是是執行 git pull --rebase
的話,提交線圖就會變成這樣:
remotes/origin/master | D---E---A---B---C---F'---G' master 複製代碼
F
G
兩個提交經過 rebase
方式從新拼接在 C
以後,多餘的分叉去掉了,目的達到。
大多數時候,使用 git pull --rebase
是爲了使提交線圖更好看,從而方便 code review。
不過,若是你對使用 git 還不是十分熟練的話,個人建議是 git pull --rebase
多練習幾回以後再使用,由於 rebase 在 git 中,算得上是『危險行爲』。
另外,還需注意的是,使用 git pull --rebase
比直接 pull 容易致使衝突的產生,若是預期衝突比較多的話,建議仍是直接 pull。
注意:
git pull = git fetch + git merge
git pull --rebase = git fetch + git rebase
上述的 git pull --rebase
策略目的是修整提交線圖,使其造成一條直線,而即將要用到的 git merge --no-ff <branch-name>
策略恰恰是反行其道,刻意地弄出提交線圖分叉出來。
假設你在本地準備合併兩個分支,而恰好這兩個分支是 fast-forwarded 的,那麼直接合並後你獲得一個直線的提交線圖,固然這樣沒什麼壞處,但若是你想更清晰地告訴你同伴:這一系列的提交都是爲了實現同一個目的,那麼你能夠刻意地將此次提交內容弄成一次提交線圖分叉。
執行 git merge --no-ff <branch-name>
的結果大概會是這樣的:
中間的分叉線路圖很清晰的顯示這些提交都是爲了實現 complete adjusting user domains and tags
每每個人習慣是,在合併分支以前(假設要在本地將 feature 分支合併到 dev 分支),會先檢查 feature 分支是否『部分落後』於遠程 dev 分支:
git checkout dev git pull # 更新 dev 分支 git log feature..dev 複製代碼
若是沒有輸出任何提交信息的話,即表示 feature 對於 dev 分支是 up-to-date 的。若是有輸出的話而立刻執行了 git merge --no-ff
的話,提交線圖會變成這樣:
因此這時在合併前,一般我會先執行:
git checkout feature
git rebase dev
複製代碼
這樣就能夠將 feature 從新拼接到更新了的 dev 以後,而後就能夠合併了,最終獲得一個乾淨舒服的提交線圖。
再次提醒:像以前提到的,rebase 是『危險行爲』,建議你足夠熟悉 git 時才這麼作,不然的話是得不償失啊。
使用 git pull --rebase
和 git merge --no-ff
其實和直接使用 git pull
git merge
獲得的代碼應該是同樣。
使用 git pull --rebase
主要是爲是將提交約線圖平坦化,而 git merge --no-ff
則是刻意製造分叉。
$ cd ~/.ssh $ ls id_rsa id_rsa.pub known_hosts 複製代碼
其中 id_rsa 是私鑰,id_rsa.pub 是公鑰。
git config --list // 查看是否設置了user.name與user.email,沒有的話,去設置 // 設置全局的user.name與user.email git config --global user.name "XX" git config --global user.email "XX" 複製代碼
ssh-keygen -t rsa -C "email"
)$ ssh-keygen Generating public/private rsa key pair. Enter file in which to save the key (/Users/schacon/.ssh/id_rsa): Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /Users/schacon/.ssh/id_rsa. Your public key has been saved in /Users/schacon/.ssh/id_rsa.pub. The key fingerprint is: 複製代碼
$ cat ~/.ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAklOUpkDHrfHY17SbrmTIpNLTGK9Tjom/BWDSU
GPl+nafzlHDTYW7hdI4yZ5ew18JH4JW9jbhUFrviQzM7xlELEVf4h9lFX5QVkbPppSwg0cda3
Pbv7kOdJ/MTyBlWXFCR+HAo3FXRitBqxiX1nKhXpHAZsMciLq8V6RjsNAQwdsdMFvSlVK/7XA
t3FaoJoAsncM1Q9x5+3V0Ww68/eIFmb1zuUFljQJKprrX88XypNDvjYNby6vw/Pb0rwert/En
mZ+AW4OZPnTPI89ZPmVMLuayrD2cE86Z/il8b+gw3r3+1nKatmIkjn2so1d01QraTlMqVSsbx
NrRFi9wrf+M7Q== schacon@agadorlaptop.local
複製代碼
git stash
可用來暫存當前正在進行的工做,好比想 pull 最新代碼又不想 commit , 或者另爲了修改一個緊急的 bug ,先 stash,使返回到本身上一個 commit,,改完 bug 以後再 stash pop , 繼續原來的工做;
git stash
;git stash list
;git stash pop
;git stash apply stash@{1}
;Filename too long warning: Clone succeeded, but checkout failed.
git config --system core.longpaths true 複製代碼
git config user.name
git config user.email
複製代碼
git config --global user.name "username" git config --global user.email "email" 複製代碼
git rm -r --cached . git add . git commit -m ".gitignore is now working」 複製代碼
一、配置remote,指向原始倉庫
git remote add upstream https://github.com/InterviewMap/InterviewMap.git
複製代碼
二、上游倉庫獲取到分支,及相關的提交信息,它們將被保存在本地的 upstream/master 分支
git fetch upstream # remote: Counting objects: 75, done. # remote: Compressing objects: 100% (53/53), done. # remote: Total 62 (delta 27), reused 44 (delta 9) # Unpacking objects: 100% (62/62), done. # From https://github.com/ORIGINAL_OWNER/ORIGINAL_REPOSITORY # * [new branch] master -> upstream/master 複製代碼
三、切換到本地的 master 分支
git checkout master # Switched to branch 'master' 複製代碼
四、把 upstream/master 分支合併到本地的 master 分支,本地的 master 分支便跟上游倉庫保持同步了,而且沒有丟失本地的修改。
git merge upstream/master # Updating a422352..5fdff0f # Fast-forward # README | 9 ------- # README.md | 7 ++++++ # 2 files changed, 7 insertions(+), 9 deletions(-) # delete mode 100644 README # create mode 100644 README.md 複製代碼
五、上傳到本身的遠程倉庫中
git push
複製代碼
本文參考了 潔癖者用 Git:pull --rebase 和 merge --no-ff
想看更過系列文章,點擊前往 github 博客主頁
走在最後,歡迎關注:前端瓶子君,每日更新