[教學] git-31 來撿 commit - 討論區

[教學] git-31 來撿 commit

文章瀏覽次數 1731 文章回覆數 0

特種兵

特種兵圖像(預設)

2020-04-19 11:20:02

From:1.161.142.154

之前跟大家分享過使用 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 來合併,實務上的狀況可能是更複雜的,總之遇到問題難免,

但解法也是很多,不要慌,靜下心來一定可以解決。