
Git pre-commit 钩子原理解析
来源标题:Anatomy of a Git pre-commit Hook
Git 钩子机制允许脚本在特定事件触发时自动执行。pre-commit 钩子在提交前运行,首行 she-bang 指定执行程序,且各钩子传入的参数并不统一。
以下正文由 AI 翻译自 Hacker News 最新(原文版权归原站所有),可能存在偏差,重要内容请以原文为准。
git 里有好几种不同的钩子(“Git Hook”),这些钩子让你能“挂”进 git 的某个事件里。 可以挂载的事件很多,有些发生在客户端,有些发生在你的“服务器”上。这里我们假定“服务器”指的是团队所有人推送提交的那个中央仓库(git 原教旨主义者听到这个说法会不高兴,但在这个媒介里也只能这么讲了)。 今天,我重点讲一个特定的 git 钩子:pre-commit。 git 钩子的第一行(感谢 unix)是 She-bang 行。这一行告诉 shell 用哪个程序来执行这个脚本。(She-bang,读作“Shhhh-bang”,指的就是 #! 后面跟着执行脚本所用二进制程序的路径): #! /usr/bin/env/node 在这之后,脚本开始执行,不同的钩子会向脚本传入不同的参数。对于 pre-commit 钩子来说,git 有一些有意思的特性,让它不那么像程序员写的,反而更像系统管理员写的。 git 没有统一的 API;作为程序员,我们可能以为所有东西都会作为参数传进钩子,但 git 并不是这样工作的。git 把钩子当作和 git 运行在同一系统上的脚本,就好像这些脚本在和 git(以及操作系统)自己的文件系统交互一样。 由此产生的一个(也许很离谱的)结果是:git 的某些交互会创建文件。当你用 -m 选项添加提交信息时(甚至当你不用 -m、让编辑器弹出来时),它实际上会在 .git 目录里创建一个叫 “COMMIT_EDITMSG” 的文件。 查看这个文件,就能看到用户刚刚试图用于提交这些文件的提交信息。如果你想基于提交信息来写脚本,这个文件里就包含提交信息。 git pre-commit 钩子的下一个特性是:退出机制遵循 unix 惯例。exit(0) 表示成功,exit(1) 表示失败。 如果你想访问因这次提交而改动的文件(比如,在允许提交之前确保单元测试通过),有一个很大的问题,不碰上几次是看不出来的:大多数 git pre-commit 钩子会遍历你工作目录里的文件,哪怕你只暂存了部分改动。这意味着你本地副本的状态和实际将要提交的内容并不一致。 git 没有提供简单的方法来查看将要提交什么;所以,如果你想检查即将提交的文件,并且需要绝对确保仓库的状态能反映构建服务器上会发生什么,你就得做一些体操。从这里开始,我会引用 John Wiegley 那个出色的、能做到这一点的 git pre-commit 钩子。你可能不需要这么极端的做法,但它确实能解决问题。 git checkout-index --prefix=$MIRROR/ -af git 的 checkout-index 会列出索引中的文件(本次提交之前已提交的文件);f 选项表示 force,a 选项表示“all”。checkout-index 关注的是 git 索引中的文件,而不一定是 git 目录文件系统上存在的所有文件。例如,已暂存的文件,或者已改动但未提交的文件,在索引中的副本会和工作目录中的副本不同。 2. 从 MIRROR 中删除索引里已不存在的文件 git diff-index --cached --name-only --diff-filter=D -z HEAD | (cd $MIRROR && xargs -0 rm -f --) 这部分会删除镜像中与 HEAD 修订版(HEAD 指向你“最新”的工作成果)不一致的任何文件。 3. 只把正确的文件移动到 $TMPDIR。 rsync -rlpgoDO --size-only --delete --exclude-from=tools/excludes $MIRROR/ $TMPDIR/ 最后,它会把根据本次提交而改动的文件拿出来,移动到某个目录($TMPDIR)。 做完这些脑力体操之后,你终于可以在 pre-commit 脚本中针对这个新镜像运行单元测试了。 需要再次强调的是,只有当你想要绝对确保仓库与构建服务器上发生的情况一致时,上面这些体操才是必需的。 John 的 githook 完整内容在这里;从中可以总结出几点: git 钩子(并非全部)存在于本地仓库中,并且会遇到与你直接操作仓库时相同的问题。它们是 shell(或 node、perl、python)脚本,能访问到你能访问到的同样的信息。 处理像 pre-commit 这样的 git 钩子时,你至少需要时刻注意三种状态: 工作目录中你已经提交的改动 工作目录中你已经暂存、但尚未提交的改动 工作目录中所有既未暂存、也未提交、也未跟踪的文件 在后续部分,我们会深入探讨 git 钩子的其他有趣用法——这里的重点在于,git 非常强大,可以用来自动化你的流程,既不用担心供应商锁定,又能获得和你已经提交改动之后一样的即时反馈。
正文由 探How 从来源站点 RSS 同步,内容未经改写;遇到排版缺失或需要图片、视频时请以原文为准。