在使用 `git commit -a` 时找出 git `pre-commit` 挂钩中的暂存文件
Find out staged files in git `pre-commit` hook when using `git commit -a`
我正在使用 git
pre-commit
挂钩来自动格式化我所有暂存的文件。我正在通过 git diff --name-only --cached
确定暂存文件,然后对这些文件调用脚本。
这一切在标准用例中都运行良好,但是当我通过
提交时它不起作用
git commit -a ..
因为文件尚未暂存。
有什么方法可以:
运行 -a
效果(添加文件到暂存区)在 pre-commit
钩子之前?
发现预提交在 -a
提交中运行?
一定有办法解决这个问题。
because the files are not yet staged
事实并非如此。但这也不完全是假的。
这是一个(愚蠢的,仅供说明之用)预提交挂钩来演示问题:
$ 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
ing 的情况下修改了一些文件:
$ 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
(在工作中- tree, unstaged), 事实上, 我们可以看到三个文件是不同的:
$ 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
vs 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
如果我没有阻止 git commit
的非 -a
版本,git commit
会 提交的是版本Makefile
在 (main / real / .git/index
) 索引中,而不是工作树中的版本。因此,如果你想检查将要提交的文件,你应该查看索引。您可以使用 git checkout-index
从 索引中提取文件 ,但要注意不要破坏可能不同的工作树版本。
git commit -a
提交的是工作树中 Makefile 的版本,Git 已经添加到(非标准,临时).git/index.lock
指数。一旦 git commit -a
完成,那个非标准的临时索引将成为真正的索引,破坏我的 Makefile
的中间、特殊阶段副本。同样,要检查将要提交的文件,请查看索引——使用重定向索引,因为 Git 会自动为 git diff-index
和 git checkout-index
.
(因为我不太清楚你的脚本需要什么,所以我无法就如何使用 git checkout-index
提取感兴趣的文件提出具体建议。考虑使用 --work-tree=
和不过是一个临时目录。)
(另见我对 的回答,其中讨论了 -a
、--only
和 --include
在内部真正做的事情。)
我正在使用 git
pre-commit
挂钩来自动格式化我所有暂存的文件。我正在通过 git diff --name-only --cached
确定暂存文件,然后对这些文件调用脚本。
这一切在标准用例中都运行良好,但是当我通过
git commit -a ..
因为文件尚未暂存。
有什么方法可以:
运行
-a
效果(添加文件到暂存区)在pre-commit
钩子之前?发现预提交在
-a
提交中运行?
一定有办法解决这个问题。
because the files are not yet staged
事实并非如此。但这也不完全是假的。
这是一个(愚蠢的,仅供说明之用)预提交挂钩来演示问题:
$ 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
ing 的情况下修改了一些文件:
$ 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
(在工作中- tree, unstaged), 事实上, 我们可以看到三个文件是不同的:
$ 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
vs 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
如果我没有阻止 git commit
的非 -a
版本,git commit
会 提交的是版本Makefile
在 (main / real / .git/index
) 索引中,而不是工作树中的版本。因此,如果你想检查将要提交的文件,你应该查看索引。您可以使用 git checkout-index
从 索引中提取文件 ,但要注意不要破坏可能不同的工作树版本。
git commit -a
提交的是工作树中 Makefile 的版本,Git 已经添加到(非标准,临时).git/index.lock
指数。一旦 git commit -a
完成,那个非标准的临时索引将成为真正的索引,破坏我的 Makefile
的中间、特殊阶段副本。同样,要检查将要提交的文件,请查看索引——使用重定向索引,因为 Git 会自动为 git diff-index
和 git checkout-index
.
(因为我不太清楚你的脚本需要什么,所以我无法就如何使用 git checkout-index
提取感兴趣的文件提出具体建议。考虑使用 --work-tree=
和不过是一个临时目录。)
(另见我对 -a
、--only
和 --include
在内部真正做的事情。)