章 9. 附錄 A: Git的缺點

有一些Git的問題,我已經藏在毯子下面了。有些可以通過腳本或回調方法輕易地解決, 有些需要重組或重定義項目,少數剩下的煩惱,還只能等待。或者更好地,投入進來幫 忙。

SHA1 的弱點

隨着時間的推移,密碼學家發現越來越多的SHA1的弱點。已經發現對對資源雄厚的組織 哈希衝撞是可能的。在幾年內,或許甚至一個一般的PC也將有足夠計算能力悄悄摧毀一 個Git倉庫。

希望在進一步研究摧毀SHA1之前,Git能遷移到一個更好的哈希算法。

微軟 Windows

Git在微軟Windows上可能有些繁瑣:

不相關的檔案

如果你的項目非常大,包含很多不相關的檔案,而且正在不斷改變,Git可能比其他系統 更不管用,因為獨立的檔案是不被跟蹤的。Git跟蹤整個項目的變更,這通常才是有益的。

一個方案是將你的項目拆成小塊,每個都由相關檔案組成。如果你仍然希望在同一個資 源庫裡保存所有內容的話,可以使用 git submodule

誰在編輯什麼?

一些版本控制系統在編輯前強迫你顯示地用某個方法標記一個檔案。儘管這種要求很煩 人,尤其是需要和中心伺服器通訊時,不過它還是有以下兩個好處的:

  1. 比較速度快,因為只有被標記的檔案需要檢查。
  2. 可以知道誰在這個檔案上工作,通過查詢在中心伺服器誰把這個檔案標記為編輯狀 態。

使用適當的腳本,你也可以使Git達到同樣的效果。這要求程序員協同工作,當他編輯一 個檔案的時候還要運行特定的腳本。

檔案歷史

因為Git記錄的是項目範圍的變更,重造單一檔案的變更歷史比其他跟蹤單一檔案的版本 控制系統要稍微麻煩些。

好在麻煩還不大,也是值得的,因為Git其他的操作難以置信地高效。例如,`git checkout`比`cp -a`都快,而且項目範圍的delta壓縮也比基于檔案的delta集合的做法 好多了。

初始克隆

The initial cost is worth paying in the long run, as most future operations will then be fast and offline. However, in some situations, it may be preferable to create a shallow clone with the --depth option. This is much faster, but the resulting clone has reduced functionality.

當一個項目歷史很長後,與在其他版本系統裡的檢出代碼相比,創建一個克隆的開銷會 大的多。

長遠來看,開始付出的代價還是值得付出的,因為大多將來的操作將由此變得很快,並 可以離線完成。然而,在一些情況下,使用`--depth`創建一個淺克隆比較划算些。這種 克隆初始化的更快,但得到克隆的功能有所削減。

不穩定的項目

變更的大小決定寫入的速度快慢是Git的設計。一般人做了小的改動就會提交新版本。這 裡一行臭蟲修改,那裡一個新功能,修改掉的註釋等等。但如果你的檔案在相鄰版本之 間存在極大的差異,那每次提交時,你的歷史記錄會以整個項目的大小增長。

任何版本控制系統對此都束手無策,但標準的Git用戶將遭受更多,因為一般來說,歷史 記錄也會被克隆。

應該檢查一下變更巨大的原因。或許檔案格式需要改變一下。小修改應該僅僅導致幾個 檔案的細小改動。

或許,資料庫或備份/打包方案才是正選,而不是版本控制系統。例如,版本控制就不適 宜用來管理網絡攝像頭周期性拍下的照片。

如果這些檔案實在需要不斷更改,他們實在需要版本控制,一個可能的辦法是以中心的 方式使用Git。可以創建淺克隆,這樣檢出的較少,也沒有項目的歷史記錄。當然,很多 Git工具就不能用了,並且修復必須以補丁的形式提交。這也許還不錯,因為似乎沒人需 要大幅度變化的不穩定檔案歷史。

另一個例子是基于韌體的項目,使用巨大的二進制檔案形式。用戶對韌體檔案的變化歷 史沒有興趣,更新的壓縮比很低,因此韌體修訂將使倉庫無謂的變大。

這種情況,源碼應該保存在一個Git倉庫裡,二進制檔案應該單獨保存。為了簡化問題, 應該發佈一個腳本,使用Git克隆源碼,對韌體只做同步或Git淺克隆。

全局計數器

一些中心版本控制系統維護一個正整數,當一個新提交被接受的時候這個整數就增長。Git則是通過哈希值來記錄所有變更,這在大多數情況下都工作的不錯。

但一些人喜歡使用整數的方法。幸運的是,很容易就可以寫個腳本,這樣每次更新,中心Git倉庫就增大這個整數,或使用tag的方式,把最新提交的哈希值與這個整數關聯起來。

每個克隆都可以維護這麼個計數器,但這或許沒什麼用,因為只有中心倉庫以及它的計數器對每個人才有意義。

空子目錄

空子目錄不可加入管理。可以通過創建一個空檔案以繞過這個問題。

Git的當前實現,而不是它的設計,是造成這個缺陷的原因。如果運氣好,一旦Git得到 更多關注,更多用戶要求這個功能,這個功能就會被實現。

初始提交

傳統的計算機系統從0計數,而不是1。不幸的是,關於提交,Git並不遵從這一約定。很 多命令在初始提交之前都不友好。另外,一些極少數的情況必須作特別地處理。例如重 訂一個使用不同初始提交的分支。

Git將從定義零提交中受益:一旦一個倉庫被創建起來,HEAD將被設為包含20個零位元組 的字元串。這個特別的提交代表一棵空的樹,沒有父節點,早于所有Git倉庫。

然後運行git log,比如,通知用戶至今還沒有提交過變更,而不是報告致命錯誤並退出。 這與其他工具類似。

每個初始提交都隱式地成為這個零提交的後代。

不幸的是還有更糟糕的情況。如果把幾個具有不同初始提交的分支合併到一起,之後的 重新修訂不可避免的需要人員的介入。

介面怪癖

對提交A和提交B,表達式“A..B”和“A…B”的含義,取決於命令期望兩個終點還是一 個範圍。參見 git help diffgit help rev-parse