Git——寫錯的不是最新的提交,而是倒數第二個?
寫錯的不是最新的提交,而是倒數第二個?
commit --amend 可以修復最新 commit 的錯誤,但如果是倒數第二個 commit 寫錯了,怎麼辦?
rebase -i:互動式 rebase
如果不是最新的 commit 寫錯,就不能用 commit --amend 來修復了,而是要用 rebase 。不過需 要給 rebase 也加一個引數: -i 。
rebase -i 是 rebase --interactive 的縮寫形式,意為「互動式 rebase」。
所謂「互動式 rebase」,就是在 rebase 的操作執行之前,你可以指定要 rebase
那麼你就可以利用這個特點,進行一次「原地 rebase」。
例如你是在寫錯了 commit 之後,又提交了一次才發現之前寫錯了:
git log
開啟互動式 rebase 過程
現在再用 commit --amend 已經晚了,但可以用 rebase -i :
git rebase -i HEAD^^
說明:
在 Git 中,有兩個「偏移符號」: ^ 和 ~ 。
^ 的用法:在 commit 的後面加一個或多個 ^ 號,可以把 commit
~ 的用法:在 commit 的後面加上 ~ 號和一個數,可以把 commit 往回偏移,偏移的數量 是 ~ 號後面的數。例如: HEAD~5 表示 HEAD 指向的 commit 往前數 5 個 commit 。
上面這行程式碼表示,把當前 commit ( HEAD 所指向的 commit ) rebase 到 HEAD 之前 2 個的 commit 上:
如果沒有 -i 引數的話,這種「原地 rebase」相當於空操作,會直接結束。而在加了 -i 後,就會 跳到一個新的介面:
編輯介面:選擇 commit 和對應的操作
這個編輯介面的最頂部,列出了將要「被 rebase」的所有 commit s,也就是倒數第二個 commit 「增加常見笑聲集合」和最新的 commit 「增加常見哭聲集合」。需要注意,這個排列是正序的,舊 的 commit 會排在上面,新的排在下面。
這兩行指示了兩個資訊:
- 需要處理哪些 commit s;
- 怎麼處理它們。
你需要修改這兩行的內容來指定你需要的操作。每個 commit 預設的操作都是 pick (從圖中也可以看出),表示「直接應用這個 commit 」。所以如果你現在直接退出編輯介面,那麼結果仍然是空 操作。
但你的目標是修改倒數第二個 commit ,也就是上面的那個「增加常見笑聲集合」,所以你需要把它的操作指令從 pick 改成 edit 。 edit 的意思是「應用這個 commit,然後停下來等待繼續修正」。其他的操作指令,在這個介面里都已經列舉了出來(下面的 "Commands…" 部分文字),你可以自己研究一下。
把 pick 修改成 edit 後,就可以退出編輯介面了:
上圖的提示資訊說明, rebase 過程已經停在了第二個 commit 的位置,那麼現在你就可以去修改你想修改的內容了。
修改寫錯的 commit
修改完成之後,和上節里的方法一樣,用 commit --amend 來把修正應用到當前最新的 commit :
git add 笑聲
git commit --amend
繼續 rebase 過程
在修復完成之後,就可以用 rebase --continue 來繼續 rebase 過程,把後面的 commit 直接應用上去。
git rebase --continue
然後,這次互動式 rebase 的過程就完美結束了,你的那個倒數第二個寫錯的 commit 就也被修正 了:
實質上,互動式 rebase 並不是必須應用在「原地 rebase」上來修改寫錯的 commit ,這隻不過是 它最常見的用法。你同樣也可以把它用在分叉的 commit 上,不過這個你就可以自己去研究一下了。
小結
這節介紹了互動式 rebase ,它可以在 rebase 開始之前指定一些額外操作。互動式 rebase 最常用的場景是修改寫錯的 commit ,但也可以用作其他用途。它的大致用法:
- 使用方式是 git rebase -i 目標commit ;
- 在編輯介面中指定需要操作的 commit s 以及操作型別;
- 操作完成之後用 git rebase --continue 來繼續 rebase 過程。