简体   繁体   English

git pre-commit挂钩中的整理文件

[英]Tidy file in git pre-commit hook

I want to tidy files in the git pre-commit hook, and then have the tidied version committed. 我想整理git pre-commit挂钩中的文件,然后提交整理的版本。

Pre-commit hook pseudo code 预提交钩子伪代码

for ($file in modified_files) {
    tidy($file)
    git add $file
}

This workflow tidies and commits files as expected: 此工作流按预期整理和提交文件:

  1. git add $file

  2. git commit -m "foo"

This workflow tidies and commits the files, but still leaves a version staged: 此工作流整理并提交了文件,但仍保留一个已上演的版本:

  1. git add $file

  2. git commit -m "foo" $file

Question

Why does the latter workflow still leave the file staged, even though the tidied version has been committed? 即使已提交整理的版本,为何后者的工作流程仍使文件处于暂存状态? It is almost as if a duplicate exists. 几乎就像是存在重复项。 I am using git version 2.7.3. 我正在使用git版本2.7.3。

It is almost as if a duplicate exists. 几乎就像是存在重复项。

A duplicate does exist. 确实存在重复项。

Specifically, given that there is a current commit ( HEAD or @ ), there are three versions of each file available. 具体来说,鉴于当前提交( HEAD@ ),每个文件都有三个版本。 One is read-only and is the one stored in the HEAD commit itself. 一个是只读的,是存储在HEAD提交本身中的一个。 The other two are the one in the index, which you update by running git add $file , and the one in the work-tree, that is in ordinary text format (as opposed to the special Gitty formats for the commit and index versions), so that you and all your programs can work on it. 另外两个是索引中的一个,您可以通过运行git add $file更新,另一个是工作树中的一个,即普通文本格式(与提交和索引版本的特殊Gitty格式相对) ,这样您和您所有的程序都可以使用它。

So far, though, this doesn't explain the problem. 但是到目前为止,这还不能解释问题。 The real explanation has to do with the way git commit $file affects the --only vs --include option to git commit . 真正的解释与顺便做git commit $file影响--only VS --include选项git commit It also has to do with the fact that while there is the index—one special, distinguished index that is associated with the work-tree—Git is also able to work with some other index, temporarily. 它也有一个事实:尽管存在索引 ,一个特殊的,尊贵与该工作树的Git相关的指数也能够与其他一些指标的工作,暂时做。

We now need several more facts: 现在,我们需要更多的事实:

  1. The default action for git commit is the same as that for git commit --include , but the default action for git commit $file is the same as that for git commit --only $file . 为默认的动作git commit是相同的git commit --include ,但进行默认操作git commit $file是相同的git commit --only $file

  2. When using git commit --only with a list of files, Git constructs a temporary , second index. 当使用git commit --only与文件列表一起使用时,Git会构造一个临时的第二个索引。

  3. After git commit succeeds, Git wants the index to match the commit. git commit成功后,Git希望索引与提交匹配。 But wait ... which index are we talking about here in point 3? 但是等等... 我们在第3点讨论的是哪个索引?

The index is what Git uses to build each commit. 索引是Git用于构建每个提交的内容。 In other words, what's in the index right now is what you and Git propose should be in the next commit you will make. 换句话说,现在索引中的内容就是您和Git建议的内容,该内容应该在您将要进行的下一次提交中。

When you use the (ordinary) index, or use --include which adds its extra files to the index, Git can make the new commit from the index, and afterward, the current ( HEAD or @ ) commit matches the index, because Git just made that commit from the index, so everything is all good. 当您使用 (普通)指数,或使用--include它增加了额外的文件索引 ,GIT中可以从指数的新承诺,后来,当前( HEAD@ )承诺相匹配的指数,因为混帐刚刚索引中进行了提交,因此一切都很好。

But when you use some other index, Git makes a new commit from the files in the temporary index. 但是,当您使用其他索引时,Git将根据临时索引中的文件进行新提交。 That new commit then becomes the HEAD commit, and Git throws away the temporary index. 然后,该新提交成为HEAD提交,Git丢弃了临时索引。 This means that the (ordinary) index would get restored to its rightful throne, guarding the entrance to the Git castle (or is it a dungeon?) from the ordinary rabble files in the work-tree. 意味着 ,(普通)指数将得到恢复到其应有的宝座,守卫入口到Git的城堡(或者是一个地牢?)从工作树普通乌合之众文件。

But if the original "the index", the one about to be restored, has those files, those specifically-committed files, the one you named with --only , in the form they had earlier in old HEAD commit, then the files you very specifically told Git to update-and-commit would all get restored to their old, smelly, pre-special-honor- git-commit -form. 但是,如果原始的“索引”(即将还原的索引)具有这些文件(这些是专门提交的文件),以--only命名的文件(其格式与以前的HEAD提交相同),则这些文件非常明确地告诉Git更新并提交将全部恢复为其旧的,有臭味的,特别荣誉的git-commit commit-形式。 So what Git does before tossing out the temporary index is to copy it back to the (regular) index. 那么,什么混帐折腾出临时索引之前所做的就是复制回它 (普通)指数。

This, however, loses things you have carefully staged in the real index, because now the index, back on its throne, has secretly been replaced by this usurper. 但是,这丢失了您已经在真实索引中精心上演的内容,因为现在索引重新回到其宝座上,已被该篡改者秘密地取代。 Most of the time you won't notice, as the usurper normally looks an awful lot like the original. 大多数情况下,您不会注意到,因为篡夺者通常看起来像原始人一样可怕。 You only see this effect when you first carefully stage a few things, then git commit --only , and then find that your careful staging has been erased. 仅当您首先仔细地git commit --only一些东西,然后git commit --only ,然后发现您的仔细暂存已被清除时,您才看到这种效果。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM