git rebase,顧名思義,就是重新定義(re)起點(base)的作用,即重新定義分支的版本庫狀態。要搞清楚這個東西,要先看看版本庫狀態切換的兩種情況:
- 我們知道,在某個分支上,我們可以通過git reset,實現將當前分支切換到本分支以前的任何一個版本狀態,即所謂的“回溯”。即實現了本分支的“後悔藥”。也即版本控制系統的初衷。
- 還有另一種情況,當我們的項目有多個分支的時候。我們除了在本地開發的時候可能會“回溯”外,也常常會將和自己並行開發的別人的分支修改添加到自 己本地來。這種情況下很常見。作為專案系統管理員,肯定會不斷的合并各個子項目的補丁,並將最新版本推送到公用版本庫,而作為開發人員之一,提交自己的補丁之 後,往往需要將自己的工作更新到最新的版本庫,也就是說把別的分支的工作包含進來。
舉個例子來說吧!假設我們的項目初期只有一個master分支,然後分支上作過兩次提交。這個時候系統只有一個master分支,他的分支曆史如下:
master0(初始化後的版本)
||
v
master1(第一次提交後的版本)
||
v
master2(第二次提交後的版本)
這個時候,我們可以通過git reset將master分支(工作目錄、工作緩衝或者是版本庫)切換到master1或者master0版本,這就是前面所說的第一種情況。
假設我們這裡把master分支通過git reset回溯到了master1狀態。那麼這個時候系統仍然只有一個master分支,分支的曆史如下:
master0(初始化後的版本)
||
v
master1(第一次提交後的版本)
然後,我們在這裡以master1為起點,建立了另一個分支test。那麼對於test分支來說,他的第一個版本test0就和master1是同一個版本,此時項目的分支曆史如下:
master0(初始化後的版本)
||
v
master1(第一次提交後的版本)===test0(test分支,初始化自master分支master1狀態)
這個時候,我們分別對master分支、test分支作兩次提交,此時版本庫應該成了這個樣子:
master0(初始化後的版本)
||
v
master1===test0==>test1===>test2
||
v
master2===>master3
- 這個時候,通過第一種git reset的方式,可以將master分支的目前狀態(master3)回溯到master分支的master0、master1、master2狀態。 也可已將test分支目前狀態(test2)回溯到test分支的test0、test1狀態,以及test分支的父分支master的master0、 master1狀態。
- 那麼。如果我要讓test分支從test0到test2之間所有的改變都添加到master分支來,使得master分支包含test分支的所有修改。這個時候就要用到git rebase了。
首先,我們切換到master分支,然後運行下面的命令,即可實現我們的要求:
這個時候,git做了些什麼呢?
- 先將test分支的代碼checkout出來,作為工作目錄
- 然後將master分支從test分支建立起的所有改變的補丁,依次打上。如果打補丁的過程沒問題,rebase就搞定了
- 如果打補丁的時候出現了問題,就會提示你處理衝突。處理好了,可以運行git rebase –continue繼續直到完成
- 如果你不想處理,你還是有兩個選擇,一個是放棄rebase過程(運行git rebase –abort),另一個是直接用test分支的取代當前分支的(git rebase –skip)。