Git如何检测文件是否被修改?

76

Git如何如此快速地检测到文件修改?

它是否对仓库中的每个文件进行哈希并比较SHA1值?这会花费很长时间,不是吗?

还是它比较atimectimemtime


可能因平台而异。我特别关注Git/Windows如何处理它。 - Pacerier
4个回答

49

Git试图通过lstat()值来确定工作树与索引是否匹配,因为回退到文件内容很昂贵。

Documentation/technical/racy-git.txt描述了使用哪些stat字段以及如何避免由于低mtime粒度而导致的一些竞争条件。此文章提供了更多详细信息

stat值并不是防篡改的,请参阅futimens(3)。 Git可能会被欺骗而错过文件的更改;这不会损害内容哈希的完整性。


1
但是每个提交都会回退到文件内容吗?还是即使在提交时也在猜测? - Pacerier
1
@Pacerier git使用Merkel Trees快速计算整个存储库的哈希值,而无需重新对每个文件进行哈希。唯一的要求是git知道哪些文件被修改,以便它知道需要重新计算Merkel Tree的哪些部分。 - Dai

9

对于像 "git status" 这样的报告,会进行初始 mtime 检查。但是当计算最终提交时,mtime 并不重要... 重要的是 SHA1。


1
@Randal:我不认为这是正确的,它总是会做一个差异比较:http://gist.github.com/240775。如果只使用mtime进行`git status`,您将在我所做的粘贴中看到修改。 - jkp
2
@jkp 我自己的跟踪显示未更改的工作树文件只执行了 lstat - Tobu

5
我猜测它使用了stat()调用的组合来确定看起来可能已经改变的内容,然后依次使用差分引擎来确定这是否属实。你可以在这里查看差分引擎的代码以获取一些想法。我仔细追踪了代码库,确信状态命令确实调用了这段代码(看起来很多东西都是如此!),当你知道Git在Windows上执行这些POSIX类型调用时,它的表现非常糟糕:在该平台上执行git status要慢一个数量级。无论如何,除了从顶部到底部阅读所有代码(如果我有时间的话,我可能会这样做!),这就是我现在能带给你的了...也许如果有人使用过这个代码库,他们可以更明确一些。注意:另一个可能的加速来自于明智地使用inline函数,其中显然是有意义的,你可以在头文件中清楚地看到这一点。[编辑:关于stat()的解释,请参见这里]

可以解释一下 stat() 函数是什么并且有什么作用吗? - hasen

2

根据不同的平台,您可以找到Git使用的系统调用来确定其状态。在Linux上尝试使用strace git status,在SunOS上尝试使用truss git status,或者使用苹果公司在Mac OS X中提供的似乎基于DTrace的工具。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接