歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux基礎 >> Linux教程 >> 探索 .Git 目錄,讓你真正理解 Git

探索 .Git 目錄,讓你真正理解 Git

日期:2017/2/28 13:53:55   编辑:Linux教程

“哇歐,我才讀了 git 的快速入門指南就覺得它簡直酷斃了,現在使用起 git 來感覺超舒服,媽媽再也不擔心我會捅出什麼簍子了。”—— 某位無名英雄曾曰過

新人剛使用 git 的時候,就像去到一個既不識當地文字也不會說當地語言的陌生的國家。只要你知道你在什麼地方、要去哪裡,一切都 OK,而一旦你迷路,麻煩就來了。

網上已經有許多關於學習基本的 git 命令的文章,但是本文不屬於這一類,而是嘗試另辟蹊徑。

新手總是被 git 嚇到,事實上也很難不被嚇到。可以肯定的是 git 是很強大的工具但還不夠友好。大量的新概念,有些命令用文件做參數和不用文件做參數各自執行的動作截然不同,還有隱晦的回饋等…

我以為克服第一道難關的方法就是不僅僅是使用 git commit/push 就完了。如果我們花點時間去真正了解到底git是由什麼構造的,那將會省去不少麻煩。

初探 .git

那麼我們開始吧。當你創建一個倉庫的時候,使用 git init 指令, git 將會創建一個神奇的目錄:.git。這個目錄下包含了所有 git 正常工作所需要的信息。說白一點,如果你想從你的項目中刪除 git 但是又要保留項目文件,只需要刪除 .git 文件夾就可以了。但是,你確定要辣麼做?

  1. ├── HEAD
  2. ├── branches
  3. ├── config
  4. ├── description
  5. ├── hooks
  6. │├── pre-commit.sample
  7. │├── pre-push.sample
  8. │└──...
  9. ├──info
  10. │└── exclude
  11. ├── objects
  12. │├──info
  13. │└── pack
  14. └── refs
  15. ├── heads
  16. └── tags

這就是你第一次提交之前 .git 目錄的樣子:

  • 這個我們稍後會討論
  • 這個文件包含你倉庫的設置信息。例如這裡會放你遠程倉庫的 URL,你的 email 地址,你的用戶名等…。 每次你在控制台使用“git config…”指令時,修改的就是這裡。
  • gitweb(可以說是 github 的前身)用來顯示倉庫的描述。
  • 這是一個有意思的特性。Git 提供了一系列的腳本,你可以在 git 每一個有實質意義的階段讓它們自動運行。這些腳本就是 hooks,可以在 commit/rebase/pull…. 的前後運行。腳本的名字表示它什麼時候被運行。例如一個有用的預推送 hook 可能會測試關於保持遠程倉庫一致性的式樣原則。
  • 你可以把你不想讓 git 處理的文件放到 .gitignore 文件裡。那麼,exclude 文件也有同樣的作用,不同的地方是它不會被共享,比如當你不想跟蹤你的自定義的 IDE 相關的配置文件時,即使通常情況下 .gitignore 就足夠了(如果你用到了這個請在評論中告訴我)。

commit 的真相

每一次你創建一個文件並跟蹤它會發現,git 會對其進行壓縮然後以 git 自己的數據結構形式來存儲。這個壓縮的對象會有一個唯一的名字,即一個哈希值,這個值存放在 object 目錄下。

在探索 object 目錄前,我們先要問自己 commit 到底是何方神聖。commit 大致可以視為你工作目錄的快照,但是它又不僅僅只是一種快照。

實際上,當你提交的時候,為創建你工作目錄的快照 git 只做了兩件事:

  • 如果這個文件沒有改變,git 僅僅只把壓縮文件的名字(就是哈希值)放入快照。
  • 如果文件發生了變化,git 會壓縮它,然後把壓縮後的文件存入 object 目錄。最後再把壓縮文件的名字(哈希值)放入快照。

這裡只是簡單介紹,整個過程有一點復雜,以後的博客裡會作說明的。

一旦快照創建好,其本身也會被壓縮並且以一個哈希值命名。那麼所有的壓縮對象都放在哪裡呢?答案是object 目錄。

  1. ├──4c
  2. │└── f44f1e3fe4fb7f8aa42138c324f63f5ac85828 // hash
  3. ├──86
  4. │└──550c31847e518e1927f95991c949fc14efc711// hash
  5. ├── e6
  6. │└──9de29bb2d1d6434b8b29ae775ad8c2e48c5391// hash
  7. ├──info// let's ignore that
  8. └── pack // let's ignore that too

