gerrit "missing Change-Id"

syrchina發表於2018-07-10

本系列是為公司寫的 git & gerrit 場景使用手冊的一篇.

套路部分為解決問題的步驟,心法部分為所用到的知識點的梳理.


場景:


你用 git push 向 gerrit 提交了待稽核程式碼,一切都很順利,你腦袋裡冒出了"程式碼頭上加了'佛祖保佑'果然有效"的想法.

此時 git 列印出如下提示,你的內心OS同步列印 "心情 -5" :

remote: Resolving deltas: 100% (14/14)
remote: Processing changes: refs: 1,done   
remote: ERROR: missing Change-Idincommit message footer
remote:
remote: Hint: To automatically insert Change-Id,installthe hook:
remote:   gitdir=$(git rev-parse --git-dir);scp-p -P 29418 liux@gerrit.xxxxx.com:hooks/commit-msg${gitdir}/hooks/
remote: And then amend the commit:
remote:   git commit --amend
remote:
To ssh://liux@121.xx.xx.xx:29418/kaiba_admin_yunying.git
 ! [remote rejected] HEAD -> refs/for/master(missing Change-Idincommit message footer)
error: failed to push some refs to'ssh://liux@121.xx.xx.xx:29418/sample_project.git'

 



套路:


大前提: commit-msg 檔案必須已經在該專案中存在.


使用ls命令檢查該檔案是否存在:

cd project_dir
ls .git/hooks/commit-msg

如果該檔案不存在,則按照 git push 時產生的提示資訊,獲取該檔案:

$ gitdir=$(git rev-parse --git-dir);scp-p -P 29418 liux@gerrit.xxxxx.com:hooks/commit-msg${gitdir}/hooks/

上面的命令可以直接從 git push 產生的錯誤資訊中複製出來.

如果要手敲該命令,別忘了把使用者名稱換成自己的.


方法一: 使用 amend 選項生成 Change-Id:


如果缺失 Change-Id 的是最後一個 (head) commit, 使用以下命令即可解決問題:

$ git commit --amend

該命令會開啟預設的 commit message 編輯器,一般是 vi.

這時什麼都不用修改,直接儲存退出即可 (:wq).

再次檢視 git log,就會發現缺失的 Change-Id 已經被補上了. 再次 git push 即可.


方法二: 如果缺失 Change-Id 的不是最後一個 commit, 可用 reset 方法:


比如,如果缺失 Change-Id 的 commit 是 git log 中的第二個 commit, 則可以用 git reset 命令將本地分支回退到該 commit.

(但其實用 git reset 找回 Change-Id 是普通青年才幹的事情,文藝青年有更優雅的辦法.見方法三)

首先執行 git log, 找出缺失了 Change-Id 的 commit,並複製其 commit-id:

$ git log
commit 8e1cad33bcd98e175cba710b1eacfd631a5dda41
Author: liux <liux@xxxx.cn>
Date:   Mon Dec 19 17:43:00 2016 +0800
 
    testcommit"with amended commit message"
     
    Change-Id: I9d2af0cc31423cf808cd235de0ad02abf451937d
 
commit 1a9096a34322885ac101175ddcac7dab4c52665d
Author: liux <liux@xxxx.cn>
Date:   Mon Dec 19 15:23:36 2016 +0800
 
    testcommit-msg hook
 
......

發現是第二個 commit 缺失 Change-Id. 將程式碼 reset 到這個 commit, 並執行 amend:

$ git reset 1a9096a34322885ac101175ddcac7dab4c52665d
$ git commit --amend

注: 上面的 git reset 用法不會毀滅你寫的程式碼,放心執行即可.

這時 git log 可以發現該 commit 已經補全了 change-Id.

下一步是把 git reset 撤消掉的程式碼重新 commit, 然後 push 即可:

$ git add ......
$ git commit -m "你的提交日誌"
$ git push review HEAD:refs/for/master


方法三: 使用互動式 rebase 找回任意提交位置的 Change-Id:


前面方法二中給出的例子是第二個提交缺失 Change-Id,這時用 git reset 還可以解決問題.

但如果你在一個方案上已經工作了一個月,生成了100個本地 commit,提交時才發現 git log 中第99個 commit 缺失 Change-Id. 如果這時還用 git reset 來找回 Change-Id ......

