深入git rebase使用

深入git rebase使用

https://baijiahao.baidu.com/s?id=1633418495146592435&wfr=spider&for=pc

 

關於Git 我們之前有很多文章介紹過相關的功能和擴展應用。我也介紹過如何在Git中自由穿梭重置redo。當然有的時候我們需要改變Git的提交歷史。Git也提交很多工具,本文蟲蟲帶領大家來實例深入學習其中的一個工具rebase。

 

準備

爲了不破壞現有的倉庫,我們首先創建一個新建一個實驗repo,所有操作都在該倉庫下操作。創建命令如下:

mkdir rebase-repo

cd rebase-repo

git init rebase-repo

git commit --allow-empty -m "init"

注意我們給git commit -m "init",增加了一個參數"--allow-empt",否則如果是一個空庫的時候會報錯,如下

 

通過實驗環境rebas-rep倉庫,任何時候出現問題搞不定了,只需刪除掉rm -rf rebase-repo/.git目錄並重新運行這些命令就可以初始化整個實驗環境。

git pull --rebase

如果遠程git服務器倉庫分支已經有了更新上,通常git pull時候將會默認執行merge合併提交。相當於執行兩個操作:

git fetch origin

git merge origin/master

實際上除了合併外還有一種方法,那就是執行rebase來同步變化,它通常更有用,git提交歷史也更清晰,rebase方法需要顯性指定--rebase參數:

git pull --rebase ,他相當執行:

git fetch origin

git rebase origin/master

合併方法更簡單,更容易理解。但是很多時候我們更需要的是rebase,我們也可以通過設置,設置rebase爲pull時候默認執行的動作:

git config --global pull.rebase true

使用git rebase改變分支依賴

當然git最初始的功能是和其字面上意義一樣,改變分支的依賴分支。假設有以下分支:

 

而且feature-2不依賴於feature-1中的任何變化,就可以rebase讓它基於master。

git checkout feature-2

git rebase master

git rebase對所有涉及的commit("pick")執行默認操作,它只是將歷史記錄回滾到最後一個公共父節點,並重新生成兩個分支的commit。git就會變成歷史現在看起來像這樣:

 

修改最近的commit

先做一個最簡單的的操作:修復最近的提交。讓我們在rebase-repo中增加一個文件,但是commit信息有問題:

echo "Hello Chongchong" > one.txt

git add one.txt

git commit -m "添加Hello"

修改commit非常簡單,只需使用"—amend"選項就可以。我們可以編輯文件並用--amend提交,如下所示:

echo 'Hello Chongchong!' > one.txt

git commit -a --amend

指定-a添加所有更改的,而--amend會將更改添加到最近一個提交中。保存並退出編輯器(vim的話wq,也可以修改提交消息)。你可以通過運行git show來看提交的信息:

 

修改歷史commit

"—amend"選項僅僅可以修改最近的一次提交。如果我們要需要修改更老的呢?我們先多創建一個提交歷史環境

echo 'Hello ' >one.txt

git add one.txt

git commit -m "添加Hello"

echo "第二個文件" > two.txt

git add two.txt

git commit -m "添加two"

現在發現one.txt少了"Chongchong!"。現在需要添加上:

echo 'Hello Chongchong!' > one.txt

git commit -a -m "添加Chongchong"

這樣既可以,但是爲了commit歷史更好看,需要把最後一個提交修改刪除最後面這次提交歷史。爲此,爲實現這個功能,我們需要使用rebase命令。下面我們使用交互式分時修改這三個提交:

git rebase -i HEAD~3

命令會在你默認的編輯器中打開最近三次的commit歷史,-i表示用交互式打開,如下所示:

 

如上圖,編輯器中顯示了最經三次的歷史,三個pick comit哈希。修改這個文件,我們可以告訴git修改歷史記錄。當我們保存推出編輯器時,git將從其歷史記錄中刪除所有這些提交,然後一次執行每一行。默認情況下,會使用(pick)每個提交,並將其添加到分支。現在我們使用fixup,修改將操作從"pick"修改爲"fixup"並在我們想要"fixup",移動到"添加two"commit的前面:

 

wq保存退出編輯器 , git會自動運行這些命令。git log看下git歷史:

 

將幾個提交合併成一個

有時候,我們需要將本地大量的提交合併爲一個,然後提交到遠程倉庫或者合併到master時,以確保整個提交歷史的清晰潔淨,這也是rebase最常用的功能之一。爲了合併提交,需要使用squash操作。我們先寫腳本實現多次提交的環境,