這就是我創建一個空文件 file_1.txt 並提交後 object 目錄看起來的樣子。請注意如果你的文件的哈希值是“89faaee…”,git 會把這個文件存在 “89” 目錄下然後命名這個文件為 “faaee…”。

你會看到3個哈希。一個對應 file_1.txt ,另一個對應在提交時所創建的快照。那麼第三個是什麼呢?其實是因為 commit 本身也是一個對象並且也被壓縮存放在 object 目錄下。

現在,你需要記住的是一個 commit 包含四個部分:

  • 工作目錄快照的哈希
  • 提交的說明信息
  • 提交者的信息
  • 父提交的哈希值

如果我們解壓縮一個提交,你自己可以看看到底是什麼:

  1. // by looking at the history you can easily find your commit hash
  2. // you also don't have to paste the whole hash, only enough
  3. // characters to make the hash unique
  4. gitcat-file-p 4cf44f1e3fe4fb7f8aa42138c324f63f5ac85828

這是我看到的

  1. tree 86550c31847e518e1927f95991c949fc14efc711
  2. author PierreDeWulf<[email protected]>1455775173-0500
  3. committer PierreDeWulf<[email protected]>1455775173-0500
  4. commit A

如你所見我們得到了所期望看到的的:快照的哈希,作者,提交信息。這裡有兩樣東西很重要:

  • 正如預料的一樣,快照的哈希 “86550…” 也是一個對象並且能在object目錄下找到。
  • 因為這是我的第一個提交,所以沒有父提交。

那我的快照裡面到底是些什麼呢?

  1. gitcat-file-p 86550c31847e518e1927f95991c949fc14efc711
  2. 100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 file_1.txt

到這裡我們看到的最後一個對象是我們先前提到的唯一會存在於快照中的對象。它是一個 blob(二進制文件),這裡就不作深究了。

分支,標簽,HEAD 都是一家人

那麼現在你知道 git 的每一個對象都有一個正確的哈希值。現在我們來看看 HEAD 吧!那麼,在 HEAD 裡又有什麼呢?

  1. cat HEAD
  2. ref: refs/heads/master

這看起來 HEAD 不是一個hash,倒是容易理解,因為 HEAD 可以看作一個你目前所在分支的指針。如果我們看看 refs/heads/master,就會發現這些:

  1. cat refs/heads/master
  2. 4cf44f1e3fe4fb7f8aa42138c324f63f5ac85828

是不是很熟悉?是的,這和我們第一個提交的哈希完全一樣。由此表明分支和標簽就是一個提交的指針。明白這一點你就可以刪除所有你想刪除的分支和標簽,而他們指向的提交依然在那裡。只是有點難以被訪問到。如果你想對這部分了解更多,請參考git book。

尾聲

到目前為止你應該了解到, git 所做的事就是當你提交的時候“壓縮”當前的工作目錄,同時將其和其他一些信息一並存入 objects 目錄。但是如果你足夠了解 git 的話,你就能完全控制提交時哪些文件應該放進去而哪些不應該放。

我的意思是,一個提交並非真正意義上是一個你當前工作目錄的快照,而是一個你想提交的文件的快照。在提交之前 git 把你想提交的文件放在哪裡? git 把他們放在 index 文件裡。我們現在不會去深入探究 index,同時如果你確實好奇你可以參考這裡。

鳴謝

我希望通過本文你更好的理解了 git 的核心概念。如果你有任何問題和評論,請毫不猶豫的告訴我,你也可以在 twitter 上粉我。

下一次我們談談 git 的變基(rebase),下次見,祝愉快。

Git 教程系列文章

GitHub 使用教程圖文詳解 http://www.linuxidc.com/Linux/2014-09/106230.htm

Git 標簽管理詳解 http://www.linuxidc.com/Linux/2014-09/106231.htm

Git 分支管理詳解 http://www.linuxidc.com/Linux/2014-09/106232.htm

Git 遠程倉庫詳解 http://www.linuxidc.com/Linux/2014-09/106233.htm

Git 本地倉庫(Repository)詳解 http://www.linuxidc.com/Linux/2014-09/106234.htm

Git 服務器搭建與客戶端安裝 http://www.linuxidc.com/Linux/2014-05/101830.htm

Git 概述 http://www.linuxidc.com/Linux/2014-05/101829.htm

分享實用的GitHub 使用教程 http://www.linuxidc.com/Linux/2014-04/100556.htm

Ubuntu下Git服務器的搭建與使用指南 http://www.linuxidc.com/Linux/2015-07/120617.htm

Git 的詳細介紹:請點這裡
Git 的下載地址:請點這裡

Copyright © Linux教程網 All Rights Reserved