[教學] git應用-對過去的提交加料 - 討論區

[教學] git應用-對過去的提交加料

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

特種兵

特種兵圖像(預設)

2021-01-14 12:34:13

From:211.23.21.202

前言

這篇可能頭腦清醒一點再看會比較好,因為操作部驟比較多,又牽涉到兩個用戶端。

已經推了幾個 commit 後,發現其中一個 commit 需要加料,原因是客戶臨時又改變需求了。

但是我不想多推另一個 commit, 因為要改的地方跟某個 commit 算是一起的,而且這也還是測試分支,

我想確定都改好也測試好就是同一個 commit, 之後到正式分支就不用再合併一次了。

確認狀況

看一下本地端的 git log 前3個 commit

$ git log -3
commit bbd1613aabf14ca0504a17009bca3e1128c90832
Author: Logo-Kuo <logo@forblind.org.tw>
Date:   Tue Jan 12 12:51:55 2021 +0800

    type: fix
    system: leave
    scope: view/self/controller/model/js
    subject: 在留停紀錄頁面加入查詢與刪除詳細留停紀錄功能

commit 13ca4376799a9f43c2b9ee1b25d51bcd26913f10
Author: Logo-Kuo <logo@forblind.org.tw>
Date:   Tue Jan 12 13:48:42 2021 +0800

    document pdf 2

commit 4fe152957fbd2e9a072861a1e3522d6e14ef1e2f
Author: Logo-Kuo <logo@forblind.org.tw>
Date:   Fri Jan 8 22:36:17 2021 +0800

    type: fix
    system: leave
    scope: view/model/controller/self/js
    subject: 新增查詢所有員工的年資與留停紀錄

我要改的 commit 是第2個,也就是 document pdf 2, id 為 13ca437,

而其他 commit 都不動,繼續保留。

我們找出想改的 commit 的前一個 commit id 是 4fe1529,

然後使用 rebase 的交互模式:

rebase

$ git rebase -i 4fe1529
pick 13ca437 document pdf 2
pick bbd1613 type: fix system: leave scope: view/self/controller/model/js subject: 在留停紀錄頁面加入查詢與刪除詳細留停紀錄功能

# 提醒一下,rebase 的 commit 跟 git log 相反,越新是越下面喔
# 接著,我們把 document pdf 2 的 commit 前面動作 pick 改成 edit 像這樣:

edit 13ca437 document pdf 2

# 對其他動作有興趣的可以看我之前的文章,這個畫面的下方也有被註解掉的說明可以參考
# 改好存檔離開

 Stopped at 13ca437...  document pdf 2                                           
# 他會停在這個 edit 的 commit 
 You can amend the commit now, with                                              

   git commit --amend                                                            
# 你可以使用上面指令來修改這個 commit 的訊息
 Once you are satisfied with your changes, run                                   

   git rebase --continue                                                         
# 如果你確定已經處理好了那可以使用上面指令讓 rebase 繼續跑完

回到提示符號後,來看一下 log:

$ git log -1                                                                    
 commit 13ca4376799a9f43c2b9ee1b25d51bcd26913f10 (HEAD)                          
 Author: Logo-Kuo <logo@forblind.org.tw>                                         
 Date:   Tue Jan 12 13:48:42 2021 +0800                                          

     document pdf 2                                                              

看到最後一個 commit 是我們要改的 commit 才是正確的。

因為我們現在在 rebase 裡面,並沒有做退版或合併之類的動作,可以想成它把之後的 commit 先藏起來了,

這樣我們才方便處理當下這個 commit.

# 看一下狀態
$ git status                                                                    
 interactive rebase in progress; onto 4fe1529                                    
# 我們處在這個 commit 的 rebase 交互模式裡
 Last command done (1 command done):                                             
    edit 13ca437 document pdf 2                                                  
# 最後一個指令停在這個 commit 上面
 Next command to do (1 remaining command):                                       
    pick bbd1613 type: fix system: leave scope: view/self/controller/model/js sub
 ject: 在留停紀錄頁面加入查詢與刪除詳細留停紀錄功能                              
