使用`git commit -a`时,可以在git`pre-commit`钩子中找到暂存的文件。

时间:2019-01-24 17:47:09

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

我正在使用git pre-commit挂钩来自动格式化所有暂存的文件。我正在通过git diff --name-only --cached确定暂存的文件,然后在这些文件上调用脚本。 所有这些在标准用例中都可以很好地工作,但是当我通过

提交时却无法工作
git commit -a ..

因为文件尚未暂存。

有什么方法可以

  1. -a钩子之前运行pre-commit效果(将文件添加到临时区域)?

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

必须有一种处理方法。

1 个答案:

答案 0 :(得分:1)

  

因为文件尚未暂存

这实际上不是真的。但这也不是完全错误的。

这是一个(愚蠢的,仅供参考)预提交钩子,用于演示问题:

$ cat .git/hooks/pre-commit
#! /bin/sh
echo \$GIT_INDEX_FILE = $GIT_INDEX_FILE
git diff-index --cached --name-only HEAD
exit 1

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

我使该可执行文件(在Git本身的Git存储库中),并修改了一些文件,而没有git add对其进行修饰:

$ git status --short
 M Makefile
 M wt-status.c

(请注意M在第二列中)。然后:

$ git commit
$GIT_INDEX_FILE = .git/index
$ git commit -a
$GIT_INDEX_FILE = [redacted]/.git/index.lock
Makefile
wt-status.c

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

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

让我们继续做一件事:我将git add修改为Makefile,然后对Makefile进行第二次更改。现在我们有:

$ git status --short
MM Makefile
 M wt-status.c

第一行告诉我们HEAD:Makefile(在提交中,冻结)与:Makefile(在索引中,暂存)不同,而Makefile$ git show HEAD:Makefile | head -2 # The default target of this Makefile is... all:: $ git show :Makefile | head -2 # # The default target of this Makefile is... $ head -2 Makefile # different # The default target of this Makefile is... (在工作树中,未分级),的确,我们可以看到这三个文件是不同的:

git commit

运行git commit -a$ git commit $GIT_INDEX_FILE = .git/index Makefile $ git commit -a $GIT_INDEX_FILE = [redacted]/.git/index.lock Makefile wt-status.c 现在会产生:

-a

如果我没有阻止git commit的非git commit版本,那么Makefile将提交的 就是{{1} }(主要/实数/ .git/index)索引中的},而不是工作树中的版本。因此,如果要检查将提交的文件,则应在索引中查找。您可以使用git checkout-index从索引中提取文件 ,但是请注意不要破坏工作树的版本,

git commit -a会提交的是工作树中Makefile的版本,Git已将其添加到(非标准,临时).git/index.lock索引中。 git commit -a完成后,该非标准临时索引将成为真实索引,从而破坏了我的Makefile的中间特殊分段副本。再次,要检查将要提交的文件,请像使用Git一样自动使用重定向索引为git diff-indexgit checkout-index查找索引。

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

(另请参阅我对Skip past (full) staging area and commit file or patch directly?的回答,其中仅讨论-a--only--include在内部的实际作用。)