目錄
Git自學與掉坑實錄(一)
· 創建版本庫
· 添加提交文件至版本庫
Git自學與掉坑實錄(二)
· 本地文件的修改與提交
· 多版本之間的切換
· 查看版本歷史
· 忽略特殊文件
Git自學與掉坑實錄(三)
· 工作區、暫存區、版本庫的概念
· 進行到各個階段管理(添加、刪除、恢復、修改)文件的方法
Git自學與掉坑實錄(四)
· 遠程倉庫
· Github的入門說明
· 參與開源項目
Git自學與掉坑實錄(五)
· 管理(創建、合并、刪除)分支
· 解決沖突
· Fast forward模式與禁用(是否顯示合并信息)
· bug分支
· 功能分支
· 多人協作(查看信息、推送遠程庫、抓?。?/p>
Git自學與掉坑實錄(六)
· 創建標簽
· 刪除標簽(本地與遠程)
Git自學與掉坑實錄(七)
· 顯示代碼顏色
· 忽略文件與強制添加某些忽略文件
· 搭建Git服務器
<br />
十二、分支管理
Git里有一條默認分支"master分支"。"HEAD"指向"master分支","master分支"指向提交,因此"HEAD"指向的就是當前分支。
當提交時,Git用"master"指向最新的提交,"HEAD"指向"master"就能確定當前分支,以及當前分支的提交點。每次提交,"master分支"都會向前延伸,"HEAD"和"master"的指針隨之向前移動,隨著不斷提交,"master分支"的線越來越長。
了解了這個概念,也就是了解分支管理的基礎。分支管理十分便于協作開發,協作者可以創建多個分支,每個人在自己的分支上獨立工作,不影響其他人,工作完成后再一次性合并到原來的分支上。
之前的章節我們也提到Git快速的版本切換,在分支的創建、切換、刪除上也同樣是分分鐘搞定的,簡而言之就是通過版本的指向,而不去改變工作區的內容。下面具體說說:
1.創建與合并分支
· 創建分支
輸入命令$(創建并切換"dev分支")git checkout -b dev
;
我們創建一條新分支"dev分支",并改變"HEAD"的指向。此時工作區的文件沒有任何變化,但是接下來版本庫的提交和修改就是針對"dev分支"了。
最新一次提交后,"dev"的指針前進一步,"master"不變
git checkout -b
中的-b
表示創建并切換"dev分支"為當前分支,相當于兩條命令:
輸入命令$(創建"dev分支")git branch dev
;
輸入命令$(切換"dev分支")git checkout dev
;
輸入命令$(查看當前分支)git branch
;
git branch
會列出所有分支,并在當前分支前加"*"
"dev分支"為當前分支
于是我們對"wil.txt"文件隨意修改點什么,并提交;
輸入命令$(切換回"master分支")git checkout master
我們發現,"wil.txt"修改的內容不見了。
說明我們只是切換到了"master分支",而"master分支"此時的提交點沒有變,因此我們還需要一步合并分支。
</br>
· 合并分支
輸入命令$(將"dev分支"的最新修改合并到"master分支")git merge dev
git merge
表示合并指定分支("dev分支")到當前分支。此時我們再查看"wil.txt"內容。
合并成功
在合并過程中,我們看到了"Fast-forward",代表快進模式,所以速度很快。
</br>
· 刪除分支
輸入命令$(刪除"dev分支")git branch -d dev
合并完成后,可以刪除"dev分支",實際上就是把"dev"的指針刪掉,此時我們只剩一條"master分支"。
通過分支推進項目的進程
輸入命令$(查看當前分支)git branch
;
<br />
2.解決沖突
當新分支與"master分支"都有新的提交時,合并就會產生沖突。
比如我們再新建一個"feature1分支",并分別對同一文件進行修改。我們在"feature1分支"上對"wil.txt"文件進行修改并提交:
當指針從"feature1分支"切換回"master分支"時,Git自動提示我們,當前"master分支"比遠程的"master分支"超前1個提交。
在"master分支"上也對"wil.txt"文件進行修改并提交:
這種情況下,Git就無法執行Fast-forward(快速合并)當新分支與"master分支"都有新的提交時,合并就會產生沖突。
我們試著把兩個分支合并看看情況:
· 輸入命令$(將"feature1分支"的最新修改合并到"master分支")git merge feature1
· 輸入命令$git status
· 再來看看這時候的"wil.txt"長什么樣:
輸入命令$
cat wil.txt
Git用"<<<<<<<","=======",">>>>>>>"標記出不同分支的內容。我們在文檔中修改后保存。
· 手動修改文件
可以直接打開"wil.txt",也可以輸入命令$vi wil.txt
進行編輯,修改內容如下:
· 提交修改文件
· 輸入命令$(分支的合并情況)
git log --graph --pretty=oneline --abbrev-commit
· 輸入命令$(刪除"feature1分支")
git branch -d feature1
· 完成。
<br />
3.分支管理策略
通常合并分支時,如果Git使用Fast forward模式,刪除分支后,會丟掉分支合并信息。
如果要強制禁用Fast forward模式,Git就會在merge時生成一個新的commit,這樣,從分支歷史上就可以看出分支信息。
輸入命令$(禁用Fast forward):git merge --no-ff -m "merge with no-ff(描述)" dev(分支名)
--no-ff
表示強制禁用Fast forward,使用普通模式合并。因為會創建一個新的commit,所以加上-m參數,把commit描述寫進去。
輸入命令$(查看分支歷史):git log --graph --pretty=oneline --abbrev-commit
當前文檔內容即"dev分支"修改的內容,并且可以看到分支的合并歷史
總結一下,"master分支"是非常穩定的,也就是僅用來發布新版本,平時不能在上面干活。"dev分支"(或其他新建分支)是不穩定的,干活都在"dev分支"上。每個人都有自己的分支,時不時地往dev分支上合并。
當版本發布時,先把"dev分支"合并到"master分支"上,再在"master分支"發布版本。而加上--no-ff
參數就是為了查看歷史時,可以看到每一個分支的合并記錄。
<br />
4.Bug分支
軟件開發中,bug就像家常便飯一樣。有了bug就需要修復,在Git中,由于分支是如此的強大,所以,每個bug都可以通過一個新的臨時分支來修復,修復后,合并分支,然后將臨時分支刪除。
但實際工作場景很可能會出現這種情況,你急需修復一個bug,但是該分支上進行的工作還沒有結束無法提交。這時候我們需要把分支上正在進行的工作儲藏起來。
· 儲存當前工作分支內容("dev分支")
輸入命令$(儲藏當前工作現場)git stash
;
再用$git status
查看工作區,應該是干凈的(除非有沒有被Git管理的文件)。
· 修復出錯分支("dev分支")
確定在哪個分支上修復,就在那個分支創建臨時分支。假設需要在"master分支"修復:
輸入命令$git checkout master
;
輸入命令$(切換創建"issue-101臨時分支")git checkout -b issue-101
。
修復bug,改寫"wil.txt"內容并提交:
輸入命令$git add wil.txt
;
輸入命令$git commit -m "fix bug 101"
。
修復完成后,切換到"master分支",完成合并,最后刪除"issue-101臨時分支":
輸入命令$git checkout master
;
輸入命令$git merge --no-ff -m "merged bug fix 101" issue-101
;
輸入命令$git branch -d issue-101
。
· 回到之前的工作分支("dev分支")
輸入命令$git checkout dev
;
輸入命令$git status
;
" On branch dev
nothing to commit (working directory clean) "
說明工作區是干凈的。
輸入命令$(查看stash)git stash list
;
" stash@{0}: WIP on dev: 6224937 add merge "
說明"stash@{0}"的工作內容還在,Git把stash內容存在某個地方,需要把它恢復一下。
· 恢復到工作分支的場景("dev分支")
a.輸入命令$(恢復后,stash內容并不刪除)git stash apply
;
輸入命令$git stash drop
b.輸入命令$(恢復的同時把stash內容也刪了)git stash pop
再次輸入命令$(查看stash)git stash list
;
就看不到任何stash內容了。
*當有多個stash時,我們可以選擇恢復制定的stash。
輸入命令$(恢復后,"stash@{0}"的內容并不刪除)git stash apply stash@{0}
;
<br />
5.Feature分支
在每個項目中,一定會不斷增加新功能,所以每添加一個新功能就新建一個"feature分支"。在上面進行開發、合并、刪除等操作。
舉例,
· 開發代號為"Vulcan"的新功能。
輸入命令$(切換并創建"feature-vulcan分支")git checkout -b feature-vulcan
;
輸入命令$(添加修改文件并提交)git add vulcan.py
&git commit -m "add feature vulcan"
;
輸入命令$(切回"dev分支")git checkout dev
。
· 要求銷毀新功能
輸入命令$(刪除"feature-vulcan分支")git branch -d feature-vulcan
;
"error: The branch 'feature-vulcan' is not fully merged.
If you are sure you want to delete it, run 'git branch -D feature-vulcan'."
由于"feature-vulcan分支"還未合并(merge),刪除將丟失分支上的修改。如果需要強行刪除,輸入命令git branch -D feature-vulcan
。
· 刪除成功
<br />
6.多人協作
當你從遠程倉庫克隆時,實際上Git自動把本地的"master分支"和遠程的"master分支"對應起來了,并且,遠程倉庫的默認名稱是"origin"。
· 查看遠程庫信息
輸入命令$(查看遠程庫的信息)git remote
輸入命令$(查看遠程庫的顯示詳細信息)git remote -v
· 推送分支
輸入命令$(把"master分支"的所有本地提交推送到遠程庫)git push origin master
輸入命令$(把"dev分支"的所有本地提交推送到遠程庫)git push origin dev
master分支是主分支,因此要時刻與遠程同步;
dev分支是開發分支,團隊成員都需要在上面工作,所以也需要與遠程同步;
bug分支只用于在本地修復bug,就沒必要推到遠程了,除非老板要看看你每周到底修復了幾個bug;
feature分支是否推到遠程,取決于你是否和你的小伙伴合作在上面開發。
總之,就是在Git中,分支完全可以在本地自己藏著玩,是否推送,視你的心情而定!
· 抓取分支
多人協作時,大家都會往"master分支"和"dev分支"上推送各自的修改。
假裝你是一個路人A,在另一臺電腦(注意要把SSH Key添加到GitHub)或者同一臺電腦的另一個目錄下克隆。
輸入命令$(克隆Github上的項目)git clone git@github.com:Github用戶名/learngit.git
此時路人A從遠程庫克隆時,默認情況下只能看到本地的"master分支"。
輸入命令$git branch
現在,路人A要在"dev分支"上開發,必須創建遠程"origin"的"dev分支"到本地。
輸入命令$(創建本地"dev分支")git checkout -b dev origin/dev
接下來,路人A可以在"dev分支"上繼續修改,然后,時不時地把"dev分支"push到遠程。
輸入命令$(創建本地"dev分支")git commit -m "add /usr/bin/env"
當路人A和你一起修改了同樣的文件并推送到"orgin",后提交的小伙伴會推送失敗,因為兩個提交會有沖突。
這時候,我們需要先從"origin/dev"將最新的提交git pull
下來,然后在本地合并,解決沖突再推送。
輸入命令$git pull
;
"no tracking information"說明本地分支和遠程分支的鏈接關系沒有創建
git pull
也失敗了,因為沒有創建本地"dev分支"與遠程"origin/dev分支"的鏈接,根據提示設置:
輸入命令$git branch --set-upstream dev origin/dev
;
再次輸入命令$git pull
。
合并git pull
下來的最新提交,需要手動解決合并沖突,上面有介紹過方法。解決后,再推送到遠程庫"origin/dev分支"。
<br /><br />
小結
$
git branch
#查看分支。
$git branch filename
#創建"filename分支"。
$git checkout filename
#切換"filename分支"。
$git checkout -b filename
#上面兩條的結合,創建并切換"filename分支"。
$git merge filename
#合并"filename分支"到當前分支。
$git branch -d filename
#刪除"filename分支"。
$git branch -D filename
#刪除未合并過的"filename分支"。
$git log --graph --pretty=oneline --abbrev-commit
#查看分支合并圖。
$git merge --no-ff -m "描述" 分支名
#表示用普通模式合并,合并后的歷史有分支,能看出來曾經做過合并;而fast forward合并就看不出來曾經做過合并。
$ls
#查看當前目錄內的文件。
$git remote
#查看遠程庫的信息。
$git remote -v
#查看遠程庫的顯示詳細信息。
$git push origin master
#把"master分支"的本地內容提交推送到遠程庫。
$git push origin "branch-name"
#把"xx分支"的本地內容提交推送到遠程庫。
$git pull
#把"xx分支"的本地內容提交推送到遠程庫。如果結果提示"no tracking information",說明本地分支和遠程分支的鏈接關系沒有創建,輸入命令git branch --set-upstream "branch-name" origin/"branch-name"
。
<br /><br /><br /><br /><br /><br /><br />
主要參考:
<br /><br /><br /><br />