# 下一個 commit 是被保留的,也就是比 document pdf 2 較新的那些 commit 
   (use "git rebase --edit-todo" to view and edit)                               
# 使用上面的指令可以回到 rebase 的交互編輯模式,例如 edit 寫錯了
 You are currently editing a commit while rebasing branch 'dev' on '4fe1529'.    
# 現在在 dev 分支 處理某個 commit
   (use "git commit --amend" to amend the current commit)                        
# 使用上面指令改 commit 訊息
   (use "git rebase --continue" once you are satisfied with your changes)        
# 使用上面指令讓 rebase 繼續跑完                                                                                 
 nothing to commit, working tree clean                                           
# 上面這句應該很熟悉吧 ,工作目錄乾淨

軟退版

接下來,我們要把 document pdf 2 拆到工作目錄下,因為我們打算繼續加料進去。

所以我們退一版,這時候不能用 --hard 因為我們需要把 commit 動過的檔案拆到工作目錄。

$ git reset HEAD~                                                               
 Unstaged changes after reset:                                                   
 M       web_data/sysLlibrary/PDF/sysPDF.php                                     
 M       web_data/sysLlibrary/PDF/template/document/document.tpl                 

兩個檔案被拆到工作目錄了

看一下 log

$ git log -1                                                                    
 commit 4fe152957fbd2e9a072861a1e3522d6e14ef1e2f (HEAD)                          
 Author: Logo-Kuo <logo@forblind.org.tw>                                         
 Date:   Fri Jan 8 22:36:17 2021 +0800                                           

     type: fix                                                                   
     system: leave                                                               
     scope: view/model/controller/self/js                                        
     subject: 新增查詢所有員工的年資與留停紀錄                                   

# 沒錯,document pdf 2 拆掉了                                                                                 
# 看一下狀態

$ git status                                                                    
 interactive rebase in progress; onto 4fe1529                                    
 Last command done (1 command done):                                             
    edit 13ca437 document pdf 2                                                  
 Next command to do (1 remaining command):                                       
    pick bbd1613 type: fix system: leave scope: view/self/controller/model/js sub
 ject: 在留停紀錄頁面加入查詢與刪除詳細留停紀錄功能                              
   (use "git rebase --edit-todo" to view and edit)                               
# 上面都解釋過了
 You are currently splitting a commit while rebasing branch 'dev' on '4fe1529'.  
# 現在我們在 dev 分支的這個 commit rebase 交互模式下切了另一個 commit 下來
   (Once your working directory is clean, run "git rebase --continue")           
# 上面解數了,接下來是我們熟悉的 status 內容                                                                                 
 Changes not staged for commit:                                                  
   (use "git add <file>..." to update what will be committed)                    
   (use "git restore <file>..." to discard changes in working directory)         
         modified:   web_data/sysLlibrary/PDF/sysPDF.php                         
         modified:   web_data/sysLlibrary/PDF/template/document/document.tpl     

 no changes added to commit (use "git add" and/or "git commit -a")               
# 就是要你處理好後繼得 add 然後推 commit

加料與提交

接著就是看我們想做什麼,就像一般在處理工作一樣,想開檔案繼續寫程式或刪除什麼之類的,

好,那假設都弄好了,就是 git add .git commit

下面是寫完 commit 訊息,我寫的是 document pdf 3:

$ git commit                                                                    
 [detached HEAD 93ac02e] document pdf 3                                          
  2 files changed, 8 insertions(+), 34 deletions(-)                              
# 注意一下,關鍵字 detached 
# 因為我們處在 rebase 交互模式下,所以斷頭中
# 看最新的兩個 log

