git rebase(變基)—— Git 學習筆記 19
git rebase(變基)
認識 git rebase
假設你現在基於遠端分支"origin",建立一個叫"mywork"的分支。
$ git checkout -b mywork origin
現在我們在 mywork 分支做一些修改,生成兩個提交(C5和C6).
但是與此同時,有些人也在"origin"分支上做了一些修改並且做了提交了。
你可以用"fetch"命令把"origin"分支上的修改拉下來(但是不合並); 正如下圖,"origin"和"mywork"這兩個分支“分道揚鑣”了。
你可以用"merge"命令把"origin"分支合併到你的分支,這會生成一個合併提交(C7)。
但是,如果你不喜歡分叉與合併,你想讓"mywork"分支的歷史看起來像一條直線,那你可以用 rebase命令
$ git checkout mywork
$ git rebase origin
這會把分叉之後的"mywork"分支(C5,C6)“嫁接”到“origin”分支的頂端。如下圖:
當“mywork”分支更新之後,它會指向最後一個新建立的提交(C6’). 而那些老的提交(C5,C6)會被Git 的垃圾收集機制丟棄,如下圖:
我們可以看一下用 merge 和用 rebase 所產生的歷史的區別:
理解 git rebase
之前我們說過git cherry-pick
其實“git rebase”就是一系列的“cherry-pick”,只是這一系列的動作用一條命令(git rebase)給完成了。你完全可以通過多次手動“cherry-pick”來複制其行為(不過不太方便,更容易出現人為錯誤)。
假設你要把 topic 分支 rebase 到 master 分支上
D <-- topic(*)
|
| C <-- master
B |
|/
|
A
你會執行命令:
git checkout topic
git rebase master
在上面的上下文中,“git rebase master”這條命令的潛臺詞是:
-
git checkout master # 切換到master分支
-
git checkout -b topic_rebased # 基於master分支建立並切換一個新分支,比如叫 topic_rebased
-
for each commit C in master…topic # 對於在topic分支且不在master分支的每個提交 C
git cherry-pick C # 揀選 C 到 topic_rebased 分支
-
忘記"topic" 的過去, 把 topic_rebased 改名為"topic"
過程如下圖:
D <-- topic(*)
|
| C <-- master
B |
|/
|
A
D <-- topic
|
| C <-- master, <--topic_rebased(*)
B |
|/
|
A
B' <-- topic_rebased(*)
D |
| |
| C <-- master
B /
|/
|
A
D' <-- topic_rebased(*)
|
B'
D |
| |
| C <-- master
B /
|/
|
A
D' <-- topic(*)
|
B'
|
C <-- master
|
A
在 rebase 的過程中,也許會出現衝突 (conflict)。如果遇到衝突,Git 會停止 rebase,並讓你去解決衝突;在解決完衝突後,可以用"git-add"命令去標記此衝突已經解決。 然後,你無需執行 git commit
,只要執行:
$ git rebase --continue
這樣 git 會繼續應用餘下的補丁。
如果你rebase到一半,突然後悔了,你可以用--abort
引數來終止 rebase,並且"mywork" 分支會回到 rebase 開始前的狀態。
$ git rebase --abort
----請各位磚家斧正----
【完】