【问题标题】:How can I tell if git was executed with the "-a" flag in a pre-commit hook?如何判断 git 是否在预提交挂钩中使用“-a”标志执行?
【发布时间】:2017-05-13 03:14:02
【问题描述】:

我有一个执行 linting 的 git 预提交钩子。当它被调用时,它会遍历暂存文件并在它们上运行 linter。这很好用。

但是,当您运行 git commit -am 'Foo' 时,它运行时没有任何暂存文件。如何判断它是使用 -a 还是 --all 标志调用的?有没有更简单的方法来获取将存储在 git 中的文件?

【问题讨论】:

  • 您所描述的情况并非如此。无论您调用commit,预提交都会使用设置为即将提交的索引和HEAD 设置适当的索引来执行,以便您可以git diff --cached --name-only 或您需要做的任何其他事情。
  • 我正在使用pygit2。当我使用未暂存的文件调用 repo.status().items() 时,我得到如下信息:[('config/git_hooks/pre-commit', 256), ('bin/run_flake8', 256)]256 是 GIT_STATUS_WT_MODIFIED 的标志。
  • 我没有看过 pygit2(我在 git 1.[567]、python 2.[345] 时代写了我自己的 Python Git 东西,但那是几个工作之前的事了,可能长期丢弃)但值得注意的是git status两个 diff,一个用于index-vs-HEAD,一个用于worktree-vs-index。 Pygit2 可能会尝试做同样的事情,但如果是这样,它就会出错,如果你是在 pre-commit 钩子中执行此操作并运行 git commit -a

标签: git githooks git-commit pre-commit-hook


【解决方案1】:

所有索引中的文件将被存储。您正在寻找“索引中与 HEAD 中的对应文件不同的文件”,您可以使用 git diff 找到这些文件,或者对于脚本,git diff-index

请注意,暂存版本也可能与工作树版本不同,这使得检查所有内容特别烦人和棘手。 (例如,对一些复杂的更改运行git add -p,然后选择其中的部分。)

这是一个虚拟预提交挂钩的示例,它显示每个文件相对于 HEAD 的名称和状态,即索引与现有 HEAD 提交的不同之处。

#! /bin/sh

git diff-index --cached -r --name-status HEAD

echo pre-commit fail
exit 1

您的任务是获取来自git diff-index --cached -r --name-status HEAD 的输出(可能添加了-z,也可能没有)并弄清楚如何测试索引中的版本,而不是工作树中的版本。

请注意,您可以使用git checkout-index 将索引提取到工作树。当然,您需要避免覆盖 real 工作树,即在别处建立临时工作树:

TMPTREE=$(mktemp -d)
...
git --work-tree=$TMPTREE checkout-index -- .

例如。您可能还想为此建立一个临时索引,而不是常规索引,因为这可能会干扰常规索引的缓存方面:

TMPINDEX=$(mktemp)
NORMINDEX=${GIT_INDEX_FILE:-$(git rev-parse --git-dir)/.index}
cp $NORMINDEX $TMPINDEX
GIT_INDEX_FILE=$TMPINDEX GIT_WORK_TREE=$TMPTREE checkout-index -- .

请务必在完成后清理您的临时文件和/或目录。

(这些代码片段均未​​经过测试。)

【讨论】:

    猜你喜欢
    • 2021-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-03
    • 2011-04-18
    相关资源
    最近更新 更多