git的fast-forward在之前的文章有介紹過,但是介紹的不細:
http://www.cnblogs.com/charlesblc/p/5953066.html
fast-forward方式就是當條件允許的時候,git直接把HEAD指針指向合並分支的頭,完成合並。屬於“快進方式”,不過這種情況如果刪除分支,則會丟失分支信息。
因為在這個過程中沒有創建commit squash 是用來把一些不必要commit進行壓縮,比如說,你的feature在開發的時候寫的commit很亂,那么我們合並的時候不希望把這些歷史commit帶過來,
於是使用--squash進行合並,此時文件已經同合並后一樣了,但不移動HEAD,不提交。需要進行一次額外的commit來“總結”一下,然后完成最終的合並。 --no-ff指的是強行關閉fast-forward方式。
有這篇文章詳細復習一下 (Link)
通常,合並分支時,如果可能,Git會用Fast forward
模式,但這種模式下,刪除分支后,會丟掉分支信息。
如果要強制禁用Fast forward
模式,Git就會在merge時生成一個新的commit,這樣,從分支歷史上就可以看出分支信息。
實戰一下--no-ff
方式的git merge
:
首先,仍然創建並切換dev
分支:
$ git checkout -b dev Switched to a new branch 'dev'
修改readme.txt文件,並提交一個新的commit:
$ git add readme.txt $ git commit -m "add merge" [dev 6224937] add merge 1 file changed, 1 insertion(+)
現在,我們切換回master
:
$ git checkout master
Switched to branch 'master'
准備合並dev
分支,請注意--no-ff
參數,表示禁用Fast forward
:
$ git merge --no-ff -m "merge with no-ff" dev Merge made by the 'recursive' strategy. readme.txt | 1 + 1 file changed, 1 insertion(+)
因為本次合並要創建一個新的commit,所以加上-m
參數,把commit描述寫進去。
合並后,我們用git log
看看分支歷史:
$ git log --graph --pretty=oneline --abbrev-commit * 7825a50 merge with no-ff |\ | * 6224937 add merge |/ * 59bc1cb conflict fixed ...
可以看到,不使用Fast forward
模式,merge后就像這樣:
關於默認的fast-forward的,上面引文沒有詳述。基本就是看不出有從其他分支合並過來的信息,只能看到每個commit實際的信息。如果其他分支丟失了,分支合並的信息就丟失了。
我自己試了一下 默認的有fast-forward的情況。如下:
$ git checkout -b testff Switched to a new branch 'testff' $ vi readme $ git add readme $ git commit readme test ff # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # Explicit paths specified without -i or -o; assuming --only paths... # On branch testff # Changes to be committed: # new file: readme #
... ".git/COMMIT_EDITMSG" [converted] 8L, 282C written [testff 5a036ee] test ff 1 file changed, 1 insertion(+) create mode 100644 readme $ git checkout -b newtestff Switched to a new branch 'newtestff' $ git merge testff Already up-to-date. $ git diff testff newtestff $ git checkout master Switched to branch 'master' Your branch is up-to-date with 'origin/master'. $ git pull $ git checkout -b newff Switched to a new branch 'newff' $ git checkout newff Already on 'newff' $ git merge testff Updating 30a974d..5a036ee Fast-forward readme | 1 + 1 file changed, 1 insertion(+) create mode 100644 readme $ git log --graph --pretty=oneline --abbrev-commit * 5a036ee test ff * 30a974d Merge branch 'xxx' into master |\ ...
重點看兩點:
1. 第一處飄黃的地方,是在test-ff版本 checkout -b的,結果發現git 兩個branch完全沒有差別。
git checkout -b dev命令相當於
創建分支: git branch dev 切換分支: git checkout dev
而這個創建是基於當前HEAD的。
所以新創建的分支和test-ff沒有區別。
2. 采用默認的merge之后,使用git log --graph --pretty=oneline --abbrev-commit 能夠看到:
* 5a036ee test ff
完全沒有原來 test-ff 分支的信息。
另,git log命令加上后面的參數很好用,--graph --pretty=oneline --abbrev-commit
比原始的輸出好看多了。
分支策略
在實際開發中,我們應該按照幾個基本原則進行分支管理:
首先,master
分支應該是非常穩定的,也就是僅用來發布新版本,平時不能在上面干活;
那在哪干活呢?干活都在dev
分支上,也就是說,dev
分支是不穩定的,到某個時候,比如1.0版本發布時,再把dev
分支合並到master
上,在master
分支發布1.0版本;
你和你的小伙伴們每個人都在dev
分支上干活,每個人都有自己的分支,時不時地往dev
分支上合並就可以了。
所以,團隊合作的分支看起來就像這樣:
小結
Git分支十分強大,在團隊開發中應該充分應用。
合並分支時,加上--no-ff
參數就可以用普通模式合並,合並后的歷史有分支,能看出來曾經做過合並,而fast forward
合並就看不出來曾經做過合並。
一些git命令:
git checkout -b dev//基於本地創建分支 git checkout -b dev origin/dev //基於遠程分支創建本地分支 可以看到git checkout -b命令相當於 創建分支: git branch dev切換分支: git checkout dev 是基於當前HEAD的 刪除本地分支 git branch -D dev 刪除遠程分支 git push origin :branch-name 冒號后面沒有空格
下面再對這些內容做一下復習:
http://www.ruanyifeng.com/blog/2015/12/git-workflow.html
http://www.ruanyifeng.com/blog/2015/12/git-cheat-sheet.html
http://www.ruanyifeng.com/blog/2015/08/git-use-process.html
http://www.ruanyifeng.com/blog/2014/06/git_remote.html