Git 小教室「在 Merge 之前想試試看有沒有衝突?」
當你開了一個新的 branch,然後做了幾個 commit,進度做得差不多之後,下一步就是準備使用 git merge
指令來進行合併。但你手邊的專案可能有好一陣子沒跟線上的同步,這個 merge 執行下去可能噴一堆的衝突要解決。
不久前在社群分享就有朋友問到,有沒有辦法可以在進行 merge 之前先看看會不會發生衝突發生?
除了直接合併下去,衝突再解掉或是再 git reset
回來就好的方法之外, git merge
指令目前並沒有類似 git commit --dry-run
的乾跑參數。
假設想要合併分支 cat
,想做到乾跑效果可以這樣做:
$ git merge cat --no-commit --no-ff
根據 Git 的說明手冊,對於 --no-commit
參數的說明如下:
With --no-commit perform the merge but pretend the merge failed and do not autocommit, to give the user a chance to inspect and further tweak the merge result before committing.
這個參數會假裝這次的合併失敗,並且不會產生新的 commit,讓使用者有機會可以在 commit 前再做一些事。
而後面再加上 --no-ff
參數則是不希望 Git 使用 Fast Forward 方式合併,如果想了解 Fast Forward 是怎麼回事,歡迎參閱「為什麼我的分支都沒有『小耳朵』」章節。
那,就讓我們實際來操作一次:
目前專案裡有 master
跟 cat
兩個分支,cat
分支是從 master
分出去的,狀態如下:
$ git merge cat --no-commit --no-ff
Automatic merge went well; stopped before committing as requested
Good! 沒發生衝突,但也沒產生 Commit 或 Fast Forward。看一下目前的 Git 狀態:
$ git status
On branch master
All conflicts fixed but you are still merging.
(use "git commit" to conclude merge)
Changes to be committed:
new file: cat1.html
new file: cat2.html
的確就停在 Commit 之前的狀態,cat1.html
跟 cat2.html
都被放到暫存區了。
要注意的是,這個地方如果沒有加上 --no-ff
的話,雖然不會產生 Commit,但還是因為 Fast forward 而完成合併。
剛剛這個例子太順利的,沒有每天在過年的,讓我們再來看一個會衝突的例子:
在這個例子裡,payment
分支跟 member
因為剛好改到同一個檔案,所以 merge 應該會發生衝突:
$ git merge member --no-commit --no-ff
Auto-merging index.html
CONFLICT (content): Merge conflict in index.html
Automatic merge failed; fix conflicts and then commit the result.
果然發生衝突了。看一下狀態:
$ git status
On branch payment
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abort the merge)
Changes to be committed:
new file: member.html
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: index.html
回到過去
在上面這兩個範例中,git reset --merge
指令來回到合併之前的狀態,而在 Git 1.7.4 版本之後,可使用 git merge --abort
也可以跟上面這個指令一樣的效果:
$ git merge --abort
再看一下狀態:
$ git status
On branch payment
nothing to commit, working tree clean
這樣就回到合併之前的狀態了。
來看一下這個 --abort
參數的手冊說明:
The second syntax ("git merge --abort") can only be run after the merge has resulted in conflicts. git merge --abort will abort the merge process and try to reconstruct the pre-merge state.
簡單的說,如果合併沒有順利完成的話,這個參數可以讓專案會回到合併之前的狀態。
歡迎來聊聊
有任何跟 Git 有關的疑難雜症或是應用情境,都歡迎來信或留言,如果討論的篇幅夠多就會另外整理一篇文章供大家參考。