今天在合併分支的時候碰到了一個問題,情況是這樣的,當前開發分支 A,合併了分支 B,發現有衝突,於是就去改衝突,改好衝突後 commit。但是此時老大提醒說提醒用另一種方法可能更好。於是就想退回去,重新改改試試。其實直接 reset 就好了。不過一查看到官網有篇文章是介紹這種情況的,正好就按他說的寫一下。
文章地址:https://git-scm.com/blog/2010/03/02/undoing-merges.html
先說一下幾個 Git 的基本知識:
- Git 倉庫有三個主要組成 —— 工作目錄,緩存區和提交歷史。
- reset 將一個分支的末端指向另一個提交。
- checkout 分支切換。
- revert 撤銷一個提交的同時會創建一個新的提交。
git revert
是個安全的方法。相比git reset
他不會改變現在的提交歷史,因此git revert
可以用在公共分支上,而git reset
最好用在私人分支上。
下面說一下那篇文章介紹的撤銷 merge 的方法:
Reset a Merge:#
reset 到 merge 之前的 commit,然後重新做之後的操作,不過這要求所有的協作者知道如何處理回退的 head,如果這不是問題,或者只是本地分支,這是一個很好的解決方法。方法如下:
$ git checkout master
git reset --hard [要回退的commit的sha值]
簡單暴力,不過很好用。
Reverting a Merge:#
當 merge 以後還有別的操作和改動時,或者你的協作者在你 merge 之後又做了一些提交的時候,git 正好也有辦法能撤銷 merge。你可以使用 revert 命令。方法如下:
$ git resert -m [要撤銷的那條merge線的編號] [merge前的版本號,即sha值]
Finished one revert.
[master 88edd6d] Revert "Merge branch 'jk/post-checkout'"
1 files changed, 0 insertions(+), 2 deletions(-)
這樣會創建新的 commit 來抵消對應的 merge 操作,如果你嘗試再次合併,Git 會看到該分支上的提交是在歷史記錄中,並假設你錯誤地嘗試合併你已經有的東西。
$ git merge jk/post-checkout
Already up-to-date.
Reverting the Revert#
$ git revert [方法二撤銷merge時提交的commit的版本號,這裡是88edd6d]
Finished one revert.
[master 268e243] Revert "Revert "Merge branch 'jk/post-checkout'"" 1 files changed, 2 insertions(+), 0 deletions(-)
這樣就可以正常的 merge 了,不過這可能會產生更多的衝突。
現在基本上重新介紹了我們以前撤回的分支中的一切。現在如果我們在這個分支上有更多的工作,我們可以重新合併它。
$ git merge jk/post-checkout
Auto-merging test.txt
Merge made by recursive. test.txt | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
寫在最後#
大致的看完之後,發現後面的方法太麻煩,簡直是沒事找事。不過作者可能完全是基於在公共分支改動的比較複雜的情況,總之,感覺還是在本地分支用 reset 最方便,或者 revert 也可以,別整的那個麻煩就行了。
最後分享一篇Git Community Book中關於 git rebase 的文章,之前不太了解,感覺寫的很好:http://gitbook.liuhui998.com/4_2.html