2011-11-19 177 views
151

我剛開始學習git,爲此我開始閱讀the Git Community Book,在本書中他們說SVN和CVS存儲文件之間的差異,並且git存儲所有文件的快照。git如何存儲文件?

但我沒有真正明白他們的意思是什麼快照。 git是否確實複製了每次提交中的所有文件,因爲這是我從他們的解釋中理解的。如果任何人有更好的學習git的來源,我將不勝感激。

+15

這裏是[精彩的文章](http://nfarina.com/post/9868516270/git-is-simpler),詳細解釋了git如何工作。你要找的可能是關於對象數據庫的§。 – greg0ire

+0

包含指向其他優秀資源的優秀文章。我已經玩了幾個小時。 – mihai

+1

我發現這篇描述git的內容非常棒:http://maryrosecook.com/blog/post/git-from-the-inside-out – Anubis

回答

186

Git確實爲每個提交存儲了所有文件的完整副本,除了對於Git倉庫中已經存在的內容,快照將僅指向所述內容而不是重複它。
這也意味着具有相同內容的多個文件僅存儲一次。

所以快照基本上是一個提交,指的是目錄結構的內容

一些很好的參考是:

你讓Git要保存使用Git的項目的快照commit命令,它基本上記錄了什麼都艙單您項目中的文件看起來像那樣

Lab 12說明如何使以前的快照


progit book具有快照的更全面的描述:

Git和任何其他VCS(Subversion和朋友包括在內)之間的主要區別是混帳認爲其數據的方式。
概念上,大多數其他系統將信息存儲爲基於文件的更改列表。這些系統(CVS,Subversion的,Perforce的,集市,等等)認爲他們保持爲一組文件的信息,並隨着時間的推移對每個文件所做的更改

delta-based VCS

的Git沒有按不要用這種方式來考慮或存儲數據。相反,Git認爲其數據更像是一組迷你文件系統的快照。
每次你提交或保存你的項目在Git中的狀態時,它基本上都會拍攝你當時所有文件的外觀,並存儲對該快照的引用。
爲了提高效率,如果文件沒有改變,Git不會再次存儲文件 - 只是指向它已存儲的前一個相同文件的鏈接。
的Git想着它的數據更像如下:

snapshot-based VCS

這是Git和幾乎所有其他VCSS之間的一個重要區別。它讓Git幾乎重新考慮了大多數其他系統從前一代複製的版本控制的各個方面。這使得Git更像是一個迷你文件系統,其上面建立了一些令人難以置信的強大工具,而不僅僅是一個VCS。


Jan Hudec會將此important comment

雖然這是真的,並在概念層面重​​要的是,它不是在存儲級真。
Git確實使用deltas來存儲
不僅如此,它比任何其他系統都更有效率。因爲它不保留每個文件的歷史記錄,所以它需要每個blob,選擇一些可能相似的blob(使用啓發式,包括最近似的先前版本和其他一些),嘗試生成變化量並選擇最小的一個。這樣它可以(通常取決於試探法)利用其他類似的文件或比以前更類似的較舊版本。 「包窗口」參數允許交易性能爲增量壓縮質量。默認值(10)通常會給出相當好的結果,但是當空間有限或加速網絡傳輸時,git gc --aggressive將使用值250,這會使其運行速度非常慢,但會爲歷史記錄數據提供額外的壓縮。

+3

@JanHudec好點。我已將您的評論納入答案中,以獲得更多的知名度。 – VonC

+1

有沒有人知道Git-like存儲模式的計算機科學術語,又名哈希值存儲? (或類似的東西) –

+0

@JoannesVermorel在其首次提交Git本身時,Linus Torvalds將其簡單描述爲「內容可尋址的對象集合」:https://github.com/git/git/commit/e83c5163316f89bfbde7d9ab23ca2e25604af290 – VonC

3

是的,git確實複製了一個文件。理念是在大多數情況下,磁盤空間本質上是免費的。

這就是爲什麼在使用git時通常不會跟蹤大型資源(視頻,錄音等)的原因。例如參見this discussion

P.S.拉爾斯沃格爾有一個很好的介紹git here

+0

儘管如果文件沒有改變,那麼它就不會被複制。此外,非文本文件不會跟蹤任何vcs – Shahbaz

+0

這完全忽略了壓縮包文件。 – svick

+2

@Shahbaz - git(像mercurial和其他幾個系統)是一個分佈式vcs。一個dvcs的工作原理與傳統的vcs不同。例如,參見[本教程](http://www.vogella.de/articles/Git/article.html)。非文本文件絕對可以被追蹤。當您克隆存儲庫以啓動新的開發分支時,將複製所有文件。 –

30

Git在邏輯上將每個文件存儲在其SHA1下。這意味着如果您有兩個文件的存儲庫中的內容完全相同(或者如果您重命名文件),則只會存儲一個副本。

但這也意味着,當您修改文件的一小部分並提交時,會另存一份該文件的副本。 git解決這個問題的方式是使用包文件。有一段時間,收集到的所有「鬆散」文件(實際上,不僅僅是文件,還包含提交和目錄信息的對象)將被收集並壓縮到一個包文件中。該包文件使用zlib進行壓縮。類似的文件也是delta壓縮的。

拉或推時也使用相同的格式(至少使用某些協議),因此這些文件不必再次重新壓縮。

這樣做的結果是,包含整個未壓縮工作副本,未壓縮最近文件和壓縮舊文件的git存儲庫通常比較小,小於工作副本大小的兩倍。這意味着即使SVN沒有在本地存儲歷史記錄,它也會比SVN的回放文件更小。

+0

啊所以mercurial更有效率空間 – Ben

+0

嘿謝謝你這個偉大的總結!它真的幫我澄清了很多關於git的事情!非常感謝! –

0

上面的答案是相當正面的,但我想添加一個更小的微小概念,即增量編碼。 保存效率直到寫入包文件。在每次提交時,鬆散對象都以壓縮但非三角洲格式寫入。