为什么选择GIT--GIT与其他SCM工具的比较

来源:百度文库 编辑:神马文学网 时间:2024/04/29 20:14:51
原文地址:http://zh-tw.whygitisbetterthanx.com/
我會做這個網站是因為我花了很多時間在替 Gitsters 辯護,對抗那些狂熱者(fanboyism),從眾者 (badwagonism) 還有 koolaid-thirst。這裡要說明的就是為什麼大家都要從 X 換成Git,而為什麼你也應該這樣做的原因。直接點擊任何一個原因來展開查看。
使 Git 從幾乎所有其他 SCM 中脫穎而出,最受矚目的特色,恐怕非它的分支模型莫屬。它完全不同於我在此一起比較的其他模型,大部分它們推薦的最佳分支方法僅僅只是複製倉儲 (repository) 到新的目錄而已。
Git 可不這麼做。 Git讓你可以擁有多個本地的分支,它們可能是完全獨立的,而且建立、合併和刪除這些開發的支線只需要幾秒鐘的時間。
這表示你可以這樣做: 建立一個分支來試試新點子,提交 (commit) 個幾次然後切回你原本的分支,加上一個 patch 然後再切回剛剛實驗用的分支,把它合併進來。
有一個分支只用來放要釋出的版本,另一個用來合併開發中的部份供測試,其他幾個小分支用來放每天的開發工作。
替每一個你正在實做的新功能建立新的分支,然後你就可以平順的在它們之中切換,最後刪除掉每一個新功能已經合併回主線的分支。
建立一個新的分支做實驗,結果發現這樣行不通就刪掉這個分支;放棄一個分支,甚至沒有任何人知道它曾經存在 (同時你還可以把其他的分支公佈出去)
最重要的是,當你要發布到一個遠端的倉儲,你不需要把你所有的分支都推出去。你可以只分享你的分支的其中一個而不是全部。這讓大家可以嘗試新的點子而不需要擔心要計劃要如何、何時合併或與其他人分享。
你在其他系統上可以找到方法做同樣的事,但是會比較困難且容易出錯。 Git讓這個過程變得非常簡單,而且當開發人員開始學習,它常常會改變他們工作的方法。
svn perforce
這基本上對所有分散式 SCM 來說都是一樣的,但是在我的經驗中 Git 把這個特性發揮的更好。 除了'fetch', 'pull' 和 'push' 這些命令外,幾乎沒有其他命令會需要硬碟之外的東西。
這不只讓大部分操作變得比你可能習慣的還要快得多,它還讓你可以離線工作。這聽起來也許沒有什麼,但是我總是驚訝於我有多麼常離線工作。當你在飛機上或火車上,你還可以建立分支、合併和提交工作、瀏覽專案的歷史,這是多麼的有生產力。

