Git 的好用技巧介紹 - Cherry-Pick 和 git reset HEAD^

古古

2024/10/08


Git 可以說是工程師使用上最頻繁的技術,這篇文章會分享兩個我覺得 Git 的好用技巧給大家,分別是:

  1. Cherry-Pick: 擷取某個 branch 中的某個 commit
  2. git reset HEAD^ 撤銷最新的 commit

所以我們就開始吧!

Git 好用技巧之一:Cherry-Pick(擷取某個 branch 中的某個 commit) #

如果說 Git 有什麼隱藏的特殊技能的話,Cherry-Pick 絕對是我心目中的第一名!

Cherry-Pick 的用途,是「擷取某個 branch 中的某個 commit」,這個聽起來是有點抽象,所以下面就透過一個實際的例子來示範 Cherry-Pick 的用法。

像是目前在 master branch 中,在 resources 資料夾底下只有一個 application.properties 的檔案:

如果這時候,我們切到 test 這個 branch 上,然後在 resources 底下新增一個 123.txt 的檔案,並且成功 commit 的話,結果就會像下圖一樣,在「步驟 3」的地方新增了一個 123 的 commit 出來。

這時如果再接著新增一個 456.txt 的檔案,並且也成功 commit 的話,結果就會和下圖一樣,在「步驟 2」的地方新增了一個 456 的 commit 出來。

所以到目前為止,在 test branch 就新增了兩個 commit:

  • 一個是 123 的 commit(包含 123.txt 檔案)
  • 另一個則是 456 的 commit(包含 456.txt 檔案)

而 master branch 中則是維持原樣,沒有任何新增的 commit,resources 底下也只有 application.properties 一個檔案。

這時候,神奇的需求來了!!如果現在有人要你切回到 master branch,並且要求你將 test branch 中的 123.txt 的檔案移植到 master branch 的話,你該怎麼辦?

在還不會使用 Cherry-Pick 時,第一直覺反應是將 test merge 進 master,並且想辦法把 456 的 commit 刪掉,這樣子就能夠只保留 123 的 commit。

這種做法雖然也能夠解決問題,但是當 commit 數一多的時候,就會變的很混亂,無法確保自己是否有保留到正確的 commit。

所以這時候,就是 Cherry-Pick 上場的時候了!

當我們在 master branch,想要擷取 test branch 中的某個 commit 時,只要在 IDE 上點擊右鍵(在這個例子中,就是對 123 這個 commit 點擊右鍵),然後選擇 Cherry-Pick:

點擊之後,就可以看到在 master branch 的 resources 資料夾中,就多出了一個 123.txt 的檔案!並且在 master branch 中,也多出了一個新的 commit 123,所以這也就表示,我們就成功的將 test branch 中的 commit,偷到 master branch 中了!

因此大家以後如果有「擷取別的 branch 中的某個 commit」的需求時,就可以使用 Cherry-Pick 幫助我們非常方便的做到!

補充:Cherry-Pick 的「偷」的動作不是真的偷過來,而是將 test branch 中的 123 commit 中的內容,複製同樣的一份到 master branch 上,所以 master branch 的 123 commit 和 test branch 中的 123 commit,兩者之間是沒有任何關係的,在 Git 的線圖上,他們會是兩個獨立的 commit。

雖然 Cherry-Pick 的使用情境看起來真的很少見,但老實說我在實際的工作中真的有用過一兩次,而且那次幫助真的滿大的,超級感謝發明 Cherry-Pick 的人XD。

那時候我是在某條 branch(ex: TICKET-112)上開發,但是後來因為各種原因所以要棄用這條 branch,換到另一條 branch 開發(ex: TICKET-917),這時候我就在新的 branch 上使用 Cherry-Pick 去拉有用的 commit 過來,真的很好用!!

Cherry-Pick 就是屬於一年不開張、開張吃一年的指令,建議大家可以先把他的情境記下來,等到將來有一天真的也遇見這種神奇的狀況時,再回頭來查看他的使用方法就好~

Git 好用技巧之二:git reset HEAD^(撤銷最新的 commit) #

git reset HEAD^ 是我個人愛用的 Git 指令,他可以用來撤銷最新的 commit,但是不會刪除該 commit 中的內容,所以適合用在「上一個 commit 沒寫好,想要重新 commit」的情境上。

舉例來說,目前在 test branch 中,有兩個 commit:

  • 一個是 123 的 commit(包含 123.txt 檔案)
  • 另一個則是 456 的 commit(包含 456.txt 檔案)

如果這時候我發現「啊!我少添加了一個 789.txt 的檔案」,那麼我就可以先執行 git reset HEAD^ 的指令,先將 commit 456 給撤銷(注意此時 456.txt 的檔案仍舊存在,只是變回尚未 commit 的狀態):

此時我就可以自由添加想要的程式(ex: 789.txt),然後後續就可以將 456.txt 和 789.txt 一起加到 commit 裡,將他們存放在同一個 commit 中。

之所以會特別介紹 git reset HEAD^,是因為我在工作上還滿常用這個指令的。根據以往的經驗,我發現將多個相關的檔案儲存在同一個 commit 裡面,這樣後續如果要排查程式的話,放在同一個 commit 中的檔案會比較好查。

像是在 IntelliJ 這個 IDE 中,點擊「456 + 789」的 commit,就會在右側呈現這一次 commit 中的檔案有哪些,所以就可以透過這個線索,去查詢和他有相關的改動為何。

所以在實作上,我個人會偏好盡量把相關的程式 commit 在一起,也算是幫助自己後續排查問題時比較好查詢這樣。

不過老實說 commit 的頻率和檔案數,這個真的就很看大家自己的喜好,所以大家就自由參考,或是說如果有什麼更好的做法,也歡迎在下方留言!

補充:如果想要在 IntelliJ 中達到 git reset HEAD^ 的效果,可以直接在該 commit 上點擊「Undo Commit」,這樣子就可以得到和 git reset HEAD^ 一樣的「撤銷 Commit」的效果了!

結語 #

這篇文章我們有分享了 Git 中的好用技巧:Cherry-Pick 和 git reset HEAD^ 給大家,雖然這兩個指令的使用頻率不是很高,但是這兩個都是我自己用過,真心覺得好用的指令~

如果你對後端技術有興趣的話,也歡迎免費訂閱 《古古的後端筆記》電子報 ,每週二為你送上一篇後端技術分享,那我們就下一篇文章見啦!