預設情況下合併分支常常直接使用 git merge
命令,是最方便快速的合併方法.其實這種情況下 git
採用的是 fast forward
模式,特點是刪除分支後,會丟失分支資訊,好像從來沒存在該分支一樣,而我們推薦的是recursive
模式,能夠保留分支的版本記錄.
遞迴模式(recursive
)
建立並切換 dev
分支,提交版本後切換回 master
分支,然後再合併 dev
分支,這不過這一次不再使用 git merge dev
命令:
# 建立並切換 dev 分支
$ git checkout -b dev
Switched to a new branch 'dev'
# 提交版本
$ echo "git checkout -b dev" >> test.txt
$ git add test.txt
$ git commit -m "git checkout -b dev"
[dev 44d68f6] git checkout -b dev
1 file changed, 1 insertion(+)
# 切換回 master 分支
$ git checkout master
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 6 commits.
(use "git push" to publish your local commits)
$
複製程式碼
現在新增 --no-ff
引數禁用 fast forward
模式,即git merge --no-ff
:
$ git merge --no-ff -m "git merge --no-ff dev" dev
Merge made by the 'recursive' strategy.
test.txt | 1 +
1 file changed, 1 insertion(+)
$
複製程式碼
上述內容顯示,這次使用的不再是 fast forward
模式,而是 recursive
模式,那讓我們看一下提交歷史有什麼不同吧!
$ git log --pretty=oneline --graph
* 22fbef7 (HEAD -> master) git merge --no-ff dev
|\
| * 44d68f6(dev) git checkout -b dev
|/
* 3b8f434 fix conflict
|\
| * 0fe95f8 git commit c2
* | 0949cc3 git commit c3
|/
* 5c482cd git commit c1
* 413a4d1 see https://snowdreams1006.github.io/git/usage/branch-overview.html
* 9c30e51 learn git branch
* b3d8193 (origin/master, origin/HEAD) see https://snowdreams1006.github.io/git/usage/remote-repository.html
* 8e62564 add test.txt
* 9b196aa Initial commit
$
複製程式碼
這種遞迴模式(recursive
) 有一個明顯的特點就是會產生一個新的 commit
,並不會像之前快速前進模式(fast forward
)那樣單純更改 HEAD
的指向.
秉承著閱後即焚的習慣,分支一旦合併後就立即刪除,現在刪除 dev
分支,看一下會發生什麼:
# 刪除 dev 分支
$ git branch -d dev
Deleted branch dev (was 44d68f6).
# 檢視提交歷史
$ git log --pretty=oneline --graph
* 22fbef7 (HEAD -> master) git merge --no-ff dev
|\
| * 44d68f6 git checkout -b dev
|/
* 3b8f434 fix conflict
|\
| * 0fe95f8 git commit c2
* | 0949cc3 git commit c3
|/
* 5c482cd git commit c1
* 413a4d1 see https://snowdreams1006.github.io/git/usage/branch-overview.html
* 9c30e50 learn git branch
* b3d8193 (origin/master, origin/HEAD) see https://snowdreams1006.github.io/git/usage/remote-repository.html
* 8e62564 add test.txt
* 9b196aa Initial commit
$
複製程式碼
由此可見,刪除 dev
分支後僅僅少了 dev
的引用而已,原來 dev
分支所做的更改全部保留下來了!
快速前進模式(fast forward
)
建立並切換 dev
分支,提交版本後切換回 master
分支,然後再合併 dev
分支,使用 git merge dev
命令:
# 建立並切換 dev 分支
$ git checkout -b dev
Switched to a new branch 'dev'
# 提交版本
$ echo "fast forward" >> test.txt
$ git add test.txt
$ git commit -m "fast forward"
[dev 3fe94c0] fast forward
1 file changed, 1 insertion(+)
$
複製程式碼
現在切換回 master
分支,採用預設的git merge
命令合併 dev
分支:
$ git checkout master
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 8 commits.
(use "git push" to publish your local commits)
sunpodeMacBook-Pro:git-demo sunpo$ git merge dev
Updating 22fbef7..3fe94c0
Fast-forward
test.txt | 1 +
1 file changed, 1 insertion(+)
$
複製程式碼
上述內容顯示這次合併採用的是快速前進模式(fast forward
),讓我們看一下提交歷史:
$ git log --pretty=oneline --graph
* 3fe94c0 (HEAD -> master, dev) fast forward
* 22fbef7 git merge --no-ff dev
|\
| * 44d68f6 git checkout -b dev
|/
* 3b8f434 fix conflict
|\
| * 0fe95f8 git commit c2
* | 0949cc3 git commit c3
|/
* 5c482cd git commit c1
* 413a4d1 see https://snowdreams1006.github.io/git/usage/branch-overview.html
* 9c30e50 learn git branch
* b3d8193 (origin/master, origin/HEAD) see https://snowdreams1006.github.io/git/usage/remote-repository.html
* 8e62564 add test.txt
* 9b196aa Initial commit
$
複製程式碼
上述內容表明,此次合併並沒有產生新的 commit
,只是更改下 HEAD
指向而已(HEAD -> master, dev
).
同樣,現在刪除 dev
分支,再看一下提交歷史:
# 刪除 dev 分支
$ git branch -d dev
Deleted branch dev (was 3fe94c0).
# 檢視提交歷史
$ git log --pretty=oneline --graph
* 3fe94c0 (HEAD -> master) fast forward
* 22fbef7 git merge --no-ff dev
|\
| * 44d68f6 git checkout -b dev
|/
* 3b8f434 fix conflict
|\
| * 0fe95f8 git commit c2
* | 0949cc3 git commit c3
|/
* 5c482cd git commit c1
* 413a4d1 see https://snowdreams1006.github.io/git/usage/branch-overview.html
* 9c30e50 learn git branch
* b3d8193 (origin/master, origin/HEAD) see https://snowdreams1006.github.io/git/usage/remote-repository.html
* 8e62564 add test.txt
* 9b196aa Initial commit
$
複製程式碼
由此可見,快速前進模式一旦刪除分支後就徹底丟失了分支的資訊,即便是從提交歷史中也找不到曾經存在的痕跡!
分支策略
git
是分散式版本控制系統,同時鼓勵大量使用分支,如此一來大量的分支該如何管理?
實際開發中,建議準從以下原則進行分支管理:
master
分支作為主幹分支,負責對外提供服務,要求穩定可靠,因為應該專人負責更新維護.dev
分支作為開發分支,取代master
分支的開發地位,積累到一定產出時再合併到master
分支.feature
分支作為新功能分支,根據實際情況動態建立,刪除分支,並適時合併到dev
分支.bugFixed
分支作為修復特定 bug 分支,可能由master
分支衍生而來,也可能由dev
分支衍生等等,修復後及時合併到原分支.custom
自定義分支,專案成員私有分支,由上級領導分配任務後各開發人員自行選擇建立自己的分支,並根據實際情況決定合併到dev
分支或feature
等分支.
小結
- 快速前進模式(
git merge <name>
)不保留分支合併歷史,遞迴模式(git merge --no-ff -m <remark> <name>
)保留分支合併歷史. - 制定大家都認同的分支管理原則,並嚴格準守規則.