git - git status 是否真的计算并检查整个工作目录内容的 SHA?
问题描述
当我使用一些工具(例如HashCalc)对某个文件进行SHA1计算时,如果文件稍微大一点(例如1GB或更多),则需要一些时间。但是,如果我在 5GB 或更大大小的存储库上运行 git status,似乎 git status 检查文件的更改不超过几秒钟。
现在,问题是 git status 是否真的计算并检查文件的 SHA,或者它只是将文件最后修改的时间和日期与索引中的记录进行比较?
解决方案
该git status
命令不计算任何散列。1
什么git status
是:
- 打印有关当前分支的信息,这涉及读取
HEAD
文件,可能还有一些小文件; - 比较(如
git diff --name-status
)HEAD
提交中的每个文件与索引中的每个文件;和 - 比较(如
git diff --name-status
)索引中的每个文件与工作树中的每个文件。
git status
显示要提交的更改和未暂存以进行提交的更改的输出部分只是两个git diff --name-status
-es 结果的重新格式化版本。
这两个相对较大的git diff
s可能需要很长时间,但它们不会。那有两个不同的原因:
使用
--name-status
,比较两个提交,或者一个提交和索引,可以非常快,因为提交中的每个文件都是通过 Git 称为树对象的东西存储的,并且索引具有非常像扁平系列的形式树对象。提交中的文件和索引中的文件都具有预先计算的哈希值。差异操作可以只比较哈希来找出文件是否不同。(文件的存在与否决定了添加和删除的状态。重命名检测,如果必须运行,可能会很慢。)使用
--name-status
,索引和您的工作树的比较可以非常快,因为索引缓存了有关您的工作树的信息。2 对于缓存数据有效的每个文件,Git 不必查看工作树文件内部。对于缓存数据无效的文件,Git 有时可以立即知道文件的工作树副本与索引副本不匹配。这通常只留下一些棘手的情况,Git 确实必须验证工作树副本是否匹配索引副本。
1从技术上讲,索引中有一个一致性检查哈希,它确实读取了索引,所以只有一个哈希。但这是针对index的,它不是您可以提交的文件。
2这里的主要速度瓶颈是您的操作系统执行lstat
系统调用的速度。或者至少,那应该是它所在的位置;某些版本的 Git 在某些极端情况下不小心引入了一些二次行为。如果 lstat 调用很慢,您可以使用 禁用特定文件git update-index --assume-unchanged
,尽管这意味着 Git 只是假设文件没有更改。这个“skip slow lstat”是它最初的目的。无论如何,Git 都可以统计文件,这就是为什么--skip-worktree
建议隐藏工作树更改的原因。
推荐阅读
- java - Java struts recaptcha v2 无法正常工作
- ios - 为什么 md-select-on-focus 在 ios 中不起作用?
- javascript - amcharts中的图表容器宽度和高度动态
- unit-testing - 如何获得一个可以抛出我正在使用 XCTAssertNoThrow(...) 测试的函数的返回值
- vue.js - 带有 Laravel 5.5 的 Vue 单文件组件
- python - Kafka生产者flush和poll的区别
- java - 根据标签值的变化将 xml 拆分为更小的
- android - Android Fragment onClick 按钮打开具有相同活动的新 Fragment
- java - 无法使用无头模式 Selenium 定位元素
- excel - 如果用户尝试在受保护的单元格中写入,则自定义消息