這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
總訣:“歸妹趨無妄,無妄趨同人,同人趨大有。甲轉丙,丙轉庚,庚轉癸。子醜之交,辰巳之交,午未之交。風雷是一變,山澤是一變,水火是一變。乾坤相激,震兌相激,離巽相激。三增而成五,五增而成九……”(共三千餘字)
獨孤九劍講究料敵先機,無招勝有招。在程式世界裡,需要根據不同的需求不斷的迭代。系統不能像劍法一樣隨手變更,往往需要花費無數個人月「最近體會到可以把變化做成介面,留給使用者,來應對一部分需求變更」。程式=演算法+資料結構
, 很少有像 TeX 那樣,在演算法和資料結構兩方面都趨近完美,Donald 獨自完成了 99.99%,甚至連 bug 數,都少到了驚人的地步。我認為程式設計最重要的是資料結構,深刻理解資料結構,設計最合適的資料結構,以不變應萬變,才能抓住需求的本質,解決使用者的痛點,做到在需求變化或者轉型時,改變最小。
總決
以不變應萬變
爛程式員關心的是代碼。好程式員關心的是資料結構和它們之間的關係。
資料結構
Git 資料結構設計的非常精良,據說在之後十幾年的開發中,feature 擴充了無數,基礎資料結構卻很少變動。體會一下 Linus 的一段話:
Git 的設計其實非常的簡單,它的資料結構很穩定,並且有豐富的文檔描述。事實上,我非常的贊同應該圍繞我們的資料結構來設計代碼,而不是依據其它的,我認為這也是 Git 之所以成功的原因之一[…], 依我的觀點,好程式員和爛程式員之間的差別就在於他們認為是代碼更重要還是資料結構更重要。
心裡痒痒的,就讓我們來一窺 Git 的奧秘吧。
Git的設計思想
Git 不隱藏檔差異,把資料看作是對小型檔案系統的一組快照。每次你提交更新,或在 Git 中儲存項目狀態時,它主要對當時的全部檔案製作一個快照並儲存這個快照的索引。 為了高效,如果檔案沒有修改,Git 不再重新儲存該檔案,而是只保留一個連結指向之前儲存的檔案。中如果與前一個版本相比檔案有改變,則儲存新檔案(快照)到下一個版本中。如果沒有改變,則只儲存之前檔案的索引,虛線框所示。
在 Git 中的絕大多數操作都只需要訪問本地檔案和資源,一般不需要來自網路上其它電腦的資訊。你能愉快地提交,直到有網路連接時再上傳。
Git 中所有資料在儲存前都計算校正和(使用 SHA-1 散列),然後以校正和來引用。 這意味著不可能在 Git 不知情時更改任何檔案內容或目錄內容。 這個功能建構在 Git 底層,是構成 Git 哲學不可或缺的部分。 若你在傳送過程中丟失資訊或損壞檔案,Git 就能發現。
你執行的 Git 操作,幾乎只往 Git 資料庫中增加資料。 很難讓 Git 執行任何無法復原操作,或者讓它以任何方式清除資料。
Git 有三種狀態,你的檔案可能處於其中之一:已提交(committed)、已修改(modified)和已暫存(staged)。 已提交表示資料已經安全的儲存在本機資料庫中。 已修改表示修改了檔案,但還沒儲存到資料庫中。 已暫存表示對一個已修改檔案的目前的版本做了標記,使之包含在下次提交的快照中。
由此引入 Git 項目的三個工作區域的概念:Git 倉庫、工作目錄以及暫存地區。
基本的 Git 工作流程如下:
在工作目錄中修改檔案。
暫存檔案,將檔案的快照放入暫存地區。
提交更新,找到暫存地區的檔案,將快照非揮發性儲存體到 Git 倉庫目錄。
Git 檔案的生命週期
工作目錄下的每一個檔案都不外乎這兩種狀態:已跟蹤或未跟蹤。 已跟蹤的檔案是指那些被納入了版本控制的檔案,在上一次快照中有它們的記錄,在工作一段時間後,它們的狀態可能處於未修改,已修改或已放入暫存區。 工作目錄中除已追蹤檔案以外的所有其它檔案都屬於未追蹤檔案,它們既不存在於上次快照的記錄中,也沒有放入暫存區。 初次複製某個倉庫的時候,工作目錄中的所有檔案都屬於已追蹤檔案,並處於未修改狀態。
編輯過某些檔案之後,由於自上次提交後你對它們做了修改,Git 將它們標記為已修改檔案。 我們逐步將這些修改過的檔案放入暫存區,然後提交所有暫存了的修改,如此反覆。所以使用 Git 時檔案的生命週期如下:
Git 儲存資料的方式
為了說的更加形象,我們假設現在有一個工作目錄,裡麵包含了三個將要被暫存和提交的檔案。 暫存操作會為每一個檔案計算校正和(使用 SHA-1 雜湊演算法),然後會把目前的版本的檔案快照儲存到 Git 倉庫中(Git 使用 blob 對象來儲存它們),最終將校正和加入到暫存地區等待提交:
$ git add README blob.go LICENSE$ git commit -m 'The initial commit of dit'
當使用 git commit 進行提交操作時,Git 會先計算每一個子目錄(本例中只有項目根目錄)的校正和,然後在 Git 倉庫中這些校正和儲存為樹對象。 隨後,Git 便會建立一個提交對象,它除了包含上面提到的那些資訊外,還包含指向這個樹對象(項目根目錄)的指標。如此一來,Git 就可以在需要的時候重現此次儲存的快照。
現在,Git 倉庫中有五個對象:三個 blob 對象(儲存著檔案快照)、一個樹對象(記錄著目錄結構和 blob 對象索引)以及一個提交對象(包含著指向前述樹對象的指標和所有提交資訊)。
做些修改後再次提交,那麼這次產生的提交對象會包含一個指向上次提交對象(父物件)的指標。
引用
ProGit2