Node.js 可选的githook作为非可选的
我试图在我的工作流程中使用Node.js 可选的githook作为非可选的,node.js,git,shell,githooks,post-checkout-hook,Node.js,Git,Shell,Githooks,Post Checkout Hook,我试图在我的工作流程中使用post merge和post checkoutgit挂钩 #!/usr/bin/env bash # MIT © Sindre Sorhus - sindresorhus.com # git hook to run a command after `git pull` if a specified file was changed # Run `chmod +x post-merge` to make it executable then put it into `
post merge
和post checkout
git挂钩
#!/usr/bin/env bash
# MIT © Sindre Sorhus - sindresorhus.com
# git hook to run a command after `git pull` if a specified file was changed
# Run `chmod +x post-merge` to make it executable then put it into `.git/hooks/`.
changed_files="$(git diff-tree -r --name-only --no-commit-id ORIG_HEAD HEAD)"
check_run() {
echo "$changed_files" | grep --quiet "$1" && eval "$2"
}
# Example usage
# In this example it's used to run `npm install` if package.json changed
check_run package.json "npm install"
这声明仅在package.json
文件更改时运行npm安装
然而,我在所有的机器上都试过这个。无论package.json是否已更改,npm install命令都会运行
为了测试这一点,我在当前提交时创建了一个新分支,然后将其签出,从而触发了签出后git钩子。我不希望运行npm install
,因为package.json
没有改变
目视验证(注意npm警告文本):
ORIG_HEAD
应替换为HEAD@{1}
,如本所述,ORIG_HEAD
是一种旧的、不太可靠的获取头部先前状态的方法。就我而言,它没有被设置。TL;博士
使用另一个签出后钩子,它使用$1
而不是原始头
。(或者,检查参数的数量,以确定您是作为签出后钩子调用还是作为合并后钩子调用,以获得相同的效果。或者,如果您知道reflogs始终处于启用状态,请使用HEAD@{1}
获取HEAD
的上一个值)
讨论
在合并后钩子中使用ORIG_HEAD
是有意义的,因为git merge
将ORIG_HEAD
设置为合并前的当前提交。(如果合并是真正的合并,而不是快进,则由merge\u HEAD
标识的提交和由HEAD^1
标识的提交必然相同。但是,如果合并是快进,则只有merge\u HEAD
和reflog才能找到存储在HEAD中的上一个提交哈希
合并前。)
然而,在签出后挂钩中使用ORIG\u HEAD
显然是错误的,因为git checkout
没有设置ORIG\u HEAD
。这意味着,如果ORIG_HEAD
甚至存在,它实际上指向一些随机提交。(当然,它实际上解析为上次更新它的任何命令留下的任何提交:git merge
、git rebase
,或任何其他写入ORIG_HEAD
的命令。但这里的要点是,它与签出之前的当前提交没有任何关系。):
给出了三个参数:
以前的头部,新头部的参考(可能有也可能没有
已更改),以及指示签出是否为分支的标志
签出(更改分支,标志=1)或文件签出(检索
索引中的文件,标志=0)。这个钩子不能影响结果
git结帐
(最后一句话不太正确。尽管签出后钩子无法阻止签出更新索引和工作树,但它可以覆盖各种工作树或索引内容,如果它产生故障退出状态,它会导致git checkout
本身也产生故障退出状态。)
这一切都意味着您需要在签出后钩子中执行不同的操作:使用第一个参数$1
,获取前一个头的哈希ID
。请注意,在特殊情况下,1签出后钩子是在初始的git克隆上运行的,因此$1
可以是null-ref(我现在很好奇,当您使用git checkout--orphan
时是什么,然后也不创建新的分支。看起来$1
也可能是null-ref。)
1让签出后钩子在git clone
上运行的唯一方法是让git clone
安装签出后钩子。这通常是不可能的,但可以通过将您的Git指向您自己的模板目录来实现,该目录具有实际挂钩,而不仅仅是示例挂钩。Torek提到:
最后一句话不太正确
尽管签出后钩子无法阻止签出更新索引和工作树,但它可以覆盖各种工作树或索引内容,如果它产生故障退出状态,它会导致git签出本身也产生故障退出状态
现在(2020年第4季度,3年后)正式记录在Git 2.29中:
参见作者(2020年8月27日)
(于2020年9月3日合并)
:阐明如何使用签出后挂钩的退出状态
因为钩子在主签出操作完成后运行,所以它不会影响哪个分支将是当前分支、工作树中更新的路径等,这被描述为“不会影响“签出”的结果”
但是,钩子的exit
状态被用作“checkout
”命令的exit
状态,并且任何生成“checkout
”的人都可以看到它,文档中缺少它。
解决这个问题
githooks
现在在其
此钩子不会影响git开关
或git签出
的结果,
除此之外,钩子的退出状态成为这两个命令的退出状态
使用HEAD@(1)
仅在启用重登录时有效。(当然,他们可能是。)关于代码的一些不相关的问题。现在,我在上面看到的内容下面添加了另一行,内容是check\u run.gitmodules“git submodule udpate”
,但由于某些原因,如果package.json保持不变,它就永远不会转到新行。有什么想法吗?这似乎很奇怪。要调试脚本,设置-x
(或将-x
添加到#!
行上的标志中)在这里可能不可行,这取决于内核和#!解释),您可以看到它运行每个命令。我将在这里注意到,udpate
有一个打字错误(替换为d和p),但是是cour
This hook cannot affect the outcome of git checkout.