完美生活:git rebase -i
軟體開發是混亂的。有很多錯誤的轉折、有需要修復的錯別字、有需要修正的錯誤、有需要稍後糾正的臨時和粗陋的代碼,還有在以後的開發過程中發現一次又一次的問題。有了版本控制,在創建「完美」的最終產品(即準備提交給上游的補丁)的過程中,你會有一個記錄著每一個錯誤轉折和修正的原始記錄。就像電影中的花絮一樣,它們會讓人有點尷尬,有時也會讓人覺得好笑。
如果你使用版本控制來定期保存你的工作線索,然後當你準備提交審核的東西時,又可以隱藏所有這些私人草稿工作,並只提交一份單一的、完美的補丁,那不是很好嗎?git rebase -i
,是重寫歷史記錄的完美方法,可以讓大家覺得你一次就寫出了完美的代碼!
git rebase 的作用是什麼?
如果你不熟悉 Git 的複雜性,這裡簡單介紹一下。在幕後,Git 將項目的不同版本與唯一標識符關聯起來,這個標識符由父節點的唯一標識符的哈希以及新版本與其父節點的差異組成。這樣就形成了一棵修訂樹,每個簽出項目的人都會得到自己的副本。不同的人可以把項目往不同的方向發展,每個方向都可能從不同的分支點開始。
![Master branch vs. private branch](/data/attachment/album/202005/18/185954e6u9qgo89fm1iqus.png "Master branch vs. private branch")
左邊是 origin 版本庫中的主分支,右邊是你個人副本中的私有分支。
有兩種方法可以將你的工作與原始版本庫中的主分支整合起來:一種是使用合併:git merge
,另一種是使用變基:git rebase
。它們的工作方式非常不同。
當你使用 git merge
時,會在主分支(master
)上創建一個新的提交,其中包括所有來自原始位置(origin
)的修改和所有本地的修改。如果有任何衝突(例如,如果別人修改了你也在修改的文件),則將這些衝突標記出來,並且你有機會在將這個「合併提交」提交到本地版本庫之前解決這些衝突。當你將更改推送回父版本庫時,所有的本地工作都會以分支的形式出現在 Git 版本庫的其他用戶面前。
但是 git rebase
的工作方式不同。它會回滾你的提交,並從主分支(master
)的頂端再次重放這些提交。這導致了兩個主要的變化。首先,由於你的提交現在從一個不同的父節點分支出來,它們的哈希值會被重新計算,並且任何克隆了你的版本庫的人都可能得到該版本庫的一個殘破副本。第二,你沒有「合併提交」,所以在將更改重放到主分支上時會識別出任何合併衝突,因此,你需要在進行 變基 之前先修復它們。現在,當你現在推送你的修改時,你的工作不會出現在分支上,並且看起來像是你是在主分支的最新的提交上寫入了所有的修改。
![Merge commits preserve history, and rebase rewrites history.](/data/attachment/album/202005/18/190001rh770g6a6r7hra0z.png "Merge commits preserve history, and rebase rewrites history.")
合併提交(左)保留了歷史,而變基(右)重寫歷史。
然而,這兩種方式都有一個缺點:在你準備好分享代碼之前,每個人都可以看到你在本地處理問題時的所有塗鴉和編輯。這就是 git rebase
的 --interactive
(或簡寫 -i
)標誌發揮作用的地方。
git rebase -i 登場
git rebase
的最大優點是它可以重寫歷史。但是,為什麼僅止於假裝你從後面的點分支出來呢?有一種更進一步方法可以重寫你是如何準備就緒這些代碼的:git rebase -i
,即互動式的 git rebase
。
這個功能就是 Git 中的 「魔術時光機」 功能。這個標誌允許你在做變基時對修訂歷史記錄進行複雜的修改。你可以隱藏你的錯誤! 將許多小的修改合併到一個嶄新的功能補丁中! 重新排列修改歷史記錄中的顯示順序!
![output of git rebase -i](/data/attachment/album/202005/18/190007un3ink2h5nyciz3p.png "output of git rebase -i")
當你運行 git rebase -i
時,你會進入一個編輯器會話,其中列出了所有正在被變基的提交,以及可以對其執行的操作的多個選項。默認的選擇是選擇(Pick
)。
Pick
:會在你的歷史記錄中保留該提交。Reword
:允許你修改提交信息,可能是修復一個錯別字或添加其它注釋。Edit
:允許你在重放分支的過程中對提交進行修改。Squash
:可以將多個提交合併為一個。- 你可以通過在文件中移動來重新排序提交。
當你完成後,只需保存最終結果,變基操作就會執行。在你選擇修改提交的每個階段(無論是用 reword
、edit
、squash
還是發生衝突時),變基都會停止,並允許你在繼續提交之前進行適當的修改。
上面這個例子的結果是 「One-liner bug fix」 和 「Integate new header everywhere」 被合併到一個提交中,而 「New header for docs website」 和 「D'oh - typo. Fixed」 合併到另一個提交中。就像變魔術一樣,其他提交的工作還在你的分支中,但相關的提交已經從你的歷史記錄中消失了!
這使得使用 git send-email
或者用你新整理好的補丁集在父版本庫中創建一個拉取請求,然後來提交一個乾淨的補丁給上游項目變得很容易。這有很多好處,包括讓你的代碼更容易審核,更容易接受,也更容易合併。
via: https://opensource.com/article/20/4/git-rebase-i
作者:Dave Neary 選題:lujun9972 譯者:wxy 校對:wxy
本文轉載來自 Linux 中國: https://github.com/Linux-CN/archive