使用 `git commit -a` 时查找 git `pre-commit` 挂钩中的暂存文件

knu*_*nub 5 git pre-commit-hook githooks git-commit

我正在使用一个git pre-commit钩子来自动格式化所有暂存文件。我通过确定暂存文件git diff --name-only --cached,然后在这些文件上调用脚本。这一切在标准用例中都运行良好,但是当我通过提交时它不起作用

git commit -a ..
Run Code Online (Sandbox Code Playgroud)

因为文件尚未暂存。

有什么方法可以:

  1. 在钩子之前运行-a效果(将文件添加到暂存区)pre-commit

  2. 发现预提交在-a提交中运行?

一定有办法处理这个问题。

tor*_*rek 11

\n

因为文件还没有暂存

\n
\n\n

这实际上并不完全正确。但这也不是完全错误的。

\n\n

这是一个(愚蠢的,仅用于说明)预提交挂钩来演示该问题:

\n\n
$ cat .git/hooks/pre-commit\n#! /bin/sh\necho \\$GIT_INDEX_FILE = $GIT_INDEX_FILE\ngit diff-index --cached --name-only HEAD\nexit 1\n
Run Code Online (Sandbox Code Playgroud)\n\n

该挂钩使用正确的(无论如何从可靠性角度来看)命令git diff-index --cached HEAD来查找暂存文件的名称。但首先,它会打印用于提交文件的索引的名称。(最后,它阻止了提交,因为我真的不想提交任何这些。)

\n\n

我制作了这个可执行文件(在 Git 本身的 Git 存储库中),并修改了一些文件而不git add使用它们:

\n\n
$ git status --short\n M Makefile\n M wt-status.c\n
Run Code Online (Sandbox Code Playgroud)\n\n

(请注意,Ms 位于第二列)。然后:

\n\n
$ git commit\n$GIT_INDEX_FILE = .git/index\n$ git commit -a\n$GIT_INDEX_FILE = [redacted]/.git/index.lock\nMakefile\nwt-status.c\n
Run Code Online (Sandbox Code Playgroud)\n\n

第一个钩子调用echo告诉我们,我们正在使用真实的(主)索引,并且它git diff-index不会产生任何输出。

\n\n

第二次调用告诉我们,我们正在使用一个备用索引文件,名为.git/index.lock(我修剪了源路径)。它显示两个暂存文件。

\n\n

让我们继续做另一件事:我将git add修改Makefile并对Makefile. 现在我们有:

\n\n
$ git status --short\nMM Makefile\n M wt-status.c\n
Run Code Online (Sandbox Code Playgroud)\n\n

第一行向我们展示了HEAD:Makefile(在提交中,冻结)与:Makefile(在索引中,暂存)不同,Makefile而(在工作树中,未暂存)不同,事实上,我们可以看到这三个文件是不同的:

\n\n
$ git show HEAD:Makefile | head -2\n# The default target of this Makefile is...\nall::\n$ git show :Makefile | head -2\n#\n# The default target of this Makefile is...\n$ head -2 Makefile\n# different\n# The default target of this Makefile is...\n
Run Code Online (Sandbox Code Playgroud)\n\n

运行git commitvsgit commit -a现在会产生:

\n\n
$ git commit\n$GIT_INDEX_FILE = .git/index\nMakefile\n$ git commit -a\n$GIT_INDEX_FILE = [redacted]/.git/index.lock\nMakefile\nwt-status.c\n
Run Code Online (Sandbox Code Playgroud)\n\n

如果我没有阻止 的非-a版本git commit,则提交的是(main / real / ) 索引中git commit的版本,而不是工作树中的版本。因此,如果您想检查将提交的文件,您应该查看索引。您可以使用它索引中提取文件,但请注意不要破坏工作树版本,因为工作树版本可能有所不同。Makefile.git/indexgit checkout-index

\n\n

提交的git commit -a是工作树中 Makefile 的版本,Git 已将其添加到(非标准的、临时的).git/index.lock索引中。一旦git commit -a完成,那个非标准临时索引将成为真正的索引,破坏我的中间的、特殊的分阶段副本Makefile。同样,要检查将提交的文件,请使用重定向索引查找索引\xe2\x80\x94,Git 会自动检查git diff-indexgit checkout-index

\n\n

(由于我不太清楚您的脚本需要什么,因此我无法就如何使用git checkout-index提取感兴趣的文件提出具体建议。--work-tree=不过,请考虑使用临时目录。)

\n\n

(另请参阅我对“跳过(完整)暂存区域并直接提交文件或补丁?”的回答,其中讨论了-a--only、 和--include真正在内部做什么。)

\n