首页 > 解决方案 > 如果我在 Git 预提交挂钩中修改日期戳文件并简单地调用“git add timeStamp.cs”,我会遇到什么麻烦?

问题描述

这个论坛上有几个主题在某种程度上涉及这个主题,但作为 Git 的初学者,我不理解它们,也无法让它们正常工作。我有一个 C# 项目,我想将提交日期和时间链接到使用 Git 预提交挂钩。当我尝试以下操作时,它似乎工作正常:

cmd.exe /c "getTimeStampAndUpdateTimeStampFile.exe"
git add timeStamp.cs

但是,我在互联网上搜索时发现的大多数代码片段要复杂得多,并且通常涉及存储,但我不明白为什么需要它。有人可以简单地解释一下的简单方法的缺点是什么,什么时候会给我带来问题?

标签: gitpre-commit-hook

解决方案


正如Sebastian Lenartowicz 所建议的那样,其他替代方案可能是一个更好的主意,但要回答这个问题:

我会遇到什么麻烦

我们需要了解 Git 不会从您的工作树(您可以查看和处理文件的地方)中的内容构建提交,而是从索引构建提交。

这里的 TL;DR 是某些git commit选项会导致使用秘密的附加索引文件,这样您git add可能会影响一次提交,但不会影响后续提交。

索引,也称为暂存区或(现在很少)缓存,主要是1只是.git目录中名为index. 也就是说,git commit通常打开并阅读.git/index以查看要放入新提交的内容。2

问题是,你可以——而且 Git 可以在内部——将自己从索引重定向某个替代索引。GIT_INDEX_FILE您可以通过设置环境变量来保存某个文件名来执行此操作,或者 Git 自己执行此操作。这会影响每个命令,包括,因此会将文件复制到备用索引而不是主索引。git subcommandgit addgit add

当您运行常规的普通git commitGit 时:

  • 使用常规索引(所以GIT_INDEX_FILE要么未设置,要么设置为 name .git/index);
  • 运行你的预提交钩子,如果它拒绝提交则提前退出;
  • 锁定索引以防止更改(git add我们正在阅读它时没有 s!);
  • 使用索引中的任何内容构建实际提交,将新的提交哈希 ID 写入或通过HEAD; 和
  • 解锁索引。

但是您也可以使用文件名git commit --only运行或默认,和/或使用. 这些具有从具有“预添加”文件的索引进行新提交的效果。为了完成这项工作,Git 构建了一个替代的临时索引。也就是说,索引——这个工作树的主索引,无论它存在于哪个文件中——还没有被修改。在您启动此特定命令之前,它仍然匹配其中的任何内容。替代索引从以下位置填写:git commit --include git commit -agit commit

  • HEAD如果您使用了git commit --only提交:我们想要一个类似HEAD但有一些更新的提交,或者
  • 如果您使用了当前索引git commit --include:我们想要一个等同于git adding 某些文件的提交,但如果新提交由于某种原因失败,我们不希望将文件添加到主)索引中。

如果你使用git commit -a了 ,Git 现在运行内部等效的git add -u来更新这个临时索引,就像git add -u更新任何索引一样。如果您指定了特定文件,Git 现在会git add在每个文件上运行等效的 。无论哪种方式,这个临时索引现在都会更新以保存提议的新提交。

所以现在,我们有一个替代的临时索引,它包含应该进入新提交的内容。如果这个新的提交成功,Git 也需要更新真实索引,所以 Git 可能也需要构建一个更新的真实索引。

此时有两个或三个索引文件:

  1. 主/实指数。
  2. 我们的临时索引。
  3. 预计的新主要指数。

如果我们的临时文件投影的新文件——即我们使用git commit --include而不是git commit --only——临时文件和投影主文件是同一个文件:文件 2 和 3 都只是命名.git/index.lock(或添加的工作树的不同路径)。

Git 现在像往常一样运行你的 pre-commit 钩子,但GIT_INDEX_FILE设置为指向文件 #2——在 this 期间使用的临时索引git commit。如果你的钩子使用git add,它会将这些文件添加到文件#2。

如果提交失败,Git 只会回滚所有内容:(主)索引保持不变。你在git add你的钩子里跑的有效地撤消了。

但是,如果提交成功,Git 现在将索引文件 #3(准备好的、更新的索引)重命名为主索引。除非文件 2 和 3 是同一个文件,否则git add您对文件 #2 所做的操作就会消失这不一定是非常有害的——用户可以git add再次运行——但这绝对是奇怪的。


1这个词在这里主要有多种原因,但总体思路是:有一些文件,出于各种目的,有时你可以——或者 Git 可以——使用不同的文件。

2如果您在添加的工作树中,则(主/默认)索引位于.git目录下的不同位置。每个工作树都有自己的私有默认索引。


推荐阅读