如何真正理解"Git 保存的是文件快照"这一句话?

2014-07-04 16:54:26 +08:00
 kzing
在<Pro Git>里有这么句话:
"Git 保存的不是文件差异或者变化量,而只是一系列文件快照"

文件快照是 Git 脱颖而出于版本管理的绝活, 但看过了许多文章, 但还是将懂未懂的感觉.

大家是怎么理解Git 的"文件快照"这一含义呢?
13716 次点击
所在节点    git
32 条回复
c742435
2014-07-04 18:02:29 +08:00
从编程复杂度来讲,反而是保存差异更高级呢
不过 git多用于代码,而且现在磁盘容量也够大了,无所谓了
c742435
2014-07-04 18:03:39 +08:00
git底层是zip吗
dorentus
2014-07-04 18:04:41 +08:00
@c742435 保存差异或许实现起来更麻烦,但不能算高级吧……
akfish
2014-07-04 18:08:00 +08:00
@generic

git的底层(plumbing layer)*接口*处理的单位是整个文件(以及整个目录树等等),这并不意味着底层*实现*直接在磁盘上存快照而不使用delta压缩。
--------------------------------------------------------------------

底层实现的确是直接在磁盘上存快照,pack不是必须,并且总是离线发生。而存blob总会立即发生,并且总是先于pack发生。在任何情况下,git总是会先**直接**存储两份物理意义上的文件。

物理文件和概念文件是否一一对应并不值得纠结,就好比讨论Linux文件系统的文件时,你不会纠结inode在哪个扇区、是否和文件一一对应。

真正决定Git本质的,就是概念上的存文件快照而不存差异。
jokester
2014-07-04 18:40:48 +08:00
@c742435 git object是用zlib压缩的
yxz00
2014-07-04 18:42:44 +08:00
@generic 理论上保存2份拷贝压缩不见得比保存delta再压缩小吧。除非svn类的软件从来不对自己的repo进行压缩,否则git的保存方式应该比svn大才对。
dorentus
2014-07-04 18:53:11 +08:00
@yxz00 git pack 不是以同一个文件为单位压缩的,即使是来源于不同文件的 object,只要 git 觉得它们足够相似,都会一起压缩。

然后 git 一般比 svn 占用空间小的原因其实是因为 svn tag/branch 都其实是复制出去一份副本的,git 不是。
dorentus
2014-07-04 18:59:42 +08:00
另外对于楼主后一个问题
“就算是一个非常非常小的改动, 提交会也会有一个新的完整的文件诞生咯? 那这样, 随着版本的增多, 或者对于文件特别大的项目, Git 不会很吃力吗?”
其实也就是文件数量会比较多或者文件大小比较大吧:文件数量会比较多的问题可以由 git repack 解决;文件大小比较大的仅限于放到 repo 里面的单个文件大小比较大的情况,也就是会影响 git diff 的性能吧。
akfish
2014-07-04 19:00:45 +08:00
@yxz00 压缩后文件大小只是一方面,还有一个很重要的点就是存取效率、传输效率。
一堆分离的delta小文件,比起良好的pack成一坨的大文件,IO pattern要差得多
Git pack的算法专门就有策略保证pack出来的文件locality良好。

另外一点就是传输的时候,Git可以先双方协商,看对方缺什么文件,有什么文件,然后总是在对方已有文件的基础上,寻找最优的pack策略,在有的时候就能获得比全局diff更低的带宽占用。
yxz00
2014-07-04 19:00:49 +08:00
@dorentus 直觉上git不会用这么不“git”的方式去做压缩。这个”足够相似“太玄乎了。看来还是得自己读代码看看。
akfish
2014-07-04 19:03:09 +08:00
Git的pack策略:

<gitster> The quote from the above linus should be rewritten a
bit (wait for it):
- first sort by type. Different objects never delta with
each other.
- then sort by filename/dirname. hash of the basename
occupies the top BITS_PER_INT-DIR_BITS bits, and bottom
DIR_BITS are for the hash of leading path elements.
- then if we are doing "thin" pack, the objects we are _not_
going to pack but we know about are sorted earlier than
other objects.
- and finally sort by size, larger to smaller.

<gitster> That's the sort order. What this means is:
- we do not delta different object types.
- we prefer to delta the objects with the same full path, but
allow files with the same name from different directories.
- we always prefer to delta against objects we are not going
to send, if there are some.
- we prefer to delta against larger objects, so that we have
lots of removals.

The penultimate rule is for "thin" packs. It is used when
the other side is known to have such objects.
generic
2014-07-04 19:57:41 +08:00
@chloerei 这涉及pack的很多实现细节,特别是pack本身还对文件作压缩,所以并不是你的两个选项那么简单。

不过我们也可以作个小实验:

~/tmp$ ls
~/tmp$ mkdir test
~/tmp$ cd test
~/tmp/test$ git init
初始化空的 Git 版本库于 /home/jin/tmp/test/.git/
~/tmp/test (master #%)$ dd if=/dev/urandom of=a bs=1 count=1000000
记录了1000000+0 的读入
记录了1000000+0 的写出
1000000字节(1.0 MB)已复制,2.53473 秒,395 kB/秒
~/tmp/test (master #%)$ git add a
~/tmp/test (master #)$ git commit -m 'initial commit'
[master(根提交) 710fdd3] initial commit
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 a
~/tmp/test (master)$ du -csh .git
1.2M .git
1.2M 总用量
~/tmp/test (master)$ dd if=/dev/urandom of=a bs=1 count=500000 oflag=append conv=notrunc
记录了500000+0 的读入
记录了500000+0 的写出
500000字节(500 kB)已复制,1.26773 秒,394 kB/秒
~/tmp/test (master *)$ ls -l a
-rw-r--r-- 1 jin users 1500000 7月 4 18:06 a
~/tmp/test (master *)$ git add a
~/tmp/test (master +)$ git commit -m 'A dash'
[master d47c454] A dash
1 file changed, 0 insertions(+), 0 deletions(-)
~/tmp/test (master)$ du -csh .git
2.6M .git
2.6M 总用量
~/tmp/test (master)$ git gc
对象计数中: 6, 完成.
Delta compression using up to 4 threads.
压缩对象中: 100% (4/4), 完成.
写入对象中: 100% (6/6), 完成.
Total 6 (delta 1), reused 0 (delta 0)
~/tmp/test (master)$ du -csh .git
1.6M .git
1.6M 总用量

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/120979

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX