1. 程式人生 > >開發必備工具之Git(一)

開發必備工具之Git(一)

目錄

一、什麼是Git

答:Git是一個分散式版本控制軟體。另外提一句,它的開發者就是大名鼎鼎的Linux之父Linus。 版本控制,顧名思義,是一種在開發的過程中用於管理我們對檔案、目錄或工程等內容的修改歷史,方便檢視更改歷史記錄,備份以便恢復以前的版本的技術。(“後悔藥”) 分散式,是一種版本控制的方式,有一箇中心的伺服器控制最新版本程式碼,每個開發者自己還有個本地倉庫,在開發過程中先將程式碼提交到本地倉庫再推送到中心伺服器上。 也就是說,Git可以幫助我們完成這幾件事:

回到過去 改變歷史 古今對比 並行開發 誰動了我的程式碼

除了Git外,常見的版本控制軟體還有SVN等

二、Git基本原理

Git的基本操作有很多,如果不理解其中的原理只是靠死記硬背,那肯定會事倍功半,所以,我建議第一步我們來學習下它的基本原理(親身體會啊/哭,以前學過好幾次Git,但過一段一時間不用就忘得差不多了,回頭想想原來學的總是一知半解)。 我們先來想一個問題:Git為什麼能知道我們以前的程式碼,為什麼能“回到過去”,答案就是因為Git把我們每一次修改提交的程式碼以及狀態都儲存了下來,而展示給我們的只有當前一個版本。看下面這張圖:

儲存快照 每次提交或儲存當前專案狀態,Git都會生成一個當前所有檔案狀態的快照,並存儲一個對該快照的引用;而且檔案沒有發生變化時,Git不會重複儲存快照,而只是連結到之前的標識檔案。 說到這,可能還點不明白,別急,我們接下來看看快照到底儲存了哪些東西。

快照儲存不是一個個程式碼原始檔,而是四種物件,幾乎所有的Git操作都是在這四種物件上完成的,這四種物件是:

  • “blob”:一個“blob”通常用來儲存檔案的內容。一個“blob”物件就是一塊二進位制資料,它沒有指向任何東西或有任何其它屬性,甚至沒有檔名。因為“blob”物件內容全部都是資料,所以如若兩個檔案在一個目錄樹或是一個版本倉庫中有同樣的資料內容,那麼它們將會共享同一個“blob”物件。“blob”物件和其所對應的檔案所在路徑、檔名是否改被更改都完全沒有關係。
  • “tree”:像一個目錄,管理一些“tree”物件或是“blob”物件。它有一串指向“blob”物件或是其它“tree”物件的指標,一般用來表示內容之間的目錄層次關係(就像檔案和子目錄)。
  • “commit”:“commit”物件指向一個“tree物件”,並且帶有相關的描述資訊,標記專案某一個特定時間點的狀態。它包括一些關於時間點的元資料,如時間戳、最近一次提交的作者、指向上次提交的指標等等。
  • “tag”:一個“tag”物件包括一個物件名(SHA1簽名)、物件型別、標籤名、標籤建立人的名字(“tagger”), 還有一條可能包含有簽名(signature)的訊息。

這些物件的關係可以用下圖來理解: 所有的物件通過commit物件聯絡起來,每一次commit物件中又都會指向上一次提交後的commit物件,所以如果我們什麼時候想回退版本,只需要找到相應的commit物件即可。而我們所謂的HEAD物件其實就指向最近一個提交的commit物件,也就是最後一個commit物件。

例如我們有一個專案,如果我們把它提交(commit)到一個Git倉庫中, 在Git中“blob”、“commit”和“tree”物件的關係看起來會如下圖: git物件 可以看到: 每個目錄都建立了“tree”物件, 每個檔案都建立了一個對應的“blob”物件。最後有一個“commit”物件來指向根“tree”物件,這樣我們就可以追蹤專案每一項提交內容。

另外,這些物件的命名也很有講究:在Git裡隨處可見一種“40個字元”的字串(例如 6ff87c4664981e4397625791c8ea3bbb5f2279a3)。由於Git中每一個“物件名”都是對“物件”內容做SHA1(SHA1是一種密碼學的雜湊演算法)雜湊計算得來的,所以對於內容不同的物件,會有不同的SHA1雜湊值。這樣就意味著兩個不同內容的物件不可能有相同的“物件名”。

這樣,一次快照就是將有關的物件,即一組組由物件名和物件內容組成的的鍵值對儲存下來。所以Git才會有那麼好的“記憶力”。

三、Git使用者互動

第二部分已經介紹了Git的基本原理,但只是涉及到Git自己內部儲存,沒說使用者該怎麼操作,所以為了能正常輸入和輸出,與使用者互動,Git做了這樣幾件事。

說到這,我又想提一個常見的詞API,API就是Application Programming Interface(應用程式介面),《JavascriptDOM程式設計藝術》書裡提到“簡單地說,API就是一組已經得到有關各方共同認可的基本約定”,說實在地我覺得這說的一點也不簡單,書裡這樣說可能是想定義得更加廣泛,但我的理解是從小地說API就像一個封裝完成的函式,你給它一個輸入,它給你一個輸出,從大地說API就是一個程式,也是輸入與輸出,區別就在於規模的不同,結合到本文的內容,Git也像是一個API,輸入命令,操作資料。好了我不說了,感覺自己著迷了,看什麼都像API 。\笑哭

回到正文,Git為了與互動,做了什麼事呢?

答案在下面的圖裡: 實際目錄

在Git,檔案可能有三種狀態:已提交(committed),已修改(modified),暫存(staged):

  • 已提交(commited),說明資料已經儲存在本地資料庫;
  • 已修改(modified),說明資料被修改,但是尚未儲存到本地資料庫;
  • 暫存(staged),說明已標記將一個被修改的檔案(當前版本)新增到待提交的快照中。

這三種狀態分別對應Git專案的三大區塊:Git目錄,工作目錄,暫存區。

  • Git 目錄(repository),即Git儲存專案元資料和物件資料庫的地方,也就是我們克隆(clone)某專案倉庫時拷貝下的內容所在地;
  • 工作目錄(working directory),即從專案某版本中檢出的當前所處分支,也就是從Git目錄資料庫中拉取的檔案在本地磁碟儲存所在地;
  • 暫存區(staging area),即一個檔案,通常包含在Git目錄中,儲存下一次需提交的內容,有時,它指向我們所說的“index”索引。

所以我們的實際操作流程是:

  • 從Git目錄,檢出分支到工作目錄
  • 在工作目錄修改檔案
  • 暫存檔案,將其新增到待提交快照
  • 提交,將快照持久化提交到Git目錄

這些結合起來,就為我們進行程式碼版本控制提供了充足的底層支撐,這次就先寫到這裡,下一篇將詳細介紹Git的使用與指令。