git checkout -b squash

先創建一個新的分支,來執行下面shell:

for i in H e l l o , ' ' C h o n g c h o n g; do

echo "$i" >>hello.txt

git add hello.txt

git commit -m "增加Hello,$i"

done

執行該腳本,通過shell for循環多次,按照多個字母提交到文件文件,每次增加一個字母,最後實現"你好,Chongchong"。複製以上腳本到shell終端執行,

 

我們使用交互式rebase執行將它們合併到一起。我們執行git rebase -i master結果:

 

先我們要將所有這些更改壓都合併爲一個commit,要實現這個目的,只需將每個"pick"操作更改爲"squash",第一行除外,如下所示:

我們使用vim批量修改命令:2:$ s/pick/squash/

 

使用wq保存並退出編輯器時,git處理,並次打開編輯器以修改最終的提交消息。顯示如下:

 

提醒我們爲該合併使用一個合適的commit消息,默認顯示了所有提交歷史的commit,我們修改爲我們需要顯示的commit消息,然後推出保存。git show顯示,提交信息如下:

 

現在我們可以將master分支rebase到squash分支,並刪除臨時的squash分支,這樣就消除了所有分支合併的過程。git rebase這時的效果和git merge一樣但是不會進行合併提交:

git checkout master

git rebase squash

git branch -D squash

將一個提交分成幾個

上面我們介紹了將多個提交合併爲一個。但是實際中也有需要將某一個比較重的提交分割成多個小提交的需求,我們此處就介紹這個。我從增加一個perl的md5檢查程序(你可以用其他任何文件來代替)來開始:

vim md5check.pl

git add md5check.pl

git commit -m "增加一個perl程序"

接下來,給文件增加代碼:

git commit -a -m "增加md5check"

git show 顯示下本地提交的內容:

 

現在我們學習如何拆分該commit:

首先啓動交互式rebase。讓我們用git rebase -i HEAD~2來修改這個提交,顯示:

 

我們把第二個條指令從"pick"更改爲"edit",然後wq保存並退出vim。Git會顯示:

 

我們可以按照上面的說明給該次提交添加更改, 在此我們執行git reset HEAD^來執行軟reset。將最新一次的文件狀態修改爲未提交狀態。現在運行git status,我們可以看到它取消提交最新提交併將其更改添加到工作樹:

 

爲了解決這個問題,我們換用交互式提交。它可以讓我們選擇地提交工作樹中的特定更改。運行git commit -p以啓動此過程,將看到以下提示:

 

上圖顯示有一個大段的代碼修改,我們來對該commit拆分。我們需要使用 "s"命令將大的提交拆分成更小的部分。

 

git自動分析,並將該修改分成6塊,讓我們點擊"y"修改爲分割的狀態。然後點擊"q" 完成交互式會話並繼續提交。這是會顯示未編輯界面,我們在此輸入合適commit消息。

 

wq 保存退出編輯器。 執行保存該次拆分:

git commit -a -m"增加md5_check"

最後我們私用rebase --continue完成edit操作,並繼續執行rebase。

git rebase --continue

使用git log來查看拆分結果

 

對commit重新排序

這個很容易。我們提交三個commit:

echo "one" >one.txt

git add one.txt

git commit -m "add one"

echo "two" >two.txt

git add two.txt

git commit -m "add two"

echo "three" >three.txt

git add three.txt

git commit -m "add three"

git log查看歷史:

 

現在我們想要改變下commit的歷史,以3,2,1順序顯示。運行git rebase -i HEAD~3,將會啓動編輯器,媳那是rebase的操作列表:

 

修改列表順序,如下:

 

wq保存並退出編輯器,git就會按照新的順序重新生成commit歷史。

 

解決rebase衝突

有時你在做一個rebase時會遇到合併衝突,解決方法和其他時候衝突解決方法也一樣。git也會對受影響的文件設置衝突標記,可以用git status顯示需要解決的衝突行,使用git add或git rm將文件標記爲添加。但是在使用git rebase情況下,我們需要注意的是:完成衝突解決的方法不同,在解決git merge引起的衝突時是用的是commit,而在rebase時候用的是git rebase --continue,也可以使用git rebase --skip忽略此次最該的提交,這樣就不會包含在rebase中。

總結

本文我們深入了git rebase的各種用法,善用git rebase可以讓我們的提交歷史變得更加優雅,雖然他不是一個必須的,但是對一個處女座的碼農來說,rebase是必不可少的神器。

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章