git 的 hook 机制:
钩子(hooks)是一些在$GIT-DIR/hooks
目录的脚本, 在被特定的事件(certain points)触发后被调用。当git init
命令被调用后, 一些非常有用的示例钩子脚本被拷到新仓库的hooks目录中; 但是在默认情况下它们是不生效的。 把这些钩子文件的".sample"文件名后缀去掉就可以使它们生效。
hook机制可以理解为回调.各个钩子其实就是一段 bash 脚本,各钩子脚本的名字都是固定的.可以查看git项目根目录下的 .git/hooks 这个文件夹,看看都有哪些可用的钩子.
$ cd project_dir
$ ls .git /hooks/
applypatch-msg.sample commit-msg.sample pre-applypatch.sample prepare-commit-msg.sample pre-rebase.sample
commit-msg post-update.sample pre-commit.sample pre-push.sample update.sample
|
如果有自己感兴趣的 git 事件要处理,修改相应的钩子脚本罗辑即可.然后把 .sample 后缀去掉,钩子就生效了.
在 gerrit 的 Change-Id 生成机制中,其实 gerrit 就是利用了 commit-msg 的钩子,在我们提交代码后,按一定规则去修改了我们的提交日志,在其末尾添加了这么一行:
Change-Id: .......
这个钩子脚本是什么时候被加入我们的项目中的呢? 其实就是你在 git push 出错时 gerrit 网站给你的提示中的那句命令:
$ gitdir=$(git rev-parse --git- dir ); scp -p -P 29418 liux@gerrit.kaiba315.com:hooks /commit-msg ${gitdir} /hooks/
|
执行该命令即可得到生成 Change-Id 的钩子脚本. 这条命令做了以下事情:
// git rev-parse --git- dir 这条命令将找到该项目的 git 目录,并将其赋值给 gitdir 这个变量.
// 一般就是项目根目录下的 .git/ 这个目录.
$ gitdir=$(git rev-parse --git- dir )
// 执行 scp 命令,从 gerrit 代码服务器将钩子脚本文件 commit-msg 下载到项目的钩子目录下 (一般是 .git /hooks/ )
$ scp -p -P 29418 liux@gerrit.kaiba315.com:hooks /commit-msg ${gitdir} /hooks/
|
查看该脚本,会发现它是用 awk 命令处理了 .git/COMMIT_EDITMSG 这个文件.
所以如果想手动生成 Change-Id ,只要执行下面命令,就可以生成一个可用的 Change-Id:
$ cd project_dir
$ echo "some commit" > /tmp/test_generate_change_id
$ .git /hooks/commit-msg /tmp/test_generate_change_id
$ cat /tmp/test_generate_change_id
some commit
Change-Id: Ic89d5ce6ce4de70d1dcb315ce543c86a2b3ac003
|
利用 git commit --amend 重新生成 Change-Id 的原理:
git commit --amend , 看名字就知道,是对某个 commit 做出修改的.这种修改既可以包含文件修改,也可以仅包含提交日志修改.
我们用 --amend 对 commit 做出修改后, commit-msg 的钩子会被重新触发, Change-Id 就会被生成出来.
用交互式 git rebase 来生成 Change-Id 也是同一个道理.
另:
通过总结历次缺失 Change-Id 的例子,发现基本我们自己通过 git commit 生成的提交都会很顺利的生成 Change-Id.
通过 git merge, git revert 等命令由 git 自己生成的 commit 则有较高概率会缺失 Change-Id.
嗯,我们发现了一个伟大的定律! 然并卵... 并不知道怎么解决这个问题.
因此提倡尽量用 git rebase 代替 git merge 来更新代码.
事实上, git rebase 更新代码 相较 git merge 更新代码,有诸多优势,只是略复杂些.强烈建议用 git rebase 方式更新代码.
git rebase -i:
// TODO: 待续...