【问题标题】:Find out staged files in git `pre-commit` hook when using `git commit -a`使用`git commit -a`时找出git`pre-commit`钩子中的暂存文件
【发布时间】:2019-06-18 12:57:58
【问题描述】:

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

git commit -a ..

因为文件尚未暂存。

有没有办法:

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

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

一定有办法解决这个问题。

【问题讨论】:

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


    【解决方案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 adding 他们:

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

    (注意Ms 在第二列)。那么:

    $ 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 commitgit 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-indexgit checkout-index 提供。

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

    (另请参阅我对Skip past (full) staging area and commit file or patch directly? 的回答,其中讨论了-a--only--include 真正在内部做什么。)

    【讨论】:

      猜你喜欢
      • 2014-06-27
      • 1970-01-01
      • 2017-05-15
      • 2014-02-15
      • 1970-01-01
      • 2021-03-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多