Gitrebase黑魔法之打造完美的線性歷史

NO IMAGE

寫在前面

到現在,相信大家都已經能夠使用 Git 做日常的項目管理了,今天給大家介紹的是 Git 的黑魔法 rebase 命令。

rebase 黑魔法和 merge 本質上做的是一個事情,都是分支歷史的合併。不會這個技能對你的日常沒有什麼影響,但是 GET 這個技能之後會讓你帥氣值加10分。

現在,您是否 Get 這個黑魔法呢?

好的,以下不是一篇博客,而是一篇黑魔法教習大全。

rebase 是一個有故事的命令

如果上一篇 cherry-pick 翻譯為挑草莓,是一個美好的童話,rebase 的翻譯就是一出大型的人性倫理記錄片,因為它的中文翻譯是 變基 。嗯,這個命令真是生來就擁有故事。

以上,不是開玩笑,rebase 的意思真的是變基,只不過,改變的不是某種取向,而是 commit 的基礎提交,也就是它的父提交。

我第一次看也不理解,沒關係,先來個小例子平靜先,如下圖所示,有兩個分支,develop 和 feature,兩個分支都有了各自的提交。

Gitrebase黑魔法之打造完美的線性歷史

在見識到 rebase 的處女秀之前,來讓我們溫故而知一下,動動小手畫一下普通的分支合併的示意圖。嗯,這是一個很明顯的策略式合併,會產生一個新的合併提交,如圖:

Gitrebase黑魔法之打造完美的線性歷史

溫故完畢,現在開始 rebase 變基的黑魔法,請瞪大你的眼睛,擦亮你的眼鏡兒。

Gitrebase黑魔法之打造完美的線性歷史

咦?!!此刻,是否感覺有點懵懵噠?

這個乍一看,有點像快進式合併,但不是,因為上面我們說了,很明顯是要策略合併的。那這是什麼呢,就是 變基 !從圖中看到,C3 的基提交由 C1 變成了 C2。

rebase 打造線性的提交歷史

上例中,你可能不明所以,但肯定能感受到的是,reabse 操作後的分支示意圖是很簡潔的一條線,非常直,沒有分叉,這是我們說的線性的提交歷史。

簡潔的線性的歷史,是很多人喜歡用 rebase 的原因。現在我們用小 Demo 實戰一下上例中的操作,感受更深刻。

  1. 創建一個空文件夾 GitDemo,git init初始化。
  2. 隨便創建一個文件,完成初次提交,創建 master 分支。
  3. 基於初次提交創建並切換 develop 分支,然後創建兩個提交。
  4. 切換會 master 分支,再創建一個提交。

這樣就會構建上例中的分支模型了,具體命令如下:

// 切換到GitDemo目錄下,並初始化Git
cd .../GitDemo  
git init  
//創建初次提交,創建 master 分支
touch rebase.txt
git add .
git commit -m '創建 reabse.txt 文件,初次提交'  
//創建並切換到 develop 分支,創建提交“develop1”
git checkout -b develop
touch develop1.txt
git add .
git commit -m "創建 develop1.txt 文件"
//創建並切換到 develop 分支,創建提交“develop2”
touch develop2.txt
git add .
git commit -m "創建 develop2.txt 文件"
//切換到 master 分支 創建提交“master1”
touch master1.txt
git add .
git commit -m "創建 master1.txt 文件"

rebase 操作的思想上分為兩個步驟:

  1. 確定變基對象:就是你改變的是哪個分支的提交,然後 checkout 到此分支。
  2. 選好 base :選好作為基點的提交,形象地來說,就是你要變到那條線上。
  3. 開始 re :rebase 基提交。

我現在要把 develop 合併到 master 上,所以要改變的是 feature 的提交,選擇的基提交是 master 的最新提交,於是命令如下:

git checkout develop
git rebase master

Gitrebase黑魔法之打造完美的線性歷史

rebase 操作執行成功,現在 develop 分支指向的變基的最新提交,但是 master 分支的指針不變,仍然指向“master1 提交”,所以,如果需要,使用git merge master develop快進式合併一下,移動 master 的指針指向最新的提交。

以上,通過 rebase 打造線性歷史作戰成功。

rebase 的兩個細節

來看下 rebase 前後的 develop 的分支歷史,如下圖,左側是 rebase 前,右側是 rebase 後。

Gitrebase黑魔法之打造完美的線性歷史

注意上圖標識箭頭的地方,對比後你會得到兩個結論

  • rebase 為每一個變基後的提交都創建了一個內容相同新的提交。
    develop 的兩個變基提交 創建 develop1.txt 文件創建 develop2.txt 文件的 SHA1 值都發生的變化,都是新創建的提交。變基前的提交已經被丟棄,已經被回收或者正在等待回收。

  • 變基後的提交會依次排到 master 分支的後面。
    注意到創建 master1.txt 文件 這個提交的時間是比 develop 分支的兩個提交要晚的,如果是 merge 操作的話,分支的歷史,會根據時間把 創建 master1.txt 文件 放在 develop 兩個提交的後面。但 rebase 操作會所有變基的對象會直接整個排到基礎提交的末端,不會讓分支歷史混亂。(關於 merge 的提交合並,你平時可以觀察一下,是不是)

rebase 的唯一法則

rebase 使用起來非常神奇,但我們要有底線,這個底線就是:

不要對在你的倉庫外有副本的分支執行變基。

這句話的直白意思,就是不要對已經推送到遠程的分支,做變基操作。想象一下,如果你的同事小明在 develop 分支上做了新的提交,你卻把 develop 分支給變基了,小明基於的提交讓你給變沒了,你說小明會不會打死你?

所以,不要對在你的倉庫外有副本的分支執行 rebase 操作,做 rebase 操作之前腦海中都要回想一下這句話。

靈魂拷問:好好的為什麼要 rebase ?

要知道 rebase 和 merge 得到的目的是相同的,都是合併代碼。於是,讓一個人用慣了 merge 的人換成 rebase ,肯定會問“好好的,我為什麼要換?”

rebase 想較於 merge 的優點就是完美的線性歷史了。不扯什麼分支的歷史是代表項目的功能節點,還是項目真實過程的這種哲理性問題。只說,你喜歡線性歷史,你就用 rebase,不喜歡你就用 merge。

至於不知道自己喜不喜歡的,我建議你倆都體驗一下,然後再決定用誰。

我之前用的都是 merge,現在開始嘗試 rebase ,慢慢感受線性歷史的美好。

寫在後面

其實 rebase 還有一種用法 rebase -i,被成為交互式 rebase ,又是一個強大的黑魔法,威力太大所以單獨成篇,後續已經發布,敬請關注!

小夥伴們,下篇博客見~


Gitrebase黑魔法之打造完美的線性歷史

歡迎關注博主的微信公眾號,快快加入哦,期待與你一起成長!

相關文章

Git丟失的commit是真的消失了嗎?

Git移動記錄儀&貼心小棉襖reflog

Git少年,你想學回滾嗎?想撤銷文件修改嗎?

Gitrebase黑魔法之打磨commit顆粒度