$ git log -2

 commit 93ac02e65ff295426c7c8a4c35634a53d3321077 (HEAD)                          
 Author: Logo-Kuo <logo@forblind.org.tw>                                         
 Date:   Tue Jan 12 15:54:14 2021 +0800                                          

     document pdf 3                                                              

 commit 4fe152957fbd2e9a072861a1e3522d6e14ef1e2f                                 
 Author: Logo-Kuo <logo@forblind.org.tw>                                         
 Date:   Fri Jan 8 22:36:17 2021 +0800                                           

     type: fix                                                                   
     system: leave                                                               
     scope: view/model/controller/self/js                                        
     subject: 新增查詢所有員工的年資與留停紀錄                                   

# 沒問題,原本的 document pdf 2 被我們拆掉,做好之後重新 commit 成為 document pdf 3
# 看狀態

$ git status                                                                    
 interactive rebase in progress; onto 4fe1529                                    
 Last command done (1 command done):                                             
    edit 13ca437 document pdf 2                                                  
 Next command to do (1 remaining command):                                       
    pick bbd1613 type: fix system: leave scope: view/self/controller/model/js sub
 ject: 在留停紀錄頁面加入查詢與刪除詳細留停紀錄功能                              
   (use "git rebase --edit-todo" to view and edit)                               
 You are currently editing a commit while rebasing branch 'dev' on '4fe1529'.    
   (use "git commit --amend" to amend the current commit)                        
   (use "git rebase --continue" once you are satisfied with your changes)        
# 上面都解釋過了                                                                                 
 nothing to commit, working tree clean                                           
# 因為已經重新推 commit 了,所以工作目錄乾淨

完成 rebase

那就讓 rebase 繼續完成

$ git rebase --continue                                                         
 Successfully rebased and updated refs/heads/dev.                                

# 順立成功
# 看最新的 3 個 commit

$ git log -3
commit 97e1228aa7d70cf4d9ec984a6cc97b2595c2d3cb
Author: Logo-Kuo <logo@forblind.org.tw>
Date:   Tue Jan 12 12:51:55 2021 +0800

    type: fix
    system: leave
    scope: view/self/controller/model/js
    subject: 在留停紀錄頁面加入查詢與刪除詳細留停紀錄功能

# 這個是當時被 rebase 保留的新 commit 
# rebase 完成,當然也還給我們了
# 不過從我們 edit 之後的 commit id 全部都會被改
# 就是之後的 commit 其實都重新做了
# 所以如果調整的是很舊的 commit 那麼 continue 就要等一下了

commit 93ac02e65ff295426c7c8a4c35634a53d3321077
Author: Logo-Kuo <logo@forblind.org.tw>
Date:   Tue Jan 12 15:54:14 2021 +0800

    document pdf 3

# 這個是我們新改好推上來的 commit

commit 4fe152957fbd2e9a072861a1e3522d6e14ef1e2f
Author: Logo-Kuo <logo@forblind.org.tw>
Date:   Fri Jan 8 22:36:17 2021 +0800

    type: fix
    system: leave
    scope: view/model/controller/self/js
    subject: 新增查詢所有員工的年資與留停紀錄

# 這個是舊的,完全不動,包括 commit id    
# 看狀態
$ git status                                                                    
 On branch dev                                                                   
 nothing to commit, working tree clean                                           
# 很好,一切正常

推上遠端倉庫

如果是基礎課程,到上面就應該結束了,

但我們是實務應用,所以要把整個分支推上遠端倉庫。

$ git push origin dev                                                           
 logo@192.168.7.11's password:                                                    
 To 192.168.7.11:/xxx/yyyy                                                        
  ! [rejected]        dev -> dev (non-fast-forward)                              
 error: failed to push some refs to '192.168.7.11:/xxx/yyyy'                      
 hint: Updates were rejected because the tip of your current branch is behind    
 hint: its remote counterpart. Integrate the remote changes (e.g.                
 hint: 'git pull ...') before pushing again.                                     
 hint: See the 'Note about fast-forwards' in 'git push --help' for details.      

這下慘了,推不上去,因為有 rebase 又退版之類的動作

我確定目前本地端是對的,那就硬推了。

