使用 git rebase 編寫清晰的提交記錄

本文使用「署名 4.0 國際 (CC BY 4.0)」 許可協議,歡迎轉載、或從新修改使用,但須要註明來源。前端

做者: 百應前端團隊 @零卡vue

文中部分素材來源網絡,若有侵權,請聯繫刪除。git

1. 爲何要使用git rebase?

你們都知道 git merge 能夠快速方便的合併兩個分支,你們在各自的分支上開發代碼,開發完成以後再合併到主幹分支,這樣雖然保證了你們的代碼不會陷入混亂,可是會形成一個問題,就是在合併一個並無上下游關係的分支時,git 會自動幫咱們生成一個 merge commit。記錄合併記錄雖然沒什麼問題,可是當咱們在頻繁合併的時候,merge commit 一多就會變的很是混亂了,舉個栗子(如下例子均爲同一個 master 分支):shell

相信當你看到這個提交記錄的時候,表情必定是這樣的:markdown

(這TM都是些啥??????)網絡

心情必定是這樣的:app

能夠看出單純使用 merge 方法,不只提交記錄不清晰,甚至連 commit 時間都是混亂的。因此,爲了解決這個使人頭大的狀況,咱們就須要用到 git rebase 了,使用了 git rebase 以後,提交記錄就會變成這樣:async

是否是瞬間感受就清晰多了!全部的改動記錄都能清晰的排列起來,閱讀的時候一眼就看的出來何時作了什麼東西,心情萬分舒暢。工具

2. 什麼是 rebase?

在介紹 rebase 以前,須要提早說明,rebase 是一個很是強大的功能,也正是由於它的強大,因此使用起來也有必定的隱患,一旦使用很差可能會對團隊的代碼形成很是大的問題。因此在使用前必定要了解其中的原理並當心謹慎的使用。oop

rebase 的功能能夠簡要的概述爲對某一條線性提交分支上的記錄進行編輯、刪除、複製、粘貼、合併。合理使用 rebase 可使團隊的提交記錄變的很是乾淨整潔。

注意:如非無可奈何不要經過 rebase 對任何已經提交到公共主幹分支上的提交記錄進行 commit!

3. 使用 rebase 替代 merge 進行主幹/開發分支合併

假設咱們在開發的時候同時拉出來兩個分支並行開發,而後有一條已經合併到主幹分支 main 了,像這樣:

這個時候咱們想要把主幹分支 main 的代碼再合併到當前開發分支 test-1,而後再進行提交,若是使用merge 會是這樣:

若是當前分支有不少的子分支,到最後合併的時候就會出現像一開始那張圖同樣爆炸的狀況。

而若是使用 git rebase main (或者 git pull --rebase origin main)合併 main 分支,提交記錄就會變成這樣:

清晰明瞭。

注:使用rebase合併主幹分支時,當前分支所作的修改永遠會被認爲是最新的,因此會致使在提交記錄上就算 test-1 分支一開始的提交時間在 test-2 以前,可是 rebase 以後 commit 記錄也是最新的,這也是rebase的初衷之一,更清晰的顯示出來在何時提交到主幹的什麼功能(由於按照提交時間來看,test-1分支的功能是在 test-2 分支功能合併到主幹 main 分支後添加的)。⚠️ 正是由於它改變了歷史,因此咱們更應該謹慎使用

固然,若是該分支是測試環境或者預發環境分支,則通常須要使用git merge來合併。由於在這兩個分支上會存在多個分支可是並無合併到主幹的修改。

再看一種狀況:

如圖所示,test-1-1 分支實際上是從 test-1 分支的 commit-1-3 節點拉取出來的,而此時 test-1分支並無合併到主幹 main 分支,可是 main 分支上的功能要提早合併到test-1-1分支上,合併完成以後將 test-1-1test-1 獨立,變成兩個互不相干的分支,這種狀況下可使用 git rebase --onto main test-1 test-1-1

能夠看到這種狀況下 test-1-1test-1 已經互相獨立互不相干了,並且 test-1-1 的記錄線已經跟 main 在同一條線上了 * *不過在正常開發狀況下應該避免這種狀況發生,由於test-1-1中已經包含了一部分的 test-1 變動,因此當 test-1 分支再合併主幹的時候,可能會有許多衝突

咱們在使用 git rebasegit pull --rebase 合併的時候可能會有許多衝突

在發生衝突時,git rebase將中止在第一個有問題提交,並在樹上留下衝突標記。咱們可使用git diff定位標記(<<<<<<),並進行編輯以解決衝突。

