2013年4月9日 星期二

筆記:版本控制Git

distributed even if your workflow isnt
distributed is the new centralized.

Git靠在檔案裡面記錄的內容來維護自己的狀態,Daemon看使用者的位置在哪個容器,就對哪個容器作事情。

目錄名稱有.git就是裸容器
  • 用檔案內容經過SHA1產生唯一ID,長度為160bit,只需比對ID,就可得知檔案是否相同
  • 用ID的前16bit做目錄名稱分配,避免同一目錄檔案過多,造成效能低下。
  • 160bit的SHA1 ID不只用在內容,Git內部的資料結構,全部都使用SHA1,blob,tree,commit,tag,全部都有自己的SHA1 ID。架構簡潔,容易了解。
  • 整個系統的資料結構,只有blob、tree、commit、tag,非常簡單。
  • 同一個檔案,如果做了更動,ID就會不同,也會將內容存成一個新的blob,相較於其他SCM是記錄檔案變動,較耗空間。所帶來的好處更多?
  • 不以檔案系統的檔名與路徑來決定內部管理資料結構,避免與檔案系統內容綁死,像是改名,追蹤歷史,都以ID來判斷。
  • 只要檔案內容不改變,不管是更名,分支,搬移,複製,全部都不需要再多一份檔案。
  • 透過維護Tree Object把所有git相關設定放在容器根目錄底下,避免四散設定檔
  • 沒有所謂daemon或是Servcie,全部都是有需要才執行功能,功能執行根據容器的內容來處理。這樣省記憶體,省CPU時間。
  • 本來想說要是檔案有好幾百萬,那光是開個tree就會很耗記憶體,搜尋與比對檔案內容是否相同,也非常花時間。Git的tree裡面可以有tree,所以tree裡面的內容會因檔案的樹狀結構而分散,除非極端的狀況,同一個目錄就幾百萬個檔案,不然一般的使用狀況,tree檔案的內容應該都很小。
  • 是不是多個專案都應該放在一個容器裡面?在Ruckus用Perforce是這麼做,在網龍用Subversion是分開,在Git裡面應該是?因為在Git裡面的branch都是以容器為單位,commit物件也是追蹤容器,所以如果多個專案在同一個repository內,沒有辦法區分出各專案的歷史。而Perforce與Subversion都是以檔案為單位,可以用資料夾來區分歷史,所以可以把多個Project放在同一個Repository裡面
  • Git以內容來區分,是否有可能做跨容器的Merge,Merge好之後可以找到某個檔案在兩個不同容器的Branch的所有歷史?

CH4 基本的Git概念

四個基礎物件:
  1. Blobs:所有資料都是Blob,用SHA1演算法來產生唯一的資料代碼,用來識別資料,比對檔案是否相同,與對資料定址。
  2. 樹(Tree):代表與處理目錄資訊
  3. 送交(Commit):代表與處理送交,容器內的歷史就是由送交所組成。
  4. 標籤(Tag):代表特定的物件,大多是送交物件
Git就用這四個物件,來建構出容器所有的歷史,並且讓重複的內容,只佔用一個空間。
四種物件都會有自己的SHA1雜湊值
索引(Index):Git送交之前的暫存狀態,在送交之前可自由修改。

CH5 檔案管理與索引

Git將檔案分為三個群組:
被追蹤:顧名思義
被忽略:不需管理檔案,*.obj,git管理用檔案.git/,使用者可以自定
不被追蹤:要被處理的檔案。

CH6 送交
每一個送交都會指向前一個送交,經過一段時間,一連串的改變可以用一系列的送交來表示,在送交的時候,必須要跟之前的送交比對有多少改變,這件事不需每一個檔案都作比較,只需比對相對應的Blobs與子樹物件即可,如此樹與樹比對的作法,大大減少遞迴比對到每一個檔案的計算與時間成本。
ref:參照至某個Git物件儲存中物件的SHA1雜湊辨識碼
symref:指向某個Git物件的名稱,也稱作符號參照
dev分支名稱是symref,參照到refs/heads/dev,這是個ref

Git的ref有三個命名空間:
  1. refs/head/ref:本地名稱
  2. refs/remotes/ref:遠端名稱
  3. refs/tags/ref:標籤
可以看到,對於Git而言,只有本地,遠端兩種分別,不管遠端在哪裡,不管遠端扮演什麼角色,沒有其他邏輯,這也是一個分散式系統實作的思維,簡化處理與遠端的互動。

有四個特殊的symref
HEAD:指向目前分支最新的送交
ORIG_HEAD:Merge或Rebase時,目前分支的HEAD
FETCH_HEAD:git fetch下來的分支的HEAD,只有在git fetch之後有效,處理完就沒了。
MERGE_HEAD:Merge時,外部來源分支的HEAD

HEAD~2:HEAD的父親
HEAD^2:HEAD父親的兄弟

Git使用DAG(有向非循環圖)來組織送交

