最近在合併上游程式碼,遇到了一個問題:某個 commit 雜糅了幾個不同的特性修改,這可能會導致 rebase 上游程式碼時需要再對該 commit 進行額外的程式碼衝突處理
解決方法:合併上游分支前,拆分雜糅的 commit,並將其中不同的特性修改合併(Squash)回相關的 commit。可以直接透過命令列進行操作,可以參考:Break a previous commit into multiple commits。也可以透過 JetBrains 家內建的 Git 進行操作,下面會介紹 IDEA 圖形化操作的方法
非先前 commit 的拆分
對於剛提交的 commit,要拆分多個 commit 是非常容易的,因為我們只要 soft reset
commit,將 commit 內容撤銷回至 暫存區
,就可以隨意提交 commit
如果對於 soft reset
不太瞭解,可以參考我之前的部落格:Git 中的回退操作:reset 和 revert
先前 commit 的拆分
先前 commit 指的是:在目標 commit 後已經有了若干個 commit。它無法直接透過 soft reset
進行拆分,因為這樣會丟失後續的 commit,如下圖,我們需要拆分 B
commit,我們就無法直接使用 soft reset
,因為這樣會丟失 C
和 D
commit 的修改
所以我們需要使用 rebase,具體步驟:
- 在 互動式 (interactive) rebase 中將
B
標記為edit
,這時B
後面的 commit 會被暫時隱藏起來 - 使用
soft reset
將B
撤銷回暫存區
- 將
B
的修改內容分多個 commit 提交B1
和B2
- 使用 rebase 的
continue
將剛才隱藏的C
和D
恢復回來
例項準備
演示使用 IDEA,其實 JetBrains 家的使用邏輯差不多,示例倉庫使用:Learn Go with Tests
git clone git@github.com:quii/learn-go-with-tests.git
需要用到 Rebase,IDEA 預設保護主分支,改寫 commit 記錄的功能會被禁用
需要先取消分支保護,移除 Protected branches
中的 master;main
假設我們需要將下面 commit 拆分為兩個:
1. 啟動 Rebase 並標記目標 commit 為 edit
點選 Interactively Rebase from Here...
選擇需要拆分的 commit,右鍵選擇 Stop to Edit
,然後再點選 Start Rebasing
這時有右下角會提示您正在處於 Rebase
狀態
選擇框可以選擇 Continue
即繼續 Rebase,Abort
則會退出 Rebase
commit 列表也會顯示感嘆號
2. 使用 soft reset 將 commit 撤銷回 暫存區
我們需要先 soft reset 到目標 commit 的上一個 commit
選擇上一個 commit,右鍵選擇:Reset Current Branch to Here...
選擇 Soft
,這樣目標 commit 的修改就會退回到暫存區
3. 將暫存區改動分為若干個 commit 提交
這個時候我們就可以繼續分開提交兩次 commit
檢視 log,兩條 commit 被成功提交
4. 使用 rebase 的 continue 恢復剩下的 commit
這時候我們需要繼續 Rebase,將剩下的 commit 還原回去:點選右下角分分支按鈕,選擇 Continue Rebase
完成 Rebase 後,剩餘的 commit 就會被追加到我們新提交的 commit 後面,至此我們就完成了先前 commit 的拆分
Rebase edit 的擴充
因為這裡的案例只是拆分 commit,沒有對 commit 進行修改,如果是修改的話,修改完成後需要使用 git add
將檔案標記為已修改,才能使用 rebase 的 continue
,這樣該 commit 就會被修改。後續的 commit 有可能與本次的改動產生衝突,需要手動處理衝突
參考資料
Break a previous commit into multiple commits