git變基
我們已經使用過git的合併(merge)功能,與之功能類似的是rebase(變基)。
開始前請記住:不要對在你的倉庫外有副本的分支進行變基。
變基的實質是丟棄一些現有的提交,並且新建一些內容一樣但實際上不同的提交。所以如果你的分支上的內容已經被共享,進行變基之後就會有一部分現有提交被丟棄,這會給其他用戶帶來麻煩與困惑。
合併是將兩個分支的最新快照以及共同祖先進行三方合併,並且生成一個新的快照。比如下圖是將C7、C6和C4進行三方合併。
還有另外一種方法,就是變基。變基將提取C5和C6中的補丁和修改,並且將其在C7上重新作用一次,然後生成一個新的提交。
如上圖所示,在testing
分支進行變基操作到master
後,git會進行如下操作:
- 找到
testing
分支和master
分支的共同祖先,即C4。 - 收集共同祖先C4到目前提交C6的所有修改和補丁,放到臨時文件中。
- 將目前的分支
testing
指向目標基底master
。 - 在
testing
上依次應用臨時文件中所有的修改和補丁。本例中為將C5和C6的修改和補丁依次應用。 - 生成一個新的提交,即C8。
三方合併和變基生成的新提交C8
內容是一致的,不同的是提交歷史:三方合併能夠清楚地看到合併的歷史,而變基只有一條串聯的歷史。
如果你要向他人維護的項目貢獻代碼,就可以將自己的修改都變基到master
上,推送之後,維護者只需要進行快進操作。
現在讓我們實踐一下。
我們創建一條分支testing
,並且在該分支上進行兩次提交。
然後回到master
分支,進行一次提交。
再次切換到testing
分支。
提交歷史大致如下:
* c36bdf6 (master) i see you there| * c5a1cc4 (HEAD -> testing) i see you here| * 86a451c water water everywhere|/ * af05578 (origin/master) We all love git.
如果現在從testing
變基到master
,那麼86a451c
和c5a1cc4
中所做的修改會依次重演到master
。如果遇到衝突,那麼會依次需要人工解決衝突。為了避免多次修改衝突,我們將86a451c
和c5a1cc4
合併為一次提交:
$ git reset --soft af05578$ git commit -m "i see water here"[testing cf6dc96] i see water here 1 file changed, 4 insertions(+)$ git log --oneline --decorate --graph --all* cf6dc96 (HEAD -> testing) i see water here| * c36bdf6 (master) i see you there|/ * af05578 (origin/master) We all love git.
現在執行變基到master
的操作:
$ git rebase masterFirst, rewinding head to replay your work on top of it...Applying: i see water hereUsing index info to reconstruct a base tree...M README.mdFalling back to patching base and 3-way merge...Auto-merging README.mdCONFLICT (content): Merge conflict in README.mderror: Failed to merge in the changes.Patch failed at 0001 i see water hereThe copy of the patch that failed is found in: .git/rebase-apply/patchWhen you have resolved this problem, run "git rebase --continue".If you prefer to skip this patch, run "git rebase --skip" instead.To check out the original branch and stop rebasing, run "git rebase --abort".
在執行變基操作時,git提示我們README.md
有衝突,解決衝突後使用git rebase --continue
繼續執行變基操作。現在請解決衝突,將文件添加到暫存區後表示該文件衝突解決完成。解決後繼續執行變基操作:
$ git rebase --continue Applying: i see water here
git告訴我們更改已經被應用到master
分支。提交歷史如下:
* c148ffd (HEAD -> testing) i see water here* c36bdf6 (master) i see you there* af05578 (origin/master) We all love git.
可以看到,git幫我們生成了一個新的提交,並且testing
指向該提交。提價歷史變成了一條串聯的線。
最後,將master
快進到testing
即可:
$ git checkout master Switched to branch masterYour branch is ahead of origin/master by 1 commit. (use "git push" to publish your local commits)$ git merge testing Updating c36bdf6..c148ffdFast-forward README.md | 4 ++++ 1 file changed, 4 insertions(+)
推薦閱讀:
※技術培訓 | Git,你真的會用么?
※一個人寫程序,版本控制用svn還是git?
※Git算不算程序員的必備技能?
※喜歡用 Git 做的一些小事
TAG:Git |