【五】分支管理
分支管理
- 1. 創建與合并分支
- 2. 解決沖突
- 3. 分支管理策略
- 4. Bug分支
- 5. Feature分支
- 6. 多人協作
- 推送分支
- 抓取分支
- 7. Rebase
1. 創建與合并分支
在版本回退里,你已經知道,每次提交,Git都把它們串成一條時間線,這條時間線就是一個分支。截止到目前,只有一條時間線,在Git里,這個分支叫主分支,即master分支。HEAD嚴格來說不是指向提交,而是指向master,master才是指向提交的,所以,HEAD指向的就是當前分支。
簡單的說就是Head指向當前分支(比如master),分支指向最新的提交。
一開始的時候,master分支是一條線,Git用master指向最新的提交,再用HEAD指向master,就能確定當前分支,以及當前分支的提交點:
每次提交,master分支都會向前移動一步,這樣,隨著你不斷提交,master分支的線也越來越長。
當我們創建新的分支,例如dev時,Git新建了一個指針叫dev,指向master相同的提交,再把HEAD指向dev,就表示當前分支在dev上:
假如我們在dev上的工作完成了,就可以把dev合并到master上。Git怎么合并呢?最簡單的方法,就是直接把master指向dev的當前提交,就完成了合并:
所以Git合并分支也很快!就改改指針,工作區內容也不變!
合并完分支后,甚至可以刪除dev分支。刪除dev分支就是把dev指針給刪掉,刪掉后,我們就剩下了一條master分支:
開始實戰
-
第一步,使用git checkout -b dev創建并切換到dev分支
-b參數是表示創建并切換,相當于git branch dev和git checkout dev兩條命令
-
第二步,用git branch查看當前分支
git branch能列出所有的分支,當前分支前有個*號。 -
第三步,修改readme.txt文件,并在dev分支提交
查看當前readme.txt文件內容:
-
第四步,切換回master分支,再查看readme.txt文件:
額。。。發現dev分支新增的最后一行沒有了,現在是這樣的:
-
第五步,使用git merge dev合并dev分支到master分支,再查看文件內容
果然合并成功了,git merge命令用于合并指定分支到當前分支。注意到上面的Fast-forward信息,Git告訴我們,這次合并是“快進模式”,也就是直接把master指向dev的當前提交,所以合并速度非常快。當然,也不是每次合并都能Fast-forward,我們后面會講其他方式的合并。 -
第六步,使用git branch -d dev刪除dev分支
因為創建、合并和刪除分支非常快,所以Git鼓勵你使用分支完成某個任務,合并后再刪掉分支,這和直接在master分支上工作效果是一樣的,但過程更安全。
switch
switch也是可以創建并切換分支的,因為舊版本git checkout -- <file>是用來撤銷修改的,為了不沖突或者記混了,建議使用新版的switch來切換分支:
# 創建并切換到dev分支 git switch -c dev # 切換到master分支 git switch master2. 解決沖突
事故現場
修改最后一行內容為Creating a new branch is quick AND simple.(加了AND simple)
修改最后一行內容為Creating a new branch is quick & simple.(加了& simple)
現在,master分支和feature1分支各自都分別有新的提交,變成了這樣:
這種情況下,Git無法執行“快速合并”,只能試圖把各自的修改合并起來,但這種合并就可能會有沖突。
果然沖突了!Git告訴我們,readme.txt文件存在沖突,必須手動解決沖突后再提交。git status也可以告訴我們沖突的文件:
我們看下現在readme.txt的內容:
Git用<<<<<<<,=======,>>>>>>>標記出不同分支的內容。
其實現在的feature1分支的文件還是原來的,合并后就沒有用了,可以直接刪除這個分支了。
3. 分支管理策略
通常,合并分支時,如果可能,Git會用Fast forward模式,但這種模式下,刪除分支后,會丟掉分支信息。
如果要強制禁用Fast forward模式,Git就會在merge時生成一個新的commit節點,這樣,從分支歷史上就可以看出分支信息。
下面我們實戰一下--no-ff方式的git merge:
首先,仍然創建并切換dev分支,修改readme.txt文件,并提交;
然后切換回master分支,使用--no-ff參數合并;
最后查看git log分支歷史。
可以看到,不使用Fast forward模式,merge后就像這樣:
分支策略
在實際開發中,我們應該按照幾個基本原則進行分支管理:
首先,master分支應該是非常穩定的,也就是僅用來發布新版本,平時不能在上面干活;
那在哪干活呢?干活都在dev分支上,也就是說,dev分支是不穩定的,到某個時候,比如1.0版本發布時,再把dev分支合并到master上,在master分支發布1.0版本;
你和你的小伙伴們每個人都在dev分支上干活,每個人都有自己的分支,時不時地往dev分支上合并就可以了。
所以,團隊合作的分支看起來就像這樣:
4. Bug分支
正常開發中,八阿哥(Bug)總是少不了的,在Git中,由于分支是如此的強大,所以,每個bug都可以通過一個新的臨時分支來修復,修復后,合并分支,然后將臨時分支刪除。
場景:當你接到一個修復一個代號101的bug的任務時,很自然地,你想創建一個分支issue-101來修復它,但是,等等,當前正在dev上進行的工作還沒有提交(例如新增了一個文件和修改了一個文件):
如果你不想提交以上文件,因為還沒有開發完,但是這個bug又很緊急,那怎么辦呢?
幸好,Git還提供了一個stash功能,可以把當前工作現場“儲藏”起來,等以后恢復現場后繼續工作,使用git stash來存儲當前的修改:
為啥存儲了,git status還能看到新增的文件呢?這是因為沒有在git 版本控制中的文件(不在暫存區),是不能被git stash 存起來的,若要一起保存,可以先add再一起保存:
如此,工作區就是clean狀態了,接下來就是開始處理bug了。
首先確定要在哪個分支上修復bug,假定需要在master分支上修復,就從master創建臨時分支issue-101:
然后開始修復bug,修改之后提交,提交后切換到master分支并完成合并,最后刪除issue-101分支:
bug修復了,現在準備切回dev分支繼續干活了:
git stash list可以查看保存的工作現場列表,git stash pop可以恢復工作現場,同時把stash內容也刪了;還有一種是用git stash apply恢復,但是恢復后,stash內容并不刪除,你需要用git stash drop來刪除。
在master分支上修復了bug后,我們要想一想,dev分支是早期從master分支分出來的,所以,這個bug其實在當前dev分支上也存在。那么簡單的解決辦法是怎么做呢?
git cherry-pick 可以復制一個特定的提交到當前分支,只需要知道commit id就行了,我們先切換到master分支,查看fix bug的commit id,然后到dev分支執行cherry-pick:
此時fix bug的代碼已經合并到了dev分支了,而且會新建一個提交節點。
5. Feature分支
軟件開發中,總有無窮無盡的新的功能要不斷添加進來。添加一個新功能時,你肯定不希望因為一些實驗性質的代碼,把主分支搞亂了,所以,每添加一個新功能,最好新建一個feature分支,在上面開發,完成后,合并,最后,刪除該feature分支。
場景:新建分支feature-new開發新功能,還沒有merge,新功能取消,需要刪除
當需求取消時,切換到dev分支,刪除新分支:
Git友情提醒,feature-new分支還沒有被合并,如果刪除,將丟失掉修改,如果要強行刪除,需要使用大寫的-D參數。
終于刪除成功了。
6. 多人協作
當你從遠程倉庫克隆時,實際上Git自動把本地的master分支和遠程的master分支對應起來了,并且,遠程倉庫的默認名稱是origin。
要查看遠程庫的信息,用git remote,用git remote -v顯示更詳細的信息:
上面顯示了可以抓取和推送的origin的地址。如果沒有推送權限,就看不到push的地址。
推送分支
推送分支,就是把該分支上的所有本地提交推送到遠程庫。推送時,要指定本地分支,這樣,Git就會把該分支推送到遠程庫對應的遠程分支上:
git push origin master如果要推送其他分支,比如dev,就改成:
git push origin dev但是,并不是一定要把本地分支往遠程推送,那么,哪些分支需要推送,哪些不需要呢?
- master分支是主分支,因此要時刻與遠程同步;
- dev分支是開發分支,團隊所有成員都需要在上面工作,所以也需要與遠程同步;
- bug分支只用于在本地修復bug,就沒必要推到遠程了,除非老板要看看你每周到底修復了幾個bug;
- feature分支是否推到遠程,取決于你是否和你的小伙伴合作在上面開發。
總之,就是在Git中,分支完全可以在本地自己藏著玩,是否推送,視你的心情而定!
抓取分支
多人協作時,大家都會往master和dev分支上推送各自的修改。
現在,模擬一個你的小伙伴,可以在另一臺電腦(注意要把SSH Key添加到GitHub)或者同一臺電腦的另一個目錄下克隆:git clone git@gitee.com:zehpyr/learngit.git
當你的小伙伴從遠程庫clone時,默認情況下,你的小伙伴只能看到本地的master分支。現在,你的小伙伴要在dev分支上開發,就必須創建遠程origin的dev分支到本地,于是他用這個命令創建本地dev分支:git checkout -b dev origin/dev,現在,他就可以在dev上繼續修改,然后,時不時地把dev分支push到遠程:git push origin dev。
如果此時你也在push相同文件,會發現推送失敗,因為你的小伙伴的最新提交和你試圖推送的提交有沖突,解決辦法也很簡單,Git已經提示我們,先用git pull把最新的提交從origin/dev抓下來,然后,在本地合并,解決沖突,再推送;如果git pull失敗了,原因是沒有指定本地dev分支與遠程origin/dev分支的鏈接,根據提示,設置dev和origin/dev的鏈接:git branch --set-upstream-to=origin/dev dev。pull成功后,解決完沖突,再commit,然后push。
多人協作的工作模式通常是這樣:
如果git pull提示no tracking information,則說明本地分支和遠程分支的鏈接關系沒有創建,用命令git branch --set-upstream-to <branch-name> origin/<branch-name>。
這就是多人協作的工作模式,一旦熟悉了,就非常簡單。
7. Rebase
- rebase操作可以把本地未push的分叉提交歷史整理成直線;
- rebase的目的是使得我們在查看歷史提交的變化時更容易,因為分叉的提交需要三方對比。
總結
- 上一篇: 【四】Java流程控制
- 下一篇: java ssh优势_java框架组合s