對於編輯的每一個文件,須要告訴 Git 衝突已解決,一般使用git add <filename>手動解決衝突並更新到對應的索引,

以後,咱們能夠手動進行下一步進程 git rebase --continue

咱們也能夠手動撤銷rebase git rebase --abort

4. 使用 rebase 編輯 commit

rebase 最經典的功能,就是編輯 commit。好比在 pull requests(gitlab爲merge request)中須要修改代碼的時候,須要把修改的內容合併到已經提交的commit上。

這裏咱們可使用 git rebase -i [startpoint] [endpoint]來編輯提交記錄,其中-i的意思是--interactive交互的意思,即彈出交互式頁面供使用者編輯。[startpoint][endpoint]指的是編輯的開始和結束節點(不包含[startpoint]節點,範圍邏輯是[startpoint] < commits <= [endpoint]),若是不指定[endpoint]則結束節點會指向HEAD所對應的節點(通常使用的時候也不指定結束節點...)。

舉個栗子:

此時咱們想編輯test-1分支的最新三條歷史記錄,咱們可使用前面所說的

git rebase -i 39ce617 或者是 git rebase -i HEAD~3,咱們會看到以下頁面:

指令說明:

p 或 pick 		使用該commit,不作修改(默認指令)
r 或 reword 	使用該commit,可是修改它的commit信息
e 或 edit 		使用該commit,可是要停下來修改(commit信息和提交內容)
s 或 squash 	使用該commit,可是將此條commit融入以前的commit
f 或 fixup 	跟squash一致,跟前一條commit合併,可是丟棄該commit的日誌消息 
x 或 exec 		運行shell命令(該行的其他部分)
b 或 break  	到此爲止(稍後繼續使用 'git rebase --continue' 進行rebase)
d 或 drop		丟棄該commit
l 或 label		使用label標記當前HEAD
t 或 reset		將HEAD重置到label標記
m 或 merge 	[-C <commit> | -c <commit>] <label> [# <oneline>]
						 使用原始合併提交的消息(或單行,若是未指定原始合併提交)建立合併提交。
             使用 -c <commit> 改寫提交消息。
複製代碼

在該頁面點擊i鍵進入編輯頁面,便可在指令模塊編輯,編輯完成後點擊esc而後輸入:wq保存並退出進入下一步操做。

通常來講,除默認的pick以外,最經常使用的就是rewordeditsquashfixup這幾個命令了,這裏就只詳細的講解以上命令。

4.1 reword

若是咱們想要修改 commit-1-5 這條commit的提交信息,只需在該條以前寫明 rreword 方法:

保存退出以後進入commit編輯頁面:

修改並保存以後,在提交記錄裏能夠看到本地 commit-1-5 記錄已經被修改爲了 commit-1-5-reword,若是後面還有分支存在修改,則使用 git rebase --continue 命令進行以後的修改,待全部commit都修改完成以後再使用 git push -f git push --force 強制推送代碼覆蓋遠端後,遠端的提交記錄就變成了:

能夠看到提交記錄已經被修改了。

4.2 edit

使用該方法以後,咱們就能夠修改想要修改的內容,修改完並執行 git add 以後,就能夠調用

git commit --amend 來修改commit的記錄內容,這裏能夠看到edit以後修改的文件是 README.md,

而後修改 commit 方式跟 reword 一致,待全部 commit 都修改完成以後,使用 git push -f 強推至遠程即可以實現記錄內容的編輯修改了。

4.3 squash

字面意思,使用 squash 是將記錄壓縮到一塊兒,通常用於一個大功能開發完成後合併提交到主幹分支上使用,這裏咱們能夠用 vue 的提交記錄舉例:

能夠看的出來 fix(types): async Component types (#11906) 記錄下合併了許多子記錄,這樣也能夠清晰的代表一個迭代的功能及開發提交記錄。

4.4 fixup

fixup 也是將代碼進行保留併合併到上一條提交記錄,惟一的區別就在於 fixup 的記錄被刪除,此方法適用於咱們在 MR 時候的 comment 修改。

注:若是咱們在 rebase 的過程當中由於一些緣由退出了終端中斷了 rebase,咱們能夠回來繼續使用git rebase --edit-todo 進行繼續編輯。

4.5 其它

其餘功能用的比較少,就很少作贅述,感興趣的能夠閱讀相關文章。

exec: paul-samuels.com/blog/2020/1…

label & reset: stackoverflow.com/questions/6…

以上就是rebase的一些基本知識了,但願這篇文章能給你們一些幫助。

5. gitlab 如何配置 rebase

Settings/General/Merge requests

參考

相關文章
相關標籤/搜索