就算是用 Mercurial,一些常用的指令如 'incoming' 和 'outgoing'也需要連線伺服器,而用 Git 你可以在離線前 'fetch'伺服器上所有的資料,然後比較、合併和查看紀錄,這些資料原本是在伺服器上還沒有在你的本分支中的。
這表示你可以很容易擁有不只你自己的分支的副本,還有其他任何和你一起工作的人的分支都可以存在你的 Git倉儲中而不打亂你原有的東西。
Git 很快。大家都這麼說,甚至那些其他系統的死忠支持者也都會給予 Git 這個評價。 使用Git,所有的操作都是在本地端的特性讓它比 SVN 與 Perforce 跑得快許多,它們兩個都需要網路連線才能完成大部分操作。然而,就算是與其他也是在本地端操作的 DSCM 比較,Git 還是快非常多。
一部分的原因可能是因為它是建立來用在 Linux 核心上的,這表示它從一開始就必須有效率的處理非常大的倉儲。此外,因為 Git 是用 C 寫的,減少了使用其他高階語言在執行期的開銷。 另外一個 Git這麼快地原因是因為它的主要開發者們將這個列為設計的目標。
底下是一些我測試的數據,使用 Django 的原始碼倉儲與三種不同的 SCM: Git, Mercurial和 Bazaar。 我也用 SVN 測試了一些同樣的項目,不過相信我,它慢更多 — 基本上是 Bazaar 的數字再加上網路的延遲...
   
   
測試的結果是所有操作,除了加新檔案之外都是 Git 最快。 (還有大量的提交操作,Hg基本上一樣快,可是我測試的提交量是如此之大,你平常不太可能有同樣的的量 — 正常的提交操作在 Git 快多了。)
GitHgBzr
Init 0.024s 0.059s 0.600s
Add 8.535s 0.368s 2.381s
Status 0.451s 1.946s 14.744s
Diff 0.543s 2.189s 14.248s
Tag 0.056s 1.201s 1.892s
Log 0.711s 2.650s 9.055s
Commit (Large) 12.480s 12.500s 23.002s
Commit (Small) 0.086s 0.517s 1.139s
Branch (Cold) 1.161s 94.681s 82.249s
Branch (Hot) 0.070s 12.300s 39.411s
Cold 和 Hot 分支數字是我第一次和第二次分支一個倉儲 — 第二次分支的數據有使用磁碟快取。
要特別注意的是雖然 'add' 操作的速度慢很多,但這是在大量的檔案 — 超過 2000 個 —上進行新增操作 。 對於大部分人日常使用來說,在任何系統上新增操作都只會用到幾分之一秒而已。 其他測試到的操作 (除了大量提交...大概)應該與你日常用到的差不多。
這些數字不會很難重現,只要用不同的系統 clone 一份 Django 計劃然後試試這些指令就可以了。 git clone git://github.com/brosner/django.git dj-git
hg clone http://hg.dpaste.com/django/trunk dj-hg
bzr branch lp:django dj-bzr
svn checkout http://code.djangoproject.com/svn/django/trunk dj-svn
Git 真的很懂得怎麼節省磁碟空間。 你的 Git 目錄只會 (一般來說) 比一個 SVN checkout大一點點 — 一些情況下甚至更小 (顯然 .svn 目錄裡面有很多東西可以丟掉)。
以下數據是用不同系統使用同樣的歷史紀錄點取出 Django 之後得到。
GitHgBzrBzr*SVN
Repo Alone 24M 34M 45M 89M
Entire Directory 43M 53M 64M 108M 61M
* 第二個 Bzr 數字是我執行 'bzr pack'後得到,我原本以為會讓它更小,結果反而讓它變大許多...。
hg bzr svn perforce
和其他系統不一樣,Git 有它稱為 "staging area" 或 "index" 的東西。這是一個中間地帶讓你可以在提交前設定你想要提交什麼。
Staging area 最酷的地方,讓 Git 遠遠拋開其他工具的,就是你可以輕易的 在工作告一段落後stage 一些你的檔案,然後提交上去而不需要提交所有修改過的檔案,或是必須在命令列上列出所有想要提交的檔案。

這還允許你只 stage 修改過的檔案的一部分。想像有一天你對一個檔案做了兩項毫不相關的修改,然後你發現忘了先提交其中一個。 現在你可以只 stage 你現在要提交的部份,然後在 stage剩下的改變給下一次提交。 這個功能可擴大應用到任何你對檔案的改變。
當然了,Git 也可以很簡單的略過這些特性。 如果你不想要控制這麼多 — 只要加上 '-a' 到你的commit 命令就可以一次把所有的修改都丟到 staging area 去。

svn perforce
任何分散式 SCM,當然包括 Git,最酷的功能之一就是它是分散式的。 這表示你不是只 "checkout"目前最新版的原始碼,而是 "clone" 整個倉儲。
這表示甚至你是使用中央集中式的工作流程,每一位使用者都有會一份主伺服器的備份,每一份都可以在主伺服器當機或損壞時推上去取代主伺服器。 基本上使用 Git 不會因為遺失單一的點而造成災難,除非就只有那一個點。
而且這不會使得操作變慢太多。平均來說,一次 SVN 的 checkout 只比其他 DSCM 快一點。當然在我測試過的 DSCM 中,Git 是最快的。
Git 1m 59s
Hg 2m 24s
Bzr 5m 11s
SVN 1m 4s
svn perforce
其中一個 Git令人驚訝的事情就是因為它的分散式設計以及超級分支系統,你可以輕易的實做出幾乎任何你想得到的工作流程。
Subversion 式的工作流程
這是一種很常見的 Git工作流程,特別是那些從集中管理式系統轉換過來的人會使用的,是一種集中管理式的工作流程。 如果在你最後一次 fetch 後有人發布過改變,Git不會允許你跟著發布,所以使用這種集中式的模型,所有的開發人員都發布到同一個伺服器也可以工作的很好。

