Git重命名了文件和索引节点

Git重命名了文件和索引节点,git,file-rename,Git,File Rename,考虑将以下命令应用于在git下跟踪的文件(hello.txt)(在干净的工作副本中): 结果: On branch master Changes to be committed: (use "git reset HEAD <file>..." to unstage) renamed: hello.txt -> bye.txt 分支主机上的 要提交的更改: (使用“git重置磁头…”取消分级) 重命名:hello.txt->bye.txt 因此,git知道

考虑将以下命令应用于在git下跟踪的文件(
hello.txt
)(在干净的工作副本中):

结果:

On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    renamed:    hello.txt -> bye.txt
分支主机上的

要提交的更改:
(使用“git重置磁头…”取消分级)
重命名:hello.txt->bye.txt
因此,git知道它是同一个文件,即使它被重命名了。 我有一些模糊的记忆,git检查inode以确定新文件与旧删除文件相同。 所以答案是,git只检查文件的内容,而不检查它是否是同一个inode。(我的结论(*):如果我对文件做了更大的修改,git将不会检测到重命名,即使inode仍然相同。)

因此,在我看来很明显,我错了,git不检查inode(或任何其他文件系统信息),只检查内容。但后来,我发现,它声称

除了时间戳之外,它还记录大小、inode和其他参数 来自lstat的信息,以减少误报的机会。什么时候 如果执行git status,它只需对文件中的每个文件调用lstat 工作树并比较元数据,以便快速确定 哪些文件保持不变

我实际上有两个问题:

On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    renamed:    hello.txt -> bye.txt
  • 我下面的理解正确吗
  • Git确实(也)依赖索引节点来检测文件是否被更改,但它不使用索引节点来检测文件重命名

  • 假设1。这是正确的。为什么git不依赖inode来检测文件重命名? 如果有,那么我们就不会有上面的问题,标记为(*)。(即,无论内容变化有多大,它都会检测到重命名。)

  • (我认为答案类似于“因此,在没有inode的系统上,行为是相同的,例如Windows”。然而,如果是这样,那么这种“相同的行为”已经因为依赖inode检测更改而被打破了。)

    完整的答案很复杂,但这里没有理由担心。有一个真正的问题,我将在最后讨论,但它与inode无关

    让我们从一次侧游开始,尽可能简短地讨论Git的
    头、索引和工作树,并且仍然保持独立。让我们简要地看一下文件/对象存储模型。然后,让我们讨论一下git diff,然后是git状态。然后,我们将准备好了解索引作为缓存的工作方式,以及inode的作用。最后,我们将准备好看看真正的问题是如何发生的

    不过,我将在这里插入以下摘要:通常,这一切都是完全看不见的。缓存的数据是正确的,
    git status
    运行的第二个
    git diff
    运行得很快。或者,缓存的数据已过期,Git注意到缓存的数据已过期,第二个
    Git diff
    会变慢,并且作为一种副作用,它会更新缓存的任何数据,这样另一个
    Git status
    运行的另一个
    Git diff
    会变快。
    因此,通常,你不必关心这些


    标题、索引和工作树
    当然,工作树只是一个普通(非Git)格式的文件树,您和计算机上的所有代码都可以使用它。最初,您克隆一个存储库和/或运行
    git checkout branch
    ,现在您的工作树中充满了和某个分支提示相对应的文件,例如
    master
    branch
    。您还可以运行
    git checkout hash
    或类似程序来获取git所称的“分离头”;在本例中,当前提交是一些历史提交,但与之前一样,您的工作树中填充了与该提交对应的文件。(此规则有一些例外:例如,您可以拥有未跟踪的文件;请参阅。)

    根据定义,
    HEAD
    commit是当前提交。与其他每一次提交一样,此提交是只读的;它有一些元数据(作者和提交者、父提交散列和提交消息);它还存储一个树对象散列ID,通过它(间接地)存储文件的完整快照。因为这是当前的提交,所以至少在最初也是这样,并且有各种特殊情况可能会干扰您在工作树中看到的内容。请注意,与对象数据库中的所有文件一样,当前提交中的所有文件都是只读的;它们也是一种特殊的Git格式。几乎没有任何非Git命令可以读取这些文件

    不过,在
    头和工作树之间,Git与其他版本控制系统(如Mercurial和Subversion)存在着很大的差异。Git公开并事实上迫使您了解Git的索引,也称为暂存区和缓存。这个索引确实,至少是象征性的,站在
    头部
    和工作树之间。
    HEAD
    (当前提交)包含一个仅限Git格式的文件快照。工作树以普通形式包含所有文件。如果我们把
    HEAD
    放在左边,把工作树放在右边,索引就会占据中间的空间。如果您在一个新的存储库中,只提交了一个自述文件,那么您可能会遇到这种看起来相当愚蠢的情况:

     HEAD     index     w.tree
    ------    ------    ------
    README    README    README
    
    HEAD
    中的
    README
    是只读的。它是特殊的Git格式。你不能改变它

    索引中的
    README
    也是特殊的Git格式,但它是读/写的:您可以更改它。但实际上你根本不能使用它,因为它是一种特殊的只使用Git的形式

    工作树中的
    自述文件
    是普通(非Git)形式。读/写:你可以用它做任何你想做的事。Git还不能使用它,因为它不在Git上的特殊版本中
     HEAD     index     w.tree
    ------    ------    ------
    README-   README-   README+
                        a.txt
    
     HEAD     index     w.tree
    ------    ------    ------
    README-   README-   README+
              a.txt     a.txt
    
     HEAD     index     w.tree
    ------    ------    ------
    README-   README-   README+
    a.txt     a.txt     a.txt
    
     HEAD     index     w.tree
    ------    ------    ------
    README    README    README
    a.txt     a.txt     a.txt
    
    read-from-index :0:$path | $smudge > $path
    
    $clean < $path | write-to-index $path
    
    $ touch $path
    
    $ git cat-file commit HEAD  # example for some random git repo on my disk
    tree e68e0f9afad22357e47d0a341770f2315ee16b2c
    parent 6d13fea5d0c1d0b4aedf96b7141c05c73bf9c9cb
    author Timur Batyrshin <erthad@gmail.com> 1590062438 +0300
    committer Timur Batyrshin <erthad@gmail.com> 1590062438 +0300
    
    add icon to the workflow
    
    $ git ls-tree e68e0f9afad22357e47d0a341770f2315ee16b2c
    100644 blob 2dd98d7ddcdb1c24d5fa368c349614baec840167    .gitignore
    100644 blob 71cf7988bc6ca7e38fbb8d0490cb0b9f2368d3dc    LICENSE
    100644 blob 67ed24d3dd5ed71a9b03180d0540276c659e71c3    README.md
    100644 blob 5ab2fb346e9bf27d048bad4725ae1180a0d1fffc    icon.png
    100644 blob 198e0a4a3df7eedc752643d1a7d21b825ff5f2b2    info.plist
    100755 blob 9969b7006112d4d25a7af472cd63ba61e6fd3736    login.sh
    100755 blob 834e97824d38849d9254aa4607e636dc5ef7bae4    populate.sh
    100755 blob 48bf586e84f820c1434959e8064fe8331a0ff5e3    show.rb
    
    $ git cat-file blob 2dd98d7ddcdb1c24d5fa368c349614baec840167 | head -n 3
    *.gem
    *.rbc
    /.config