不要香菇,不要藍瘦.文藝青年表示有辦法優雅的解決問題: 互動式 rebase.


第一步,找到缺失 Change-Id 的那個 commit:

$ git log
commit 8aaaa749db4a5b105aa746659c5cd266ac82fffe
Author: liux <liux@xxxx.cn>
Date:   Mon Dec 19 17:43:24 2016 +0800
 
    I am commit message 3
     
    Change-Id: Ic89d5ce6ce4de70d1dcb315ce543c86a2b3ac003
 
commit 8e1cad33bcd98e175cba710b1eacfd631a5dda41
Author: liux <liux@xxxx.cn>
Date:   Mon Dec 19 17:43:00 2016 +0800
 
    I am commit message 2
     
    Change-Id: I9d2af0cc31423cf808cd235de0ad02abf451937d
 
commit 1a9096a34322885ac101175ddcac7dab4c52665d
Author: liux <liux@xxxx.cn>
Date:   Mon Dec 19 15:23:36 2016 +0800
 
    I am commit message 1
 
commit d714bcde0c14ba4622d28952c4b2a80882b19927
Author: shangsb <shangsb@czfw.cn>
Date:   Wed Dec 14 09:20:52 2016 +0800
 
    這是一個提交
     
    Change-Id: I629b2bedff95491875f63634ad3da199612735b6
......

發現是 "I am commit message 1" 這個提交沒有 Change-Id.


第二步,編輯互動式 rebase 的命令檔案:

執行 git rebase -i, 引數為 該提交的上一個提交的 commit-id (本例中為 "表單" 那個提交):

$ git rebase -i d714bcde0c14ba4622d28952c4b2a80882b19927

這個命令會開啟預設的編輯器,一般為 vi. 內容如下:

pick 1a9096a I am commit message 1
pick 8e1cad3 I am commit message 2
pick 8aaaa74 I am commit message 3
# Rebase d714bcd..8aaaa74 onto d714bcd
#
# Commands:
#  p, pick = use commit
#  r, reword = use commit, but edit the commit message
#  e, edit = use commit, but stop for amending
#  s, squash = use commit, but meld into previous commit
#  f, fixup = like "squash", but discard this commit's log message
#  x, exec = run command (the rest of the line) using shell
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out

可以將這個檔案理解為 git rebase 的內嵌指令碼.其命令寫法已經在下面的註釋裡給出了.

這裡不贅述,僅給出最終要將該檔案編輯成什麼樣子:

reword 1a9096a I am commit message 1
pick 8e1cad3 I am commit message 2
pick 8aaaa74 I am commit message 3
# Rebase d714bcd..8aaaa74 onto d714bcd
#
# Commands:
#  p, pick = use commit
#  r, reword = use commit, but edit the commit message
#  e, edit = use commit, but stop for amending
#  s, squash = use commit, but meld into previous commit
#  f, fixup = like "squash", but discard this commit's log message
#  x, exec = run command (the rest of the line) using shell
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out

即: 將缺失了 Change-Id 的 commit 前面的 "pick" 改為 "reword" 即可. 儲存退出 (:wq)

注1: 上述檔案中 commit 的順序是和 git log 顯示的順序相反的: git log 為最新的在最前; 上述檔案為 最新的在最後.

注2: 如果進入該模式後,卻不確定該怎麼改,這時不要擔心,直接退出編輯則什麼都不會發生 (:q!)

注3: 如果沒有搞清楚運作機制,就要注意,除了按需把 pick 改為 reword 外,不要做其他改動.尤其注意不要刪除任何行 (被刪除的那行對應的提交將丟失).

注4: 你應該已經發現,有多個 commit 缺失 Change-Id 的情況也可以用該方法一次性處理.


第三步,逐個編輯 commit-msg:

上一步開啟的檔案儲存退出後,git會逐個開啟被你標註了 reword 的提交日誌頁面.

不需要修改任何東西,逐個儲存退出即可 (一路 :wq).


第四步,再次提交:

用 git log 檢視提交日誌,會發現缺失的 Change-Id 都生成了. 愉快的提交程式碼吧!

$ git push review HEAD:refs/for/master

 from: https://blog.csdn.net/liuxu0703/article/details/54343096

相關文章