代码之家  ›  专栏  ›  技术社区  ›  M_M

(如何)我可以在预提交挂钩内运行git签出?

  •  0
  • M_M  · 技术社区  · 8 年前

    也许 通常 不应将更改签回。

    因此,我编写了一个预提交挂钩,它成功地询问用户是否确定要将更改提交到此文件。如果他们说是,文件被签入(钩子返回0,提交继续),如果不是,提交被中止。

    我希望用户可以选择恢复对文件的更改并继续提交,而不是放弃。

    要将文件还原为未更改的状态,我使用 git checkout -- file/in/question

    假设文件已修改并暂存以进行提交,我将运行以下预提交挂钩:

    #!/bin/bash
    echo "git checkout -- file/in/question"
    git checkout -- file/in/question
    echo "git status"
    git status
    exit 1 #would be 0 if the hook worked as expected
    

    我得到以下输出:

    git checkout -- file/in/question
    git status
    On branch blah
    Changes to be committed:
      (use "git reset HEAD <file>..." to unstage)
    
            modified:   file/in/question
    

    为什么git状态报告git签出没有任何影响?(正确-从钩子返回0会导致文件被错误提交)

    2 回复  |  直到 8 年前
        1
  •  3
  •   Mark Adelsberger    8 年前

    checkout 从索引(即从提交阶段的更改)更新工作树。

    您想要的是更新索引(可能来自 HEAD

    git reset HEAD -- file/in/question
    

    git checkout HEAD -- file/in/question
    
        2
  •  3
  •   Community Mohan Dere    5 年前

    在任何时候,都有三个(!)每个文件的副本(不包括添加或删除文件的特殊情况)。这也适用于您的特定文件。为了方便起见,我们将此文件称为 F .

    • F 处于当前或 HEAD

    • 一份 在索引中,并已准备好提交。此副本可以更改,但我们必须注意谁会注意到任何更改以及何时注意到。

    • 最终副本 F F 是唯一应用涂抹和行尾过滤的;索引中的副本是干净的变体。)

    • 如果 git commit 作为运行 git commit -a git commit <path1> <path2> ... <pathN> ,Git当前正在使用 短暂的 真实的 稍后索引(当且仅当提交完成。)

    • 通过 git提交

    现在让我们把这些放在一起,观察一些问题。

    • 如果你 在预提交钩子中的更改,没有什么可担心的:您返回一个go/stop状态,Git继续从索引中进行新的提交(之后 头部

    • 如果你 进行更改,您将在索引和/或工作树中进行更改。谁会看到这些变化?什么时候?

    • 你实际上要求的改变是 git checkout -- F

    • 您可以使用 git reset HEAD -- F git checkout HEAD -- F checkout 表单还将从索引复制到工作树。

    • Git正在使用临时索引,作为最后一步,Git将复制它添加到此临时索引中的任何条目(由于 -a <path>

      在一些(非常)旧的Git版本中,Git没有注意到对预提交挂钩中的索引所做的更改(例如,它从不重新读取索引)。我很长时间都记不清这有什么影响,或者它影响了什么Git版本,但值得对此做一些仔细的测试:我有点模糊的记忆,Git在C代码中构建了提交树代码,通过不重新读取索引,它用原始索引内容而不是新内容构建了树,因此,在预提交挂钩期间复制到索引中的文件实际上并没有进入提交。

    在任何情况下,如果您在索引中更新文件,那么在工作树中也更新它可能是明智的,但请考虑对那些仔细准备了 本例中的工作树版本。


    在另一种不同但相关的情况下,我们应该注意Git何时将索引项从临时索引复制回实际索引(在 commit -a commit <path> 案例),这也会清除任何精心准备的不同阶段的文件。也就是说,如果您这样做:

    git add -p somefile
    

    git commit somefile 提交当前工作树版本 第一 ,您将丢失精心准备的版本。这可能(也可能不是)暗示了你可能想要如何处理这个问题。特别是,如果要对工作树中的阶段和内容进行任何更改,只是为了避免意外,那么让预提交钩子完全拒绝使用临时索引是非常有用的。