2015-11-05 102 views
3

我今天運行了一個有趣的事情,我想知道git如何處理本地分支。所以我遇到了我的倉庫中的一些問題,並刪除了本地文件夾(轉到回收站)並recloned。(極端也許)我做了以後,我意識到我刪除了一個本地分支,我從來沒有推,因爲這是一個個人方面的項目。我驚慌了一會兒,決定從回收站中恢復文件夾,並將其放在不同的位置,看看我是否能夠將我工作的幾個文件推回到遠程。起初,我只是試圖用文件瀏覽器搜索找不到文件(我很傷心),然後我記得我在刪除之前我在一個不同的分支,所以我把gitbash重定向到項目舊repo的新位置和'git分支'看到我所有的舊分支出現(git magic#1)。所以我結帳有問題的分支和文件資源管理器碰巧開放到我期待該文件的位置,並看到該文件奇蹟般地出現(git magic#2)存儲本地分支的文件在哪裏

這讓我想知道git store在哪裏所有本地分行的數據。我知道有一個隱藏的文件夾,但我搜索了該文件,並沒有顯示它是壓縮,並在那裏重命名?

+0

如果在.git/refs /中沒有包含分支名稱的文件,請查看.git/packed-refs –

回答

10

項目根目錄中有一個隱藏文件夾.git(它在運行git init或以其他方式初始化存儲庫時被創建),其中git存儲所有「魔法位」。這不是非常神奇的 - 有一個HEAD文本文件,說明「頭」在哪裏(例如當前簽出分支或提交),有refs目錄有更多的目錄具有與本地和遠程分支名稱相對應的文件 - 每個目錄文件只是一個帶有提交SHA的文本文件(就像字典,當你說「check out master branch!」時,git會去查找相應的文件,讀取它是什麼提交 - 並檢查提交)。

提交引用「對象」,方便地在objects/目錄中。該目錄實際上包含多個帶有雙字母名稱的目錄 - 這是前兩個字母SHA散列 - 與目錄內的文件名一起構成完整散列(提交,樹或blob)。在這個雙字母目錄裏面,有實際的「對象」(git magic!)。對象可以是「blob」或「tree」類型,前者對應於文件,後者(鬆散地)對應於目錄。閱讀關於docs中的git對象 - 這是一個簡單的閱讀,也爲您提供了一些工具來查看單個對象。

因此,如果在.git/refs/heads/master是一個文本文件,其內容爲a2789da8f918ef26c90e51d05de5723e5ad543a4 - 這意味着master在該提交。您提交該項目的項目的「狀態」存儲在.git/objects/a2/789da8f918ef26c90e51d05de5723e5ad543a4中 - 這是項目目錄的樹對象,此時列出項目目錄中所有文件&目錄的SHA。

因此,你不能真正瀏覽並找到來自不同分支的實際文件 - git不會以這種方式考慮事情,它會將文件視爲文件列表& dirs。當您更改文件並提交它時,它會爲該文件的內容創建一個新的「對象」,併爲父目錄創建新的樹對象(爲更新的文件更新SHA),並寫入一個提交對象(樹對象,其中列出了所有文件項目目錄中的&文件夾)。或者至少這是我的理解,或多或少。

希望能夠幫助我們揭開神祕面紗!


2017-12-21編輯:更新了我對@Herman每條評論的舊回答。對於它的價值,這裏的答案可能會有點「沒有足夠上下文的太多信息」。

較短的答案 - git將.git目錄中的所有數據存儲在項目根目錄中,它存儲對項目文件夾狀態的引用,而不是單獨的文件副本。

爲子孫後代着想,如果有人絆倒在這個答案在未來的 - 我強烈推薦這門課程:

https://app.pluralsight.com/library/courses/how-git-works/table-of-contents (你可以找到免費試用提供了pluralsight並獲得大量的值超出你的試用版)。

+0

提交不包含差異。你可以「漂亮地打印」一個提交的內容:嘗試,例如'git cat-file -p HEAD'來查看'HEAD'提交中的內容。 'tree'行給出了一個樹對象的ID,該對象也在'objects /'目錄中,你可以通過'git cat-file -p'樹對象來查看其中的內容,依此類推。所有對象都通過其SHA-1 ID進行存儲。 – torek

+0

感謝@torek,更新了答案以反映我從文檔中學到的內容。 – apprenticeDev

+1

仍然存在一些錯誤:兩個字符的名稱沒有引用提交,並將文件引用到blob和樹中。兩個字符的名稱與38個字符的文件名一起構成40個字符的SHA-1對象ID,可以是提交,斑點或樹。如果是提交,它將包含對根樹SHA-1 ID的引用,對父提交的SHA-1 ID,作者/提交者信息和提交消息的引用。 – herman