[Git] 使用 git format-patch 將指定 commit 的內容補丁到任意分支
在公司使用 Git 協同開發時,常常遇到一個問題,
就是平常會從 dev 開一個分支出來,開發新的功能,
但中途可能發現有個 bug 需要修掉。
理論上應該回到 dev 再開一個新的 bug 分支,
但是那樣的話,原本在寫的新功能的部分就會消失,
導致本來可以測試的部分又壞掉…
所以我通常會想要從功能分支上,直接開出一個 bug 分支,
這樣它會有新的功能,同時可以修 bug,也不影響我的測試。
但是我不能直接把這個 bug 分支送上 PR (Pull Request),
因為它會把開發中的部分也直接送上去了。
有沒有辦法單把我修 bug 的部分,單獨變成另一個新的 bug 分支,
這樣我就可以單獨對它送出 PR 呢?
感覺上應該是有許多種方法,我這邊試的是用 git format-patch 的方式。
首先,用 git log 查看一下,
這個例子裡的前一個 commit a4f9 是有新功能的部分,
最新的 af64 則是修了 bug:
testuser@localhost ~ $ git log commit af64a3dbd21b332551f4dd7b9d7d0d91b1e612fd Author: Test User <testuser@test.com> Date: Wed Apr 22 09:56:51 2020 +0800 Fix cli: showvminfo commit a4f91f12af185c2202a6a09b8a8c805eb957790d Merge: 1cd2782 14fc670 Author: Test User <testuser@test.com> Date: Tue Apr 21 23:12:19 2020 +0800 Merge branch 'dev' into feature/041613-convert-cmdline
我想把 af64 那個 commit 變成一個單獨的補丁檔 (patch),
可以用 git format-patch 指令。
不過要注意參數我給的是 a4f9 也就是前一個 commit,
因為 git format-patch 會把 af49 到最新 commit (af64) 間的改變,
變成一個 patch 檔,
像這次它產生了一個 0001-Fix-cli-showvminfo.patch:
testuser@localhost ~ $ git format-patch a4f91f12af185c2202a6a09b8a8c805eb957790d 0001-Fix-cli-showvminfo.patch
當然你也可以用 HEAD~1 取代 a4f9,
表示我要取前一次 commit 到最新 commit 間的改變,效果相同:
git format-patch HEAD~1
這個 patch 檔案的內容,前面是給 git 看的資訊,
後面的部分就跟 diff 指令會產生的 patch 檔類似:
testuser@localhost ~ $ cat 0001-Fix-cli-showvminfo.patch From af64a3dbd21b332551f4dd7b9d7d0d91b1e612fd Mon Sep 17 00:00:00 2001 From: Test User <testuser@test.com> Date: Wed, 22 Apr 2020 09:56:51 +0800 Subject: [PATCH] Fix cli: showvminfo --- src/cli/showvminfo.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/cli/showvminfo.py b/src/cli/showvminfo.py index f0ef1f9..1c3e2f9 100644 --- a/src/cli/showvminfo.py +++ b/src/cli/showvminfo.py @@ -1,11 +1,12 @@ +import xml.etree.cElementTree as ET from cli import Cmd +from manager.xml import Xml
我現在就可以回到 dev 分支,然後開一個 bug/fix-showvminfo 分支,
準備來修 bug:
testuser@localhost ~ $ git checkout -b bug/fix-showvminfo Switched to a new branch 'bug/fix-showvminfo'
接著用 git apply –check 檢查一下這個補丁檔,能不能應用在這個分支上。
如果沒有衝突的話,這個指令不會輸出任何東西:
git apply --check 0001-Fix-cli-showvminfo.patch
接著就可以拿掉 –check 參數,讓 git apply 真正的打上補丁:
git apply 0001-Fix-cli-showvminfo.patch
這時用 git status 指令,可以看到補丁確實被打上了,
可以再用 git diff 指令檢查一下修改的內容,再 commit 了:
testuser@localhost ~ $ git status On branch bug/fix-showvminfo Changes not staged for commit: (use "git add ..." to update what will be committed) (use "git checkout -- ..." to discard changes in working directory) modified: cli/showvminfo.py
git commit 之後,就可以對這 bug 分支送出 PR,
它不會包含之前的 af49 的 commit,
因此 PR 裡就只會有修 bug 的部分,同事審查起來也比較簡單~
如果很確定 patch 檔案沒問題的話,也可以直接用 git am 來上補丁,
省掉 git apply 和 git commit 兩個動作,
不過我還是傾向用 git apply 一步步做,比較安心囉~^^