$ git push origin dev -f                                                        
 logo@192.168.7.11's password:                                                    
 Enumerating objects: 47, done.                                                  
 Counting objects: 100% (47/47), done.                                           
 Delta compression using up to 6 threads                                         
 Compressing objects: 100% (24/24), done.                                        
 Writing objects: 100% (25/25), 4.31 KiB | 315.00 KiB/s, done.                   
 Total 25 (delta 18), reused 0 (delta 0), pack-reused 0                          
 To 192.168.7.11/xxx/yyyy                                                        
  + bbd1613...97e1228 dev -> dev (forced update)                                 
# 好了,但故事還沒完喔

server 端的狀況

我已經完成工作了,但其他合作開發的伙伴就慘了。

因為做了上述動作,是必其他合作伙伴的分支也會受到影響

不說別的,server 端的 dev 分支也是 client 端,所以來看一下會發生什麼事情。

我們就假設其他伙伴或處理 server 端的人不知情好了,首先,他應該會先更新遠端倉庫的狀態:

logo@sys:/xxx/test_sys$ git remote update                                       
 Fetching origin                                                                 
 logo@127.0.0.1's password:                                                      
 remote: Enumerating objects: 13, done.                                          
 remote: Counting objects: 100% (13/13), done.                                   
 remote: Compressing objects: 100% (7/7), done.                                  
 remote: Total 7 (delta 5), reused 0 (delta 0)                                   
 Unpacking objects: 100% (7/7), done.                                            
 From 127.0.0.1:/xxx/yyyy                                                        
    0c97c3b..b4935b3  master     -> origin/master                                
  * [new tag]         3.9.2      -> 3.9.2                                        

更新好了,不過要註意的地方有:

  • server 端就是跟 git 遠端倉庫同一臺機器,所以 ip 會變成 127.0.0.1
  • 我們的 server 端是 linux 環境,所以提示符號長不太一樣,不是 windows git bash
  • 因為是整個遠端倉庫狀態的更新,所以其他分支像 master 有變動也會更新,雖然我們是在 dev 分支
# 看狀態
logo@sys:/xxx/test_sys$ git status                                              
 On branch dev                                                                   
 Your branch and 'origin/dev' have diverged,                                     
 and have 2 and 2 different commits each, respectively.                          

# 比較細心的應該就發現不對了
# 就算沒發現,直接推拉也會有錯誤提示
 (use "git pull" to merge the remote branch into yours)                        

 nothing to commit, working tree clean                                           

它說我們的狀態跟遠端倉庫比起來有兩個不同

那看一下最新的2個 log

logo@sys:/xxx/test_sys$ git log -2                                              
 commit bbd1613aabf14ca0504a17009bca3e1128c90832 (HEAD -> dev)                   
 Author: Logo-Kuo <logo@forblind.org.tw>                                         
 Date:   Tue Jan 12 12:51:55 2021 +0800                                          

     type: fix                                                                   
     system: leave                                                               
     scope: view/self/controller/model/js                                        
     subject: 在留停紀錄頁面加入查詢與刪除詳細留停紀錄功能                       

 commit 13ca4376799a9f43c2b9ee1b25d51bcd26913f10                                 
 Author: Logo-Kuo <logo@forblind.org.tw>                                         
 Date:   Tue Jan 12 13:48:42 2021 +0800                                          

     document pdf 2                                                              

應該很熟悉,基本上就是跟我們文章剛開始還沒動工的時候一樣。

如果自己本身已經推新的 commit 的話會需要再多處理一下,這部分我們下一篇會分享

拉回來衝突了

照理就是也看一下遠端倉庫的 log, 才知道要怎麼調整,不過我們先裝傻,就給它拉回來更新看看:

logo@sys:/xxx/test_sys$ git pull origin dev                                     
 logo@127.0.0.1's password:                                                      
 From 127.0.0.1:/xxx/yyyy                                                        
  * branch            dev        -> FETCH_HEAD                                   
 Auto-merging web_data/sysLlibrary/PDF/template/document/document.tpl            
 CONFLICT (content): Merge conflict in web_data/sysLlibrary/PDF/template/document
 /document.tpl                                                                   
 Automatic merge failed; fix conflicts and then commit the result.               