CH9 合併
合併必須發生在單一容器內,也就是說,所有要被合併的分支都必須在相同的容器內。分支如何出現在容器內並不重要。遠端的分支,要作合併也是把分支從遠端下載回來,然後再與本地分支作合併。-->這個作法提供了一個分散式系統實作的思維,單一系統不在遠端作操作,而是把資料從遠端抓回來之後再處理,邏輯就是以本地邏輯,這樣可以簡化系統的複雜度。

合併過來就產生一個新的送交,來表示新的統一狀態。

處理合併的方式,就是沿著送交歷史,比對送交物件,在這邊,SHA1雜湊代碼的功用又出現了,不需一路比對到每一個Blog,只需比對送交物件的SHA1雜湊代碼就可以知道是否為相同送交。

退化的合併:
  1. 已是最新:我有動,其他人沒動,當作是合併的終止條件。
  2. 快轉:我沒動,其他人有動,把所有外來的送交加到我的HEAD上,然後修改HEAD指到最新的送交。

CH10 修改送交
未發布的送交記錄可以隨意修改,已發布的送交記錄請勿修改。這也是設計分散式系統應該要遵守的原則,各自獨立,一旦有互動就要遵守約定。
我目前最理解可以使用Rebase的點,就是當自己在分支上進行開發,產生了一連串的送交,然後從中央容器

CH11 遠端容器
Git記錄容器內所有分支的歷史記錄,完全不用向Server查詢,用磁碟空間來取得容器的獨立性
Git複製出來的容器與原始容器完全對稱,所以可以獨立自主。-->分散式系統的一個點應該與其他點完全對稱,可以獨立處理所有的事情,但也可以互相協調讓輸出量更大。
Git的本地分支可以設定遠端追蹤分支,只要送交物件相同,就可以作合併與rebase,提供使用者彈性。
Git用email地址識別唯一使用者,認證的部份交由外部系統來作,使用者管理系統每個環境都用,Git不需再作一個。而且因為email地址是全球唯一,所以在沒有中央Server的Git環境中,也能辨識出單一使用者。
裸容器的概念是為了要整合最終結果,一個專案可以不只有一個裸容器,可以因為政治,技術,地理,任務等等方式,幾個容器的擁有人共同協商出一個裸容器。

CH12 管理容器
Git的分散式開發模型可以使用中央管理容器,每個開發者仍然可以擁有私人的容器拷貝並能夠獨立作業,工作是分散的。
Git沒有唯一真實的歷史記錄,只要有測試過,push/patch進來,結果正確就可以。所以送交物件,只會有先後順序,時間是第二順位。換言之,時間以及空間的操作都不是好選項,所以Git必定考慮到量子物理的影響。-->分散式系統地點分散,作業流程分散,要求時間同步當然也不可能,Git操作的是資料,所以一切以資料的順序為主,這也是可以應用在分散式系統設計的觀念。


CH15 結合專案

https://projects.kde.org/ KDE專案列表說明
http://quickgit.kde.org/ KDE所有專案的容器,可以參考它組織整個KDE產品的架構
http://techbase.kde.org/Development/Git KDE從SVN轉到Git的官方資訊
http://www.omat.nl/2010/10/03/git-kde-org-available/ KDE從SVN轉到Git的相關資訊

要在容器裡面匯入其他專案的函式庫,在Git裡面有以下解法:

  1. 使用拷貝來匯入子專案:如果是外部函式庫,且不會在開發過程中有任何改變,或是很少的更新,外部函式庫的歷史對容器並不重要。
  2. 使用git pull -s subtree來匯入子專案:會從子專案中合併整個歷史記錄,好處是當子專案在外部被更新,本地容器也可以透過git pull -s subtree來更新,還可以保留子專案的歷史記錄。但是如果要把對子專案的修改上傳,邏輯上就會破壞子專案本身自己的歷史記錄,這個結果子專案的開發者沒有辦法接受。
  3. 使用客制化腳本程式來取出子專案:在容器內git clone子專案內容,然後忽略子專案在容器中的內容,讓專案可以編譯,如果想改子專案內容,進到子專案目錄,就是另一個容器。如果需要修改子專案內容且push回去,也是可以的,但是遇到分支,就又需要手動處理一次。有人已經寫出自動管理在容器內的子專案容器的Script。
  4. 原生的解法,使用gitlinks與git submodule:


CH16 在Subversion容器上使用Git

需要把SVN當作是Git的中央容器,有點違背Git分散式的原則,但沒差。
一個容器可以下載所有分支,也可以一個容器一個分支

使用Git svn,可以離線工作,查詢記錄的速度也更快。
使用Git svn,可以減低SVN Server負擔,加快整體開發速度。
使用Git svn,可以作到在SVN的環境下,沒有人知道你在使用Git。

沒有留言:

張貼留言

DevOps Lessons Learned at Microsoft Engineering 筆記

原文: https://www.infoq.com/articles/devops-lessons-microsoft 筆記 組織 講Microsoft裡面的DevOps 故事描述的是Cloud & Enterprise and the Bing ...