git如何处理文件删除和重新添加?

git如何处理文件删除和重新添加?,git,Git,我想知道git如何处理文件操作。假设我删除了FileA,在两次提交之后,我将同一个文件重新添加到同一路径。FileA是存储为git历史记录中的新文件副本,还是之前存在的两次提交将链接到当前提交?如果FileA发生轻微变化,会发生什么情况?tl;dr Git将文件内容与文件名分开存储。如果内容相同,它将重用现有内容。如果它被稍微修改,它将存储一个新的副本。它会定期将内容更改存储在packfile中 当Git存储一个文件时,它将其存储在两个对象中 树 blob(二进制大对象) 该树基本上是一个目录列

我想知道git如何处理文件操作。假设我删除了FileA,在两次提交之后,我将同一个文件重新添加到同一路径。FileA是存储为git历史记录中的新文件副本,还是之前存在的两次提交将链接到当前提交?如果FileA发生轻微变化,会发生什么情况?

tl;dr Git将文件内容与文件名分开存储。如果内容相同,它将重用现有内容。如果它被稍微修改,它将存储一个新的副本。它会定期将内容更改存储在packfile中

当Git存储一个文件时,它将其存储在两个对象中

  • blob(二进制大对象)
  • 该树基本上是一个目录列表。它包含文件和目录的名称、权限、对象的类型(blob或tree)以及对象的ID

    100644 blob a906cb2a4a904a152e80877d4088654daad0c859      somefile
    040000 tree 99f1a6d12cb4b6f19c8655fca46c3ecf317074e0      somedir
    
    然后将压缩后的文件内容存储在blob中。如上所述,
    somefile
    的内容存储在blob
    a906cb2a4a904a152e80877d4088654daad0c859

    如果您有两个具有相同内容的文件,Git将对这两个文件使用相同的blob

    如果您
    git rm somefile
    并提交,git将创建一个没有该文件的新树,并将其附加到提交。因为它被早期提交中的早期树引用,所以blob将继续存在

    040000 tree 99f1a6d12cb4b6f19c8655fca46c3ecf317074e0      somedir
    
    如果您使用与旧文件相同的内容添加新文件,git将重用相同的blob

    100644 blob a906cb2a4a904a152e80877d4088654daad0c859      newfile
    040000 tree 99f1a6d12cb4b6f19c8655fca46c3ecf317074e0      somedir
    
    如果FileA稍微更改,会发生什么情况

    Git将存储一个包含新文件完整内容的新blob对象

    100644 blob 8f94139338f9404f26296befa88755fc2598c289      somefile
    040000 tree 99f1a6d12cb4b6f19c8655fca46c3ecf317074e0      somedir
    
    Git最终将通过将所有单独的对象放入其中,而这些对象只能存储增量,从而对此进行优化

    更多信息,请参阅


    这里有一个快速演示

    $ echo 'Basset hounds got long ears' > FileA
    $ git add FileA
    $ git commit -m First
    [main (root-commit) af9df46] First
     1 file changed, 1 insertion(+)
     create mode 100644 FileA
    $ git hash-object FileA
    34f45be4cebdae4cf67218bd47df88dcd9a4cdc6
    $ tree .git/objects/
    .git/objects/
    ├── 34
    │   └── f45be4cebdae4cf67218bd47df88dcd9a4cdc6
    ├── af
    │   └── 9df4604a35039b68625b8283d7b36fb0409136
    ├── e5
    │   └── d8ddccedc871c546b4f6bf0e316165786c62ba
    ├── info
    └── pack
    
    5 directories, 3 files
    
    af9df46是提交对象。e5d8dcced是树对象。34f45be4ce是包含FileA内容的blob对象

    $ git rm FileA
    rm 'FileA'
    $ git commit -m Second
    [main 3bcbfae] Second
     1 file changed, 1 deletion(-)
     delete mode 100644 FileA
    $ tree .git/objects/
    .git/objects/
    ├── 34
    │   └── f45be4cebdae4cf67218bd47df88dcd9a4cdc6
    ├── 3b
    │   └── cbfae6e607ef605b572f2b88ea21ad021b030b
    ├── 4b
    │   └── 825dc642cb6eb9a060e54bf8d69288fbee4904
    ├── af
    │   └── 9df4604a35039b68625b8283d7b36fb0409136
    ├── e5
    │   └── d8ddccedc871c546b4f6bf0e316165786c62ba
    ├── info
    └── pack
    
    7 directories, 5 files
    
    3bcbfae6是第二个提交对象。4b825dc是新的树对象。请注意,34f45be4ce blob仍然存在

    $ echo 'Basset hounds got long ears' > FileB
    $ git add FileB
    $ git hash-object FileB
    34f45be4cebdae4cf67218bd47df88dcd9a4cdc6
    $ git commit -m Third
    [main 9ba46ad] Third
     1 file changed, 1 insertion(+)
     create mode 100644 FileB
    $ tree .git/objects/
    .git/objects/
    ├── 34
    │   └── f45be4cebdae4cf67218bd47df88dcd9a4cdc6
    ├── 3b
    │   └── cbfae6e607ef605b572f2b88ea21ad021b030b
    ├── 4b
    │   └── 825dc642cb6eb9a060e54bf8d69288fbee4904
    ├── 9b
    │   └── a46ad12eab0a384ebae59aa46def2bbc2b7f0a
    ├── af
    │   └── 9df4604a35039b68625b8283d7b36fb0409136
    ├── c9
    │   └── 8f44c0bd58f45a14f0bb29b15acd4c1616b0dc
    ├── e5
    │   └── d8ddccedc871c546b4f6bf0e316165786c62ba
    ├── info
    └── pack
    
    9 directories, 7 files
    
    我们添加了一个与FileA具有相同内容的不同文件。有一个新的提交对象,9ba46ad。一个新的树对象c98f44c。但它使用相同的blob,34f45be4

    $ git gc
    Enumerating objects: 10, done.
    Counting objects: 100% (10/10), done.
    Delta compression using up to 8 threads
    Compressing objects: 100% (4/4), done.
    Writing objects: 100% (10/10), done.
    Total 10 (delta 0), reused 7 (delta 0), pack-reused 0
    Windhund:test.git (main)$ tree .git/objects/
    .git/objects/
    ├── info
    │   ├── commit-graph
    │   └── packs
    └── pack
        ├── pack-4e76192447fc323d1026ae980fdbda304b70a597.idx
        └── pack-4e76192447fc323d1026ae980fdbda304b70a597.pack
    
    2 directories, 4 files
    

    运行
    git-gc
    (垃圾收集)后,git用更高效的包文件替换了单个对象文件。

    当你说“delete-FileA”时,你的意思是
    git-rm-FileA
    ?当你说“将相同的文件读取到相同的路径”时,你的意思是说
    git add FileA
    并且FileA具有相同的内容?是的。相同的文件或稍有修改。或者回答OP的特定问题:“Git将在提交前重复使用2次提交的文件”(+1)@knittl,这要简洁得多。如果在提交n次后重复,是否也是如此?@OHLÁLÁ是的,Git完全是本地的,必须在每次提交中存储所有文件的完整内容。也有一些例外,比如浅层克隆和克隆。Git对此进行了优化,它只能存储更改之间的增量。