整合管理員工作流程
另外一種常見的 Git 工作流程就是有一個整合管理員 — 一個負責提交到 'blessed'倉儲的人,然後其他數位開發人員從這個倉儲複製,發布到他們自己的獨立倉儲去,然後要求整合者 pull 他們的修改。 這是在開放原始碼界或是GitHub 倉儲上常見的開發模型。

司令官與副手的工作流程
對於一些更複雜的專案,你可以讓你的開發人員們使用類似於 Linux核心的開發流程,開發人員們各自負責專案中不同的子系統 (副手) 然後合併所有關於此子系統的改變。另外一位整合者 (司令官) 只可以從他的副手手上pull 改變,然後發布到 'blessed' 倉儲讓所有人都可以複製回去。

在一次的,Git 是完全非常有彈性的,所以你可以混合和取用適合你的工作流程。
hg bzr svn perforce
這由我來說可能有點偏頗,因為我替 GitHub 工作,但是我還是決定要寫這一部份,因為很多人說他們是因為 GitHub而選擇 Git。
GitHub 是很多人使用 Git 的原因之一,因為它更像是一個社交網路而不僅僅是簡單的 hosting服務。 人們找到其他開發人員或是專案,和他們想要做的事類似,因此可以輕易的分支然後貢獻,以 Git 和各種專案為中心創造出一個非常活躍的社群。
網路上還有其他類似的服務,有 Git 的也有其他 SCM的,但是很少是使用者導向或社交導向的,沒有一個其他服務有類似的用戶群。 這個 GitHub 的社交觀點是它的殺手級應用,合併以上的特色使得使用Git 與 GitHub 工作變成快速開發開放原始碼專案的極佳組合。
這樣的社群不是其他 SCM 所擁有的。
perforce
這本來不是真的 — 早期 Git 不是一個真正的SCM,比較像是一組工具讓你可以用分散式的觀點做出有版本控制的檔案系統。 但是現在,Git 的命令集以及學習曲線已經變得和其他 SCM類似,甚至比一些更好。
不特別去做研究的話很難證明這一點,我在這僅顯示出 Mercurial 與 Git 的預設 'help'菜單之間的差異。 我把兩個系統間相同 (或是近似) 的命令做了高亮顯示。 (在 Hg 中,如果你輸入 'hg help',你會得到一個 40多個指令的清單。)
Mercurial Help
add add the specified files ... annotate show changeset informati... clone make a copy of an existi... commit commit the specified fil... diff diff repository (or sele... export dump the header and diff... init create a new repository ... log show revision history of... merge merge working directory ... parents show the parents of the ... pull pull changes from the sp... push push changes to the spec... remove remove the specified fil... serve export the repository vi... status show changed files in th... update update working directory Git Help
add Add file contents to the index bisect Find the change that introduce... branch List, create, or delete branches checkout Checkout a branch or paths to ... clone Clone a repository into a new ... commit Record changes to the repository diff Show changes between commits, ... fetch Download objects and refs from... grep Print lines matching a pattern init Create an empty git repository log Show commit logs merge Join two or more development h... mv Move or rename a file, a direc... pull Fetch from and merge with anot... push Update remote refs along with ... rebase Forward-port local commits to ... reset Reset current HEAD to the spec... rm Remove files from the working ... show Show various types of objects status Show the working tree status tag Create, list, delete or verify...
在 Git 1.6 之前,所有的 Git 命令都放在執行檔路徑下,常使一些人的感到迷惑。 現在雖然 Git仍然認識這些指令,但在執行檔路徑下的命令只剩下 'git' 一個。 如果你仔細比較 Mercurial 和 Git 會發現,Git 和Mercurial 有幾乎一樣的指令集和說明系統 — 以初學者的 UI 角度來說兩者之間幾乎沒有差別。現在已經很難說 Mercurial 或Bzr 比 Git 容易學習了。