每一個可以努力的日子,都是一份厚禮。
Git tips: 合併 commit 保持分支幹凈整潔
本文的讀者需要已經了解 基本的 Git 操作和開發流程。
在我們開發完分支後,一般分支上會有很多 commit —— 少不了諸如 “fix typo”, “sth wrong in the previous commit” 之類的 commit。在合併到主幹的時候,往往這類 commit 顯得臃腫多餘。為了方便別人做 code review,我們希望合併一些不必要的 commit 使我們的分支顯得乾淨一目了然,也方便管理。有 3 種方式可以做到。
一、git rebase
$ git rebase -i origin/master |
-i
參數表示互動 interactive,這時 git 會使用你設定的編輯器,讓你對 git 歷史記錄做詳細修改。
下面以 Atlassian 的例子來說明
# 開始開發一個新 feature $ git checkout -b new-feature master # 改了一些代碼 $ git commit -a -m "Start developing a feature" # 剛剛的修改有點問題,再改一下 $ git commit -a -m "Fix something from the previous commit" # 緊急修復,直接在 master 分支上改點東西 $ git checkout master # 改了一些代碼 $ git commit -a -m "Fix security hole" # 開始交互式地 rebase 了 $ git checkout new-feature $ git rebase -i master |
這時 git 會打開編輯器,你會看到 new-feature 分支上的 2 個最新 commit,以及一些指引提示
pick 32618c4 Start developing a feature pick 62eed47 Fix something from the previous commit # Commands: # p, pick = use commit # r, reword = use commit, but edit the commit message # e, edit = use commit, but stop for amending # s, squash = use commit, but meld into previous commit # f, fixup = like "squash", but discard this commit's log message # x, exec = run command (the rest of the line) using shell # # These lines can be re-ordered; they are executed from top to bottom. # # If you remove a line here THAT COMMIT WILL BE LOST. # # However, if you remove everything, the rebase will be aborted. # # Note that empty commits are commented out |
每個 commit 前有一個操作命令,默認是 pick
,表示該行被選中,需要進行 rebase 操作。下面一堆注釋的指引中還有幾個指令,我們常用到的是以下 2 個
- squash:將這一行的 commit 與上一個 commit 進行合併
- fixup:與 squash 相同,只是不會保留這行 commit 的提交 message 信息
比如上面的例子,我們在編輯器中修改指令為
pick 32618c4 Start developing a feature squash 62eed47 Fix something from the previous commit |
這樣一改,保存執行後,new-feature 分支就只剩下 1 個 commit 了,這個合併後的 commit 提交的信息包含之前 2 個 commit 的信息
Start developing a feature Fix something from the previous commit
消除了一個多餘的不那麼重要的 commit,達到了我們的目的。最後,只需 fast-forward merge 到 master
$ git checkout master $ git merge new-feature |
在別人看來,你就是一個天才開發者,沒有出差錯地一次實現了 new-feature
,項目的 commit 歷史記錄顯得乾淨而有意義。
如果我們在編輯器中不用 squash 指令,而使用 fixup 指令,這樣改
pick 32618c4 Start developing a feature fixup 62eed47 Fix something from the previous commit |
則結果一樣,還是只剩 1 個 commit,但是合併後的提交消息,就只有之前第一個 commit 的消息,第二個的 commit 消息被注釋掉了
Start developing a feature
這樣也達到了我們的目的,消除了曾經發生過 2 個 commit 的痕迹。在別人看來,這個新功能的分支是按計劃一次性開發好的,中途並未發生 “錯別字” 之類的意外,簡直完美。
二、–fixup & –autosquash
# 自動標記這一次的 commit 為上一個 commit 的 fix $ git commit --fixup <commit> # 自動組織合併兩個 commit $ git rebase -i --autosquash |
這種方式和上面的第一種原理是一樣的,只是形式上不是在編輯器中調整歷史記錄,而是直接執行命令,結果等同。
三、撤銷過去的 commit 重建一個新的
$ git reset HEAD~2 $ git add . $ git commit -am "This is the new feature" $ git push --force |
這種方式就比較暴力了,嗯。
說點題外話
修改上一次 commit 提交的 message
有時我們提交代碼,message 寫的太匆忙有錯字(不是代碼里有錯字,而是 commit message 寫錯),就可以用下面的命令來修正
$ git commit --amend |
不過只能修正上一次的 commit。如果很多個 commit 之前就有 message 寫錯,就得用上我們之前說的 git rebase
了
$ git rebase -i HEAD~4 |
和之前一樣,會打開編輯器,顯示最近的 4 次提交
pick 07c5abd Introduce OpenPGP and teach basic usage pick de9b1eb Fix PostChecker::Post#urls pick 3e7ee36 Hey kids, stop all the highlighting pick fa20af3 git interactive rebase, squash, amend |
將 pick 指令改為 reword 指令,就可以修改這一行的 commit message
pick 07c5abd Introduce OpenPGP and teach basic usage pick de9b1eb Fix PostChecker::Post#urls reword 3e7ee36 Hey kids, stop all the highlighting pick fa20af3 git interactive rebase, squash, amend |
– EOF –
參考文檔
這篇文章由lovelucy於2015-12-25 16:25發表在編程。你可以訂閱RSS 2.0 也可以發表評論或引用到你的網站。除特殊說明外文章均為本人原創,並遵從署名-非商業性使用-相同方式共享創作協議,轉載或使用請註明作者和來源,尊重知識分享。 |
Google Chrome 47.0.2526.106 Windows 7 大約8年前
技術文,不明覺歷。