← 上一章:【狀況題】想要在某些 Commit 之間再加新的 Commit 下一章:Reset、Revert 跟 Rebase 指令有什麼差別? →


【狀況題】想要刪除某幾個 Commit 或是調整 Commit 的順序

調整 Commit 順序

要在 Git 裡調整 Commit 的順序其實滿簡單的,假設這是目前的歷史紀錄:

$ git log --oneline
27f6ed6 (HEAD -> master) add dog 2
2bab3e7 add dog 1
ca40fc9 add 2 cats
1de2076 add cat 2
cd82f29 add cat 1
382a2a5 add database settings
bb0c9c2 init commit

我想讓所有跟 cat 有關的 Commit 都移到 dog 相關的 Commit 的後面,一樣的 Rebase 起手式:

$ git rebase -i bb0c9c2

這時候跳出來的編輯器的 Commit 內容是這樣:

pick 382a2a5 add database settings
pick cd82f29 add cat 1
pick 1de2076 add cat 2
pick ca40fc9 add 2 cats
pick 2bab3e7 add dog 1
pick 27f6ed6 add dog 2

別忘了,在 Rebase 狀態看到的這個紀錄是跟我們平常看的紀錄是反過來的,越新的 Commit 在越下面。接下來我只要這樣移動一下:

pick 382a2a5 add database settings
pick 2bab3e7 add dog 1
pick 27f6ed6 add dog 2
pick cd82f29 add cat 1
pick 1de2076 add cat 2
pick ca40fc9 add 2 cats

是的,就是只要做這樣的修改,存檔、離開後,Rebase 就會做它的工作:

$ git rebase -i bb0c9c2
Successfully rebased and updated refs/heads/master.

搞定!現在的歷史紀錄就變這樣了:

$ git log --oneline
a2df4b2 (HEAD -> master) add 2 cats
a8e28c5 add cat 2
1e51a3d add cat 1
9f6a6a5 add dog 2
5a14212 add dog 1
382a2a5 add database settings
bb0c9c2 init commit

所有 cat 相關的 Commit 都搬到 dog 後面了。

使用 SourceTree 也挺容易的,用同樣的方式叫出 Rebase 視窗:

reorder commit

這時候可以用滑鼠拖拉順序,或是在視窗的上方有可以調整上下的按鈕,拉好期望的序順後:

reorder commit

按下 OK 鍵,便會進行 Rebase 指令:

reorder commit

輕輕鬆鬆就搞定了!

刪除 Commit

要刪除 Commit 更簡單了,在 Rebase 的過程中,把原本的 pick 改成 drop,或甚至直接把那行刪掉也可以。例如原本的 Commit 是這樣:

pick 382a2a5 add database settings
pick cd82f29 add cat 1
pick 1de2076 add cat 2
pick ca40fc9 add 2 cats
pick 2bab3e7 add dog 1
pick 27f6ed6 add dog 2

如果我想把跟 dog 有關的 Commit 都刪掉,只要把最後兩行刪掉:

pick 382a2a5 add database settings
pick cd82f29 add cat 1
pick 1de2076 add cat 2
pick ca40fc9 add 2 cats

存檔、離開後便開始進行 Rebase 指令:

$ git rebase -i bb0c9c2
Successfully rebased and updated refs/heads/master.

來看一下現在的 Commit 紀錄:

$ git log --oneline
ca40fc9 add 2 cats
1de2076 add cat 2
cd82f29 add cat 1
382a2a5 add database settings
bb0c9c2 init commit

剛剛那 2 個 Commit 就被刪除了。

使用 SourceTree 的話,一樣先叫出 Rebase 視窗,在打算刪除的 Commit 上按滑鼠右鍵,選擇「Delete commit…」功能:

remove commit

可以把打算刪除的都先標記起來:

remove commit

按下 OK 鈕之後便會開始執行 Rebase 指令:

remove commit

剛剛標記成刪除的 Commit 就被刪掉了。

後遺症?

那些穿越時空電影的劇情都會警告時空旅行者不要隨便修改歷史,想想看,如果你搭時光機回到你爸媽那個年代,然後想辦法拆散他們兩人,然後你還會是你嗎?

同樣的,不管是調整 Commit 的順序,或是刪除某個 Commit,都一樣要注意相依性問題。例如某個 Commit 修改 index.html 的內容,結果你把這個 Commit 移到建立 index.html 的那個 Commit 之前;或是你刪除了某個建立 welcome.html 檔案的 Commit,但後面的 Commit 都需要 welcome.html 這個檔案…像這樣的操作一定會出問題的,使用 Rebase 指令的時候要特別注意。


← 上一章:【狀況題】想要在某些 Commit 之間再加新的 Commit 下一章:Reset、Revert 跟 Rebase 指令有什麼差別? →

Comments