使用git也有一段时间了,不过最近突然冒出一个问题——在git中快照究竟是什么?使用过git的人应该都会发现在使用git管理自己的代码仓库时,随着代码更改次数的增加,代码仓库的实际大小并不会有太大变化,这的确是很神奇。而魔法师git所用的“道具”就是快照(snapshot),不过这一名词过于抽象,真的很让人费解!
我在网上看过很多人的解释,有些人虽然解释得很通俗,不过还是让人摸不着头脑:
想象一下,给一张桌子拍一张照片,纪录了桌子上所有物品的位置、状态,这样就可以称之为快照了。
我们不必存储所有的物品,只需存储这个照片就可以了,下一次想恢复以前的状态的时候,只需要翻出当时的那张照片,再把物品按照那张照片里的位置摆放一下就OK了。
--来自V2EX:https://www.v2ex.com/t/124019
当然,还有一些错误的认识。有不少人认为git存储的是每次文件相对于基本文件的差异,其实这是很多人的误区。的确有不少版本控制软件就是这样做的,如CVS、Subversion等等,但git不是,它记录的是快照。但重点是这快照究竟是什么呢?
在Progit的第一章中,对记录差异和记录快照进行了对比,下图是记录差异的原理图:
这类版本控制软件记录的是一组基本文件和每个文件随时间逐步积累的差异,这个看起来非常好理解。但是git记录快照就稍微有点儿抽象了:
在英文版中这样描述:
Every time you commit, or save the state of your project in Git, it basically takes a picture of what all your files look like at that moment and stores a reference to that snapshot.
通俗的翻译就是:每次你提交或者要在git中保存项目的状态时,git仅仅是制作快照(像拍照一样记录所有文件在那个时刻的样子),并保存指向这个快照的引用。之所以把英文引用过来,是想让大家注意一下里面的这个描述:
takes a picture of what all your files look like at that moment
这一句的意味在中文版Progit中是感受不出来的。
虽然上面的解释让我有了大致的理解,但是还是很有些似懂非懂,模棱两可。
另外,在书中的这样一句话好像点醒了我,虽然并没有直接解释快照(snapshot),但是为我指明了方向:
Git更像是把数据看作是对小型文件系统的一组快照
也许快照是文件系统中的概念或者技术,而git只是利用这一技术,所以Progit中才没有详细介绍这一技术,虽然其中频繁提到快照(snapshot)这个词。我在提问之前,我在维基百科上看过这一概念,但所能知道也就是:来自照相领域的概念,是指特定时间点的一个状态。
如果我的猜想是正确的话,我希望那些懂文件系统或者对操作系统十分了解的大神可以为我们通俗地解释下这个概念或者技术。
note:为了使更多的人可以看到我的问题,我将可能涉及到的标签类型都加了上去。
你把progit繼續讀到blob的部分, 可能就會覺得那個快照的圖示不抽象了.
git做的事大致是這樣的:
(這不是一個精確例子, 實際上git還要在文件中保存一些元數據, 這不影響你的理解)
"快照" 經常指概念上的複製 + 物理上的引用.而不是真的有兩份.
這種快照往往和 copy-on-write 機制共用來減少數據存儲. 比如 btrfs/zfs 可以給一個文件系統快照.
有此概念的不止文件系統, 比如virtualbox可以給一個虛擬機快照, Linux的內存管理也有 copy-on-write.
除了节约空间外, 快照可以用來實現回滾等功能.
另外多說一句
git 可能 會使用diff來存儲 ("delta compression"), 比如把多個blob壓縮成git pack的時候.
這是git底層存儲系統的細節, 不影響其原理. 既然每個blob是不變的, 而且可以隨時還原出來, 邏輯上認為這些快照同時 "存在" 沒有什麼問題.