標籤:

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,那麼86a451cc5a1cc4中所做的修改會依次重演到master。如果遇到衝突,那麼會依次需要人工解決衝突。為了避免多次修改衝突,我們將86a451cc5a1cc4合併為一次提交:

$ 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 |