0

第一次将文件添加到索引时,文件的创建时间戳存储在索引记录中ctime,文件当前修改的时间戳存储在mtime字段中。

在更改后添加文件mtime时,将使用文件的当前时间戳进行更新。

当文件被签出时,它不使用mtimegit 世界中这些时间戳的用途是什么?

查看对索引的引用,它们似乎就在那里。也许他们有一些从未实现过的未来目标?

$ git ls-files --debug readme.txt
readme.txt
  ctime: 1531246924:79161700
  mtime: 1531258019:669963000
  dev: 0        ino: 0
  uid: 0        gid: 0
  size: 13      flags: 0
4

1 回答 1

2

索引有三个名称:“索引”(您在此处使用的那个)、暂存区域(在某种意义上更好,因为它描述了它的功能)和缓存。这是适用于此的姓氏。

是什么使索引成为索引或缓存,而不仅仅是一个暂存区,它索引并缓存了工作树的内容。缓存的目的是加快速度。但是缓存总是有一个问题:在某些时候,缓存的部分或全部数据变得无效。缓存提供对真实、实际、正确数据的快速/快捷访问,不再反映现实。缓存必须被丢弃或重新填充正确的数据。

现在,Git 的索引保存了工作树中的文件副本,或者至少当时存在git checkout于工作树中。1 如果您以某种方式更改了文件,Git 如何知道缓存的副本无效?

Git 的答案是与缓存副本一起存储有关stat该文件的一些信息,包括文件的大小和您观察到的两个时间戳。如果你以某种方式修改文件——即使只是改变它的模式,它不会触及文件的内容(所以大小和 mtime 保持不变)——ctime 时间戳将被更新,Git 会知道某些东西已经改变了。当然如果你修改了内容或者改变了大小,Git 也会知道的。


1从技术上讲,索引保存文件的干净副本,准备提交。如果您有行尾设置和/或涂抹和/或清洁过滤器,则清洁后的副本实际上可能与工作树副本不匹配。


你注意到:

当文件被签出时,它不使用 mtime [这里未完成的想法]

我认为您观察到的是 Git 的其他优化之一。如果您git checkout <commit-specifier>在空的情况下运行(例如,克隆操作的第一次签出),Git 必须第一次完全填充索引和工作树。但是,一旦你这样做了,如果你现在运行不同 git checkout的代码来签出其他提交,Git 可以优化签出:

  • 索引包含当前提交的所有文件,存储在工作树中。
  • 您想要签出的新提交有许多与当前提交 100% 相同的文件。
  • 因此,Git 只需要替换索引和工作树中的不同文件。

结果,工作树中两次提交之间相同的文件的 mtime 保持不变,因为这些文件根本没有被触及。

这只是缓存进行缓存的另一个方面。但是,它确实发挥了切换分支的能力,同时在索引和/或工作树中进行了一些修改。有关详细信息,请参阅在当前分支上有未提交的更改时签出另一个分支

于 2018-07-10T22:26:08.230 回答