我想知道git如何处理文件操作。假设我删除了FileA,在两次提交之后,我将相同的文件重新添加到相同的路径中。FileA是存储在git历史记录中的一个新文件副本,还是一个存在,之前的两个提交将链接到当前提交?如果FileA稍有改变,情况会怎样?
发布于 2021-02-27 07:38:40
Git博士将文件的内容与文件名分开存储。如果内容相同,则将重用现有内容。如果它被稍微修改,它将存储一个新的副本。它将定期地将内容更改存储在包文件中。
当Git存储一个文件时,它将它存储在两个对象中。
树基本上是一个目录列表。它包含文件和目录的名称、它们的权限、它是什么类型的对象(blob或树)以及它们的对象的ID。
100644 blob a906cb2a4a904a152e80877d4088654daad0c859 somefile
040000 tree 99f1a6d12cb4b6f19c8655fca46c3ecf317074e0 somedir然后,它将压缩的文件内容存储在blob中。上面提到somefile的内容存储在blob a906cb2a4a904a152e80877d4088654daad0c859中。
如果您有两个内容相同的文件,则Git将对两个文件使用相同的blob。
如果您使用git rm somefile和commit,Git将在没有文件的情况下创建一个新树并将其附加到提交中。因为它是由早期的树引用的,所以在早期提交时,blob会继续存在。
040000 tree 99f1a6d12cb4b6f19c8655fca46c3ecf317074e0 somedir如果您使用与旧git add newfile相同的内容,Git将重用相同的blob。
100644 blob a906cb2a4a904a152e80877d4088654daad0c859 newfile
040000 tree 99f1a6d12cb4b6f19c8655fca46c3ecf317074e0 somedir如果FileA稍有改变,情况会怎样?
Git将使用新文件的完整内容存储一个新的blob对象。
100644 blob 8f94139338f9404f26296befa88755fc2598c289 somefile
040000 tree 99f1a6d12cb4b6f19c8655fca46c3ecf317074e0 somedirGit最终将通过将所有单独的对象放入包装文件中进行优化,后者只能存储三角洲。
有关更多信息,请参见Pro Git中的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 filesaf9df46是提交对象。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 files3bcbfae 6是第二个提交对象。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,34f45B4。
$ 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已经用更高效的包文件替换了各个对象文件。
https://stackoverflow.com/questions/66396518
复制相似问题