[教學] git應用-撿 commit 的疑惑 - 討論區

[教學] git應用-撿 commit 的疑惑

文章瀏覽次數 1090 文章回覆數 3

特種兵

特種兵圖像(預設)

2020-07-31 00:54:40

From:1.161.146.102

這邊收到伙伴的來信,詢問關於使用 cherry-pick 上的疑惑。

來撿 commit 一文中已經介紹過 cherry-pick 了。

主要是用來撿想要的 commit 但在使用上伙伴產生了疑惑,就讓我們來看一下吧。

首先,我們建立一個檔案,名為 index.txt 裡面有三行,分別是:

第一行
第二行
第三行

然後做了一個 commit

 commit 51f33baeac4aef3a8aaf6a2d6a4cbb124f25f20c (HEAD -> master)                
 Author: Logo Kuo <logo@forblind.org.tw>                                         
 Date:   Fri Jul 31 00:03:36 2020 +0800                                          

     原始 index.txt                                                              

接下來,把 index.txt 裡的第二行改成「修改第二行了」,也加了第四行,檔案內容變這樣:

第一行
修改第二行了
第三行
我是第四行

一樣做個 commit:

 commit c69bfc015bb98ec13db6167172b23d856c99c6be (HEAD -> master)                
 Author: Logo Kuo <logo@forblind.org.tw>                                         
 Date:   Fri Jul 31 00:07:34 2020 +0800                                          

     改第二行加第四行                                                            

最後,我們再把第三行刪掉,一樣做一個 commit:

 commit aec61567f3eb0f6fb7cb27fe6c244ddb0b6ee332 (HEAD -> master)                
 Author: Logo Kuo <logo@forblind.org.tw>                                         
 Date:   Fri Jul 31 00:11:05 2020 +0800                                          

     刪第三行                                                                    

所以關於 index.txt 總共有三個提交。

我們原本是在 master 主幹道,現在切換到 new_test 這個分支。

在這個分支目前完全沒有 index.txt 這個檔案。

我們如果直接撿第三個 commit 會怎麼樣:

$ git checkout new_test                                                         
 Switched to branch 'new_test'                                                   

$ git log -1                                                                    
 commit 21d3781343c4fb29d7f94ef2449a7fe71d9f17d8 (HEAD -> new_test)              
 Author: Logo Kuo <logo@forblind.org.tw>                                         
 Date:   Thu Apr 16 17:34:35 2020 +0800                                          

     修改 abc.txt                                                                

$ git status                                                                    
 On branch new_test                                                              
 nothing to commit, working tree clean                                           

$ git cherry-pick aec6156                                                       
 CONFLICT (modify/delete): index.txt deleted in HEAD and modified in aec6156...  
 刪第三行. Version aec6156... 刪第三行 of index.txt left in tree.                
 error: could not apply aec6156... 刪第三行                                      
 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'                                   

為什麼不行,因為這個分支我們沒有 index.txt 要怎麼對它做修改,在第三個 commit 並沒有新增一個 index.txt 檔案的動作,

這個是我們在第一個 commit 做的事情。

$ git status                                                                    
 On branch new_test                                                              
 You are currently cherry-picking commit aec6156.                                
   (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:   index.txt                                              

 no changes added to commit (use "git add" and/or "git commit -a")               

他告訴我們 index.txt 沒有在工作區,那我們直接把它加進來:

$ git add index.txt
$ git commit -m '加入 index.txt'                                                
 [new_test a970dc8] 加入 index.txt                                               
  Date: Fri Jul 31 00:11:05 2020 +0800                                           
  1 file changed, 3 insertions(+)                                                
  create mode 100644 index.txt                                                   

$ git log -1                                                                    
 commit a970dc84dfb5da1e8e4fa3c4d74e06e1e87f942f (HEAD -> new_test)              
 Author: Logo Kuo <logo@forblind.org.tw>                                         
 Date:   Fri Jul 31 00:11:05 2020 +0800                                          

     加入 index.txt                                                              

趕快來看一下 index.txt 的內容:

$ cat index.txt                                                                 
 第一行                                                                          
 修改第二行了                                                                    
 我是第四行                                                                      

檔案的內容是完整的,看起來就是第三個 commit 提交的版本。

那位伙伴的問題在於把 commit 想成是前面一個個 commit 的累加,

也就是說,如果我直接撿第三個 commit 出來的結果會不完整,因為我沒有第一和第二個 commit.

經過上述的實驗,我們發現這樣的想法是錯誤的,

如果是這樣的話,撿 commit 是沒意義的,因為每個 commit 都要靠上一個 commit 來累積,

那直接撿最後一個行不通,一定要往回撿,那就全部 merge 了,何必單獨撿 commit.

所以,我們要有個正確的概念,就是可以把每個 commit 想成是單獨唯一的,

你撿了這個 commit 就是擁有這個 commit 所有看到的結果。

因此,你不需要考慮他的前一個 commit 做了什麼,你只要確定這個 commit 的結果是你要的,你就可以把他撿過來了。

像我們經常會在一個分支裡面推了好幾個 commit 例如,第一個新增刪除功能,第二個是把刪除的表格調整好,第三個是新增修改功能。

結果第三個新增修改功能時不小心把刪除功能搞壞了,

所以我們只要撿第二個 commit 就會有新增的刪除功能且表格是調整好的。

這樣我們的主幹道就會很簡潔,就挑完成且確定沒問題的 commit 過來就好了。

另外,使用 cherry-pick 後面使用空格來隔開多個 commit 一次撿多個 commit 時,

它不會自動幫我們 merge 在一起,而是一個個撿過來,如果要合併可以考慮看 合併 commit 這篇。

留言

#1

特種兵

特種兵圖像(預設)

2020-07-31 01:12:09

From:1.161.146.102

再考考大家,看觀念有沒有清楚
如果我現在弄了一個 index.txt 內容跟要 cherry-pick 的 commit 的 index.txt 完全不同
那會發生什麼事?

#2

特種兵

特種兵圖像(預設)

2020-08-24 23:03:29

From:1.161.137.155

其實就回歸到能自動 merge 就自動 merge
不能 merge 就會發生衝突,然後我們必須處理衝突再重推上去

#3

貓貓蟲

貓貓蟲圖像

2020-08-25 14:10:42

From:60.251.157.136

衝突是難免的 我現在工作都是很大型的project 衝突是家常便飯
基本上要會解衝突才算是會基本的git