不妙了,拉回來合併失敗了,檔案產生衝突。

# 看狀態
logo@sys:/xxx/test_sys$ git status                                              
 On branch dev                                                                   
 Your branch and 'origin/dev' have diverged,                                     
 and have 2 and 2 different commits each, respectively.                          
   (use "git pull" to merge the remote branch into yours)                        

 You have unmerged paths.                                                        
   (fix conflicts and run "git commit")                                          
   (use "git merge --abort" to abort the merge)                                  
# 你有還沒合併的檔案,看是要處理後 commit 還是放棄合併,回到 pull 之前                                                                                 
 Unmerged paths:                                                                 
   (use "git add <file>..." to mark resolution)                                  

         both modified:   web_data/sysLlibrary/PDF/template/document/document.tpl
# 這個檔案衝突了,處理後 add 進來再 commit                                                                                 
 no changes added to commit (use "git add" and/or "git commit -a")               

其實提示就很清楚該怎麼做了,讓我們把衝突的檔案打開,

參考之前處理衝突的文章所述,解決衝突並存檔。

推 commit 時會有 merge 訊息,我先直接使用,推好後看狀態

logo@sys:/xxx/test_sys$ git status                                              
 On branch dev                                                                   
 Your branch is ahead of 'origin/dev' by 3 commits.                              
   (use "git push" to publish your local commits)                                
# 變成領先3個 commit                                                                                  
 nothing to commit, working tree clean                                           
# 看一下 log   
logo@sys:/xxx/test_sys$ git log -4
 df0c5db2d46c3f07118e0b6 (HEAD -> dev)                   
 Merge: bbd1613 97e1228                                                          
 Author: logo <logo@sys.sys.forblind.org.tw>                                     
 Date:   Tue Jan 12 16:06:27 2021 +0800                                          

     Merge branch 'dev' of 127.0.0.1:/xxx/yyyy into dev                          
# 第一個是 merge commit 遠端倉庫沒有                                                                                
 commit 97e1228aa7d70cf4d9ec984a6cc97b2595c2d3cb (origin/dev)                    
 Author: Logo-Kuo <logo@forblind.org.tw>                                         
 Date:   Tue Jan 12 12:51:55 2021 +0800                                          

     type: fix                                                                   
     system: leave                                                               
     scope: view/self/controller/model/js                                        
     subject: 在留停紀錄頁面加入查詢與刪除詳細留停紀錄功能                       

# 第二個,這個也是 pull 回來的 commit                                                                                 
 commit 93ac02e65ff295426c7c8a4c35634a53d3321077                                 
 Author: Logo-Kuo <logo@forblind.org.tw>                                         
 Date:   Tue Jan 12 15:54:14 2021 +0800                                          

     document pdf 3                                                              
# 第三個,這個也是 pull 回來的 commit                                                                                 
 commit bbd1613aabf14ca0504a17009bca3e1128c90832                                 
 Author: Logo-Kuo <logo@forblind.org.tw>                                         
 Date:   Tue Jan 12 12:51:55 2021 +0800                                          

     type: fix                                                                   
     system: leave                                                               
     scope: view/self/controller/model/js                                        
     subject: 在留停紀錄頁面加入查詢與刪除詳細留停紀錄功能                       
# 從這個開始才是舊的,兩邊分支完全一樣的地方

問題似乎解決了,但如果沒有 push 回去的話,之後就會一直要 merge 了。

先退後拉

讓我們回到還沒 pull 的狀態,還有沒有另外一種不要 merge 也不需要解決衝突的作法。

因為事情其實沒那麼複雜,既然我們 server 端這邊沒有推新的 commit 的話,

那就是完全以遠端倉庫的版本為主就好,這樣整個分支的架構也不會跟遠端倉庫不一制。

從之前的 status 看出有兩個不同 commit, 那我們 server 端就直接退兩個版本再拉回就好。

