之前跟大家分享過使用 merge 來合併分支。
但有時我們並不想合併整個分支,而是選擇我們想要的 commit 來合併,
例如 a 分支做了一個更新使用者密碼的功能,
b 分支把新增帳號會錯誤的 bug 修掉,
那在 a 分支與 b 分支可能還有做其他的事,但我目前的專案只想要這幾個功能就好,
其他的功能可能現在不需要,或者還沒測試所以先不要納入正式系統。
那這樣我們就需要分別撿這些 commit 過來合併,而不是合併整個分支。
使用 cherry-pick
接著 commit 的版號就可以解決,並且可以一次輸入多個版號來合併。
加上 --no-commit
參數是會先把該 commit 內容放在暫存區讓我們用 git status
查看一下確認,
真的需要再合併提交,是更保險一點的做法。
我們現在在 master 撿 new_test 分支的 7a1d292
這個 commit 來合併看看:
# 先查出該 commit 的版號
$ git checkout new_test
Switched to branch 'new_test'
$ git log --oneline -4
21d3781 (HEAD -> new_test) 修改 abc.txt
10cf74c 增加一個 word 檔
0d9c34e 在 abc.txt 加了一行
7a1d292 把 ooqq.txt 的第一行改成我是第一行
# 切回 master 合併
$ git checkout master
Switched to branch 'master'
$ git cherry-pick 7a1d292
CONFLICT (modify/delete): ooqq.txt deleted in HEAD and modified in 7a1d292... 把
ooqq.txt 的第一行改成我是第一行. Version 7a1d292... 把 ooqq.txt 的第一行改成我
是第一行 of ooqq.txt left in tree.
error: could not apply 7a1d292... 把 ooqq.txt 的第一行改成我是第一行
hint: after resolving the conflicts, mark the corrected paths
hint: with 'git add <paths>' or 'git rm <paths>'
hint: and commit the result with 'git commit'
看來不太對勁,合併失敗了,仔細看一下訊息會發現,
在第一行 git 告訴我們 ooqq.txt 這個檔案已經被刪了要怎麼修改?
讓我們檢查一下:
# 先看一下有沒有刪除 ooqq.txt 的 commit
$ git log --oneline -3
762ece1 (HEAD -> master) 複製一個 test.py 蓋掉原本的同名檔案
580aaf0 (tag: V2.0) 新增 qqoo.txt
5bbbe37 刪除 ooqq.txt
# 原來在 5bbbe37 我們已經把 ooqq.txt 刪掉了
# 再看一下現行資料夾有什麼檔案
$ ls
hello.txt log.txt ooqq.txt qqoo.txt test.py
# 怪了,不是 ooqq.txt 刪了怎麼還在,如果還在的話又怎麼會合併失敗?
# 檢查一下狀態
$ git status
On branch master
You are currently cherry-picking commit 7a1d292.
(fix conflicts and run "git cherry-pick --continue")
(use "git cherry-pick --skip" to skip this patch)
(use "git cherry-pick --abort" to cancel the cherry-pick operation)
Unmerged paths:
(use "git add/rm <file>..." as appropriate to mark resolution)
deleted by us: ooqq.txt
no changes added to commit (use "git add" and/or "git commit -a")
他告訴我們,現在是處在要合併某個 commit 出了狀況,
上面提供了一些指令讓我們可以處理這個狀況,
我們先選擇繼續合併:
$ git cherry-pick --continue
error: Committing is not possible because you have unmerged files.
hint: Fix them up in the work tree, and then use 'git add/rm <file>'
hint: as appropriate to mark resolution and make a commit.
fatal: Exiting because of an unresolved conflict.
U ooqq.txt
當然不行啊,他跟你說你還沒處理,現在還在暫存區要怎麼合併。
有看到 ooqq.txt 前面有個 U
吧。
所以我們可以放棄 --abort
這次的 cherry-pick 合併,看後續想做什麼,
既然那麼好心,工作目錄都有了,那我們選擇把 ooqq.txt 加進來就好:
$ git add ooqq.txt
# 然後看一下狀態
$ git status
On branch master
You are currently cherry-picking commit 7a1d292.
(all conflicts fixed: run "git cherry-pick --continue")
(use "git cherry-pick --skip" to skip this patch)
(use "git cherry-pick --abort" to cancel the cherry-pick operation)
Changes to be committed:
new file: ooqq.txt
看來已經修復這個問題了,ooqq.txt 已經變成 new file 了。
因為我們還在 cherry-pick 當中,所以我們不做新的 commit 而是讓 cherry-pick 可以繼續:
$ git cherry-pick --continue
# 跳出編輯器要我輸入 commit 訊息,想用原本的就好,所以直接存檔離開
[master 05693fe] 把 ooqq.txt 的第一行改成我是第一行
Date: Sun Mar 29 23:27:06 2020 +0800
1 file changed, 1 insertion(+)
create mode 100644 ooqq.txt
# 注意看最後兩行,有新增檔案也有修改資訊
# 檢查狀態
$ git status
On branch master
nothing to commit, working tree clean
# 確認紀錄
$ git log --oneline -4
05693fe (HEAD -> master) 把 ooqq.txt 的第一行改成我是第一行
762ece1 複製一個 test.py 蓋掉原本的同名檔案
580aaf0 (tag: V2.0) 新增 qqoo.txt
5bbbe37 刪除 ooqq.txt
# 看一下 ooqq.txt 的內容
$ cat ooqq.txt
我是第一行
# 切到 new_test 分支,看一下 ooqq.txt 的內容
$ git checkout new_test
Switched to branch 'new_test'
$ cat ooqq.txt
我是第一行
嗯,兩邊一樣,合併成功。
因為合併發生問題,所以我們更需要仔仔細細的檢查,遇到問題不要逃閉,必須設法解決,
書上的 cherry-pick 例子是很順利的合併,但我覺得在實務上一次撿多個 commit 來合併就有可能發生衝突或不合邏輯的狀況,
這時候就需要一步步利用之前學習的知識及 git 提供給我們的做法和資訊來處理,
剛剛我們只撿了一個 commit 來合併,實務上的狀況可能是更複雜的,總之遇到問題難免,
但解法也是很多,不要慌,靜下心來一定可以解決。