git分支間切換注意點和bug分支的處理
備註:
本文參考於廖雪峰老師的部落格Git教程。依照其部落格進行學習和記錄,感謝其無私分享,也歡迎各位查看原文。
知識點
-
當前一個分支上修改文件或目錄後,在沒有提交前,任何一個分支的狀態(
git status
)都會同步為一樣 -
合併或切換分支工作,一定是在當前分支提交後,或者使用
git stash
將當前暫存區狀態保存下來之後進行,即當前分支git status
顯示為乾淨的倉庫再切換 -
同時修改了同一個工作區相同文件,由於Git管理版本是通過移動
HEAD
指針,工作區的修改對於移動到不同分支的指針是一樣的。此時master
和dev
分支git add
添加到暫存區,git status
在不同分支狀態是一樣的,如果master
分支先commit
,中間所做的修改,會全部算作master
的修改(由於dev
沒有提交,僅僅add
添加了暫存區,中間的修改在切換分支提交後會在dev
分支丟失,但所有修改都存在於master
的提交中)。故:實際開發中一定要提交或者暫存當前暫存區的狀態後,再切換分支進行其他修改,否則在本分支所做修改的狀態會丟失。 -
git stash
對於git
沒有管理的文件狀態不會保存(新創建或修改沒有添加過的文件)。 -
git stash list
查看stash
的列表 -
git stash pop
恢復stash
到當前分支,並刪除stash
-
git stash apply
,git stash drop
恢復stash
和刪除stash
-
git stash apply stash@{0}
恢復指定的stash
到當前分支。
記一次分支合併問題狀況
從分支點開始,不同分支修改工作區的內容(不添加到暫存區和提交),切換分支,工作區的內容是一樣的。
這一點也證明了,Git修改的是HEAD
指針,而不是文件
如下:
-
–
git status
查看dev
分支上Git的狀態,乾淨工作區 -
切換到mster,查看Git狀態,乾淨工作區
$ git status
位於分支 dev
無文件要提交,乾淨的工作區
$ git checkout master
切換到分支 'master'
您的分支領先 'origin/master' 共 8 個提交。
(使用 "git push" 來發布您的本地提交)
$ git status
位於分支 master
您的分支領先 'origin/master' 共 8 個提交。
(使用 "git push" 來發布您的本地提交)
無文件要提交,乾淨的工作區
- master分支下,修改readme文件,查看狀態,和切換到dev分支下,查看狀態。忽略遠程分支的提示。
$ git status
位於分支 master
您的分支領先 'origin/master' 共 8 個提交。
(使用 "git push" 來發布您的本地提交)
尚未暫存以備提交的變更:
(使用 "git add <文件>..." 更新要提交的內容)
(使用 "git checkout -- <文件>..." 丟棄工作區的改動)
修改: readme.txt
修改尚未加入提交(使用 "git add" 和/或 "git commit -a")
$ git checkout dev
M readme.txt
切換到分支 'dev'
$ git status
位於分支 dev
尚未暫存以備提交的變更:
(使用 "git add <文件>..." 更新要提交的內容)
(使用 "git checkout -- <文件>..." 丟棄工作區的改動)
修改: readme.txt
修改尚未加入提交(使用 "git add" 和/或 "git commit -a")
必須在提交或者暫存當前暫存區的狀態後,再切換或合併分支
工作區的修改對於不同分支是一樣的:
同時修改了同一個工作區相同文件,由於Git管理版本是通過移動
HEAD
指針,工作區的修改對於移動到不同分支的指針是一樣的。此時master
和dev
分支git add
添加到暫存區,git status
在不同分支狀態是一樣的,如果master
分支先commit
,中間所做的修改,會全部算作master
的修改(由於dev
沒有提交,僅僅add
添加了暫存區,中間的修改在切換分支提交後會在dev
分支丟失,但所有修改都存在於master
的提交中)。故:實際開發中一定要提交或者暫存當前暫存區的狀態後,再切換分支進行其他修改,否則在本分支所做修改的狀態會丟失。同理,合併分支也一樣,必須在提交或者暫存當前暫存區狀態後,再進行分支的合併。
如下為修改工作區或添加到暫存區後對git分支切換和提交的整體測試:
- 如下,
master
分支上修改readme
,查看狀態,
$ git status
位於分支 master
您的分支領先 'origin/master' 共 8 個提交。
(使用 "git push" 來發布您的本地提交)
尚未暫存以備提交的變更:
(使用 "git add <文件>..." 更新要提交的內容)
(使用 "git checkout -- <文件>..." 丟棄工作區的改動)
修改: readme.txt
修改尚未加入提交(使用 "git add" 和/或 "git commit -a")
- 切換到
dev
查看狀態,
$ git checkout dev
M readme.txt
切換到分支 'dev'
$ git status
位於分支 dev
尚未暫存以備提交的變更:
(使用 "git add <文件>..." 更新要提交的內容)
(使用 "git checkout -- <文件>..." 丟棄工作區的改動)
修改: readme.txt
修改尚未加入提交(使用 "git add" 和/或 "git commit -a")
- 在
dev
分支上修改readme
文件,切換到master
分支,查看內容
$ git checkout master
M readme.txt
切換到分支 'master'
您的分支領先 'origin/master' 共 8 個提交。
(使用 "git push" 來發布您的本地提交)
$ cat readme.txt
`this is a test that I learning and use git version control system
this is a beginning
wofaidognyixie dognxi
create two new branch
Creating a new branch is quick and simple.
add a new branch
master modify
dev modify
- 在
master
分支上將修改添加到暫存區,查看狀態
$ git add readme.txt
$ git status
位於分支 master
您的分支領先 'origin/master' 共 8 個提交。
(使用 "git push" 來發布您的本地提交)
要提交的變更:
(使用 "git reset HEAD <文件>..." 以取消暫存)
修改: readme.txt
- 切換到
dev
分支,修改readme
文件後,切換回master
分支,查看狀態。會出現工作區的修改提示
$ git checkout dev
M readme.txt
切換到分支 'dev'
$ git checkout master
M readme.txt
切換到分支 'master'
您的分支領先 'origin/master' 共 8 個提交。
(使用 "git push" 來發布您的本地提交)
$ git status
位於分支 master
您的分支領先 'origin/master' 共 8 個提交。
(使用 "git push" 來發布您的本地提交)
要提交的變更:
(使用 "git reset HEAD <文件>..." 以取消暫存)
修改: readme.txt
尚未暫存以備提交的變更:
(使用 "git add <文件>..." 更新要提交的內容)
(使用 "git checkout -- <文件>..." 丟棄工作區的改動)
修改: readme.txt
- 切換回
dev
分支,git add
添加在存儲區後,查看狀態,狀態為暫存(未提交)
$ git checkout dev
M readme.txt
切換到分支 'dev'
$ git add readme.txt
$ git status
位於分支 dev
要提交的變更:
(使用 "git reset HEAD <文件>..." 以取消暫存)
修改: readme.txt
- 切換回
master
分支,git status
查看狀態也為暫存(未提交)
$ git checkout master
M readme.txt
切換到分支 'master'
您的分支領先 'origin/master' 共 8 個提交。
(使用 "git push" 來發布您的本地提交)
liu@liu-virtual-machine:~/gitTest$ git status
位於分支 master
您的分支領先 'origin/master' 共 8 個提交。
(使用 "git push" 來發布您的本地提交)
要提交的變更:
(使用 "git reset HEAD <文件>..." 以取消暫存)
修改: readme.txt
- 在
master
分支提交,查看狀態,顯示無文件要提交,工作區乾淨
$ git commit -m"commit master"
[master 1ba95a4] commit master
1 file changed, 2 insertions(+)
$ git status
位於分支 master
您的分支領先 'origin/master' 共 9 個提交。
(使用 "git push" 來發布您的本地提交)
無文件要提交,乾淨的工作區
- 切換到
dev
分支,工作區狀態為乾淨,暫存區無提交,如下。
$ git checkout dev
切換到分支 'dev'
$ git status
位於分支 dev
無文件要提交,乾淨的工作區
- 此時,分別在
master
和dev
分支先查看readme
文件內容
dev
分支,顯示為所有改動之前的內容
master
分支下的readme
文件內容為最新(包含在dev
分支下修改和添加到暫存區的內容)
超前提交的分支無法合併落後版本的分支(即無法倒退到未提交過的分支狀態)
目前所知,依靠分支之間的合併(merge)無法實現版本倒退(也許有辦法,未進行深入研究),只能通過git reset --hard commit_id
實現版本回退。
在master
上新建分支dev
,然後修改master
上內容,並添加提交,此時master
的版本比dev
版本要高,如果此時想把dev
(分支的低版本)合併到master
上會發生什麼呢?
master
如果更新後(更新後的上游分支),試圖將未進行更新的dev
分支合併到當前分支,會提示必須給出一個提交資訊解釋此合併,否則會終止合併提交
輸入合理解釋後,會再一次確認存儲緩衝區的更改
如下為操作完成後的終端狀態
$ git merge dev
Merge made by the 'recursive' strategy.
testOndev.txt | 0
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 testOndev.txt
但是查看文件內容,並沒有回到原先狀態。
倒退合併失敗,其實這種情況應該使用版本回退。
- 即使使用
--no-ff
參數,使用普通模式合併,如下:
$ git merge --no-ff -m"merge backup" dev
Already up-to-date.
文件內容依然保持和master一致,沒有合併到dev分支狀態。
解決:使用版本回退git reset --hard commit_id
,可以完成實際的修改。
$ git reset --hard a7d3eb7
HEAD 現在位於 a7d3eb7 fixed conflict
內容修改。
bug分支
有了上面切換分支和合併失敗的經歷,就不難理解下面的操作了。
軟體開發中,bug
總是在你想到和想不到的正常情況和意外情況下出現。修復bug
,在Git中完全可以通過建立一個臨時分支來修復,修復後合併分支即可。
但是當你正在開發時,對於突然接到一個修復bug
的任務,由於當前開發(dev
分支)沒有完成,dev
上的工作可能還沒有提交。
此時如果想創建一個臨時分支issue10
修復master
分支的bug
。
查看Git狀態如下:
$ git status
位於分支 dev
要提交的變更:
(使用 "git reset HEAD <文件>..." 以取消暫存)
新文件: newFile
尚未暫存以備提交的變更:
(使用 "git add <文件>..." 更新要提交的內容)
(使用 "git checkout -- <文件>..." 丟棄工作區的改動)
修改: readme.txt
由於沒有開發完,可能暫時無法提交
暫存當前暫存區的狀態
- Git提供了一個
stash
功能,可以把當前暫存區工作狀態「儲藏」起來,等以後恢復現場後繼續工作。
$ git stash
Saved working directory and index state WIP on dev: 0df6e43 Merge branch 'dev'
HEAD 現在位於 0df6e43 Merge branch 'dev'
- 查看狀態,顯示無文件要提交,工作區也是乾淨的。
$ git status
位於分支 dev
無文件要提交,乾淨的工作區
註:git stash
對於git沒有管理的文件狀態不會保存(新創建沒有添加過的文件)。
- 確定從哪個分支上修復
bug
,現在在master
分支上修復,切換並新建分支issue10
。
$ git checkout master
切換到分支 'master'
您的分支領先 'origin/master' 共 13 個提交。
(使用 "git push" 來發布您的本地提交)
$ git checkout -b issue10
切換到一個新分支 'issue10'
$ cat readme.txt
`this is a test that I learning and use git version control system
this is a beginning
wofaidognyixie dognxi
create two new branch
Creating a new branch is quick and simple.
add a new branch
master modify
dev modify again commit on master
如上為readme內容,將master modify
改為modify on master
,提交
$ git add readme.txt
$ git commit -m"fixed a bug"
[issue10 afc33ef] fixed a bug
1 file changed, 1 insertion(+), 1 deletion(-)
切換到master
分支併合並。最後刪除issue10
分支
$ git checkout master
切換到分支 'master'
您的分支領先 'origin/master' 共 13 個提交。
(使用 "git push" 來發布您的本地提交)
$ git merge --no-ff -m"merged fixed bug" issue10
Merge made by the 'recursive' strategy.
readme.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
$ git branch -d issue10
已刪除分支 issue10(曾為 afc33ef)。
bug
修改完成後,現在回到dev
分支接著開發,此時dev
的狀態是乾淨的。
$ git checkout dev
切換到分支 'dev'
$ git status
位於分支 dev
無文件要提交,乾淨的工作區
- 使用
git stash list
查看暫存的狀態
$ git stash list
stash@{0}: WIP on dev: 0df6e43 Merge branch 'dev'
恢復暫存起來的狀態
-
用
git stash apply
恢復,但恢復後,stash
內容並不刪除,需要用git stash drop
來刪除 -
使用
git stash pop
,恢復的同時會把stash
內容也刪除。
$ git stash pop
位於分支 dev
要提交的變更:
(使用 "git reset HEAD <文件>..." 以取消暫存)
新文件: newFile
尚未暫存以備提交的變更:
(使用 "git add <文件>..." 更新要提交的內容)
(使用 "git checkout -- <文件>..." 丟棄工作區的改動)
修改: readme.txt
丟棄了 refs/stash@{0} (90a1bdda8ec2c4d1a2833b45ffa2a0be3f2af670)
可以多次stash
,恢復的時候,先用git stash list
查看,然後用git stash apply
指定恢復到哪個狀態
$ git stash apply stash@{0}