硬退版

這次我們沒有要把 commit 拆解到工作目錄,所以採用的是有加 --hard 的硬退版。

而且我退了三個版,反正超過兩個就好,理論上不管退幾個都沒關係的,

因為兩個 commit 之前的分支狀況是兩邊完全相同的。

其實,退三個的真正原因是我直接從 merge 完領先3個 commit 的狀態下操作的。

logo@sys:/xxx/test_sys$ git reset --hard HEAD~~~                                
# 也可以用 ~3
 HEAD is now at 4fe1529 type: fix system: leave scope: view/model/controller/self
 /js subject: 新增查詢所有員工的年資與留停紀錄                                   

# 看最新的 log 
logo@sys:/xxx/test_sys$ git log -1                                              
 commit 4fe152957fbd2e9a072861a1e3522d6e14ef1e2f (HEAD -> dev)                   
 Author: Logo-Kuo <logo@forblind.org.tw>                                         
 Date:   Fri Jan 8 22:36:17 2021 +0800                                           

     type: fix                                                                   
     system: leave                                                               
     scope: view/model/controller/self/js                                        
     subject: 新增查詢所有員工的年資與留停紀錄                                   

# 再看一下狀態                                                                                 
logo@sys:/xxx/test_sys$ git status                                              
 On branch dev                                                                   
 Your branch is behind 'origin/dev' by 2 commits, and can be fast-forwarded.     
   (use "git pull" to update your local branch)                                  

 nothing to commit, working tree clean                                           

# 變成落後兩個了,那就拉回來更新即可

logo@sys:/xxx/test_sys$ git pull origin dev --tags                              
 logo@127.0.0.1's password:                                                      
 From 127.0.0.1:/xxx/yyyy                                                        
  * branch            dev        -> FETCH_HEAD                                   
 Updating 4fe1529..97e1228                                                       
 Fast-forward                                                                    
  sys/controllers/leaveAdminController.php           | 20 ++++++                 
  sys/models/leaveAdminModel.php                     | 39 +++++++++++-           
  sys/self/settings.php                              |  8 +++                    
  sys/static/js/query_stay_time.js                   | 72 +++++++++++++++++++++- 
  sys/template/admin/leave/query_stay_time.tpl       | 43 +++++++++++--          
  web_data/sysLlibrary/PDF/sysPDF.php                | 30 ---------              
  .../sysLlibrary/PDF/template/document/document.tpl | 12 ++--                   
  7 files changed, 182 insertions(+), 42 deletions(-)                            

# 加了 --tags 是因為我們的 commit 有加版本標籤,這部分可參考之前的基礎教學
# 最後再看一下最新的兩個 commit

logo@sys:/xxx/test_sys$ git log -2                                              
 commit 97e1228aa7d70cf4d9ec984a6cc97b2595c2d3cb (HEAD -> dev, origin/dev)       
 Author: Logo-Kuo <logo@forblind.org.tw>                                         
 Date:   Tue Jan 12 12:51:55 2021 +0800                                          

     type: fix                                                                   
     system: leave                                                               
     scope: view/self/controller/model/js                                        
     subject: 在留停紀錄頁面加入查詢與刪除詳細留停紀錄功能                       

 commit 93ac02e65ff295426c7c8a4c35634a53d3321077                                 
 Author: Logo-Kuo <logo@forblind.org.tw>                                         
 Date:   Tue Jan 12 15:54:14 2021 +0800                                          

     document pdf 3                                                              

# 沒問題,新的有拉回來了
# 看狀態
logo@sys:/xxx/test_sys$ git status                                              
 On branch dev                                                                   
 Your branch is up to date with 'origin/dev'.                                    

 nothing to commit, working tree clean                                           

終於可以收工了

結語

其實所有操作在之前的文章都有提過,但還是覺得應該多幾次實務操作讓大家熟悉。

之前關於其他合作伙伴的部分都是簡單幾句話說明,現在會儘可能呈現實際操作過程。

但也因為這樣文章會變得比較冗長。