gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-04 02:27:38 25 4
gpt4 key购买 nike

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

最佳答案

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

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

  1. blob(二进制大对象)

树基本上是一个目录列表。它包含文件和目录的名称、它们的权限、它是什么类型的对象(blob 或树)及其对象的 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 add newfile 的内容与旧文件相同,Git 将重用相同的 blob。

100644 blob a906cb2a4a904a152e80877d4088654daad0c859      newfile
040000 tree 99f1a6d12cb4b6f19c8655fca46c3ecf317074e0 somedir

What happens in the case if FileA is slightly changed?

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

100644 blob 8f94139338f9404f26296befa88755fc2598c289      somefile
040000 tree 99f1a6d12cb4b6f19c8655fca46c3ecf317074e0 somedir

Git 最终会通过将所有单个对象放入 packfiles 来优化它它只能存储增量。

参见 Git Objects in Pro 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 已将单个对象文件替换为更高效的包文件。

关于git - git 如何处理文件删除和重新添加?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66396518/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com