Posted on 2011-06-27 20:17
幻海藍(lán)夢 閱讀(2131)
評論(0) 編輯 收藏 所屬分類:
Git
X | |
最近我花費(fèi)了大量時間為 Gitsters 辯護(hù)以對抗那些 fanboyism, bandwagonism 以及 koolaid-thirst 的指責(zé)。 為此我建設(shè)了此網(wǎng)站來說明大家為什么要從 X 轉(zhuǎn)換至 Git,以及為何你也應(yīng)該這么做。點(diǎn)擊任何一個原因展開以查看詳情。
hg bzr svn perforce
使 Git 從幾乎所有 SCM 中脫穎而出并出并且最吸引人的特色,恐怕非它的分支模型莫屬。 它完全不同于我在此用于比較的所有其他模型,那些模型所推薦的最佳分支方式僅僅是將庫 (repository) 復(fù)制到一個新的目錄而已。
Git 不那么做。 Git 允許你擁有多個完全獨(dú)立的本地分支,創(chuàng)建、合并和刪除這些分支僅需要幾秒鐘的時間。
這意味著你可以這樣做:
- 創(chuàng)建一個新分支嘗試新的想法,提交幾次,切換回原先的分支,應(yīng)用一個 patch,然后再切換至剛才實(shí)驗(yàn)中的新分支,將其合并。
- 一個分支用來存放將要發(fā)布的版本,另一個測試分支專門合并開發(fā)中的工作,其他數(shù)個小分支存放日常開發(fā)工作。
- 為每一個開發(fā)中的新功能建立相應(yīng)分支,這樣便可以在這些分支中無縫切換,并在某個功能開發(fā)完畢合并進(jìn)主分支后刪除相應(yīng)分支。
- 創(chuàng)建一個分支來做實(shí)驗(yàn),若發(fā)現(xiàn)行不通則直接刪掉該分支;放棄這個分支,別人甚至不知道它存在過(即使這期間你已經(jīng) push 了其他分支)。
重要的是,當(dāng)你向一個遠(yuǎn)程庫 push 時,你無需 push 所有分支。你可以只共享一個分支而不是全部。 這會推動大家嘗試新想法而不用操心如何、何時合并或與他人共享。
使用其他系統(tǒng),你也可以找到一些方法來做同樣的事,但會困難的多而且極易出錯。 Git 讓這個過程異常簡單,而且當(dāng)大部分開發(fā)者學(xué)習(xí) Git 時,他們同時改變了他們的工作方式。
svn perforce
雖然所有分布式 SCM 都有這特點(diǎn),但根據(jù)我的經(jīng)驗(yàn) Git 做的更好。除了 'fetch', 'pull' 和 'push', 你很少會用到其他需要跟你的硬盤以外的東西打交道的命令。
這不僅使大部分操作比你已經(jīng)習(xí)慣的要快的多,而且讓你可以離線工作。 這聽起來不怎么樣,不過我經(jīng)常為自己需要離線完成那么多工作感到驚訝。 當(dāng)你在飛機(jī)或火車上還可以建立分支、合并、提交以及瀏覽項(xiàng)目歷史時,你的工作生產(chǎn)力會非常高。
即使是使用 Mercurial,諸如 'incoming' 和 'outgoing' 的常用命令也需要與服務(wù)器連接, 而 Git 讓你可以在離線前從服務(wù)器上 'fetch' 所有數(shù)據(jù),然后對原本在你本地分支中并不存在的數(shù)據(jù)進(jìn)行比較、合并或查看歷史紀(jì)錄。
這意味著可以很容易的在你的 Git 庫中同時保存你自己和與你協(xié)同工作的其他人的多個分支,而不會弄混任何內(nèi)容。
bzr svn perforce
Git 很快。 包括大部分其他系統(tǒng)的忠實(shí)用戶在內(nèi)的人都這么評價 Git。 Git 所有操作都在本地進(jìn)行的特性使它比 SVN 和 Perforce 要快,因?yàn)楹髢烧叩钠胀ú僮鞫家M(jìn)行網(wǎng)絡(luò)連接。 即使與其他允許本地操作的分布式 SCM 相比,Git 也要快得多。
部分原因可能是因?yàn)?Git 是被創(chuàng)造用來供 Linux 內(nèi)核開發(fā)使用的,而那意味著從一開始它就需要高效處理大型庫。 此外,Git 是用 C 語言編寫的,這減少了運(yùn)行期與高層語言進(jìn)行協(xié)作的開銷。Git 這么快的另一個原因是它的主要開發(fā)者把這當(dāng)成設(shè)計目標(biāo)。
我使用 Git,Mercurial 和 Bazaar 這三個不同的 SCM 各存放一份 Django 的源代碼,進(jìn)行了一些測試,下面是一些測試結(jié)果。 我也用 SVN 進(jìn)行了一些測試,不過相應(yīng)我,它要更慢 — 基本上是 Bazaar 的測試結(jié)果加上網(wǎng)絡(luò)延遲...
測試結(jié)果表明除了增加新文件以外,所有的操作都是 Git 最快。(此外在一些非常大的提交操作測試中,Hg 基本上與 Git 一樣快,不過我測試的那種提交操作實(shí)在太大, 你不大可能會遇到那種情況 — Git 處理普通提交比其他 SCM 要快得多)
| Git | Hg | Bzr |
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 是第一次和第二次對一個庫進(jìn)行分支操作的結(jié)果數(shù)字 — 第二次分支使用了硬盤緩存。
需要注意的是雖然 'add' 操作 Git 要慢很多,但這是在大量文件 — 超過 2000 個 — 上進(jìn)行的新增操作。 對于大部分人的日常工作來說,任意一個系統(tǒng)上的新增操作只會花費(fèi)幾分之一秒。其他測試到的操作(可能除了大提交)都與日常使用到的相近。
這些測試結(jié)果并不難重現(xiàn)。只要用不同系統(tǒng)復(fù)制一份 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
svn
Git 真的非常善于節(jié)省磁盤空間。你的 Git 目錄一般只會比一個 SVN checkout 大一點(diǎn)點(diǎn) — 有時更小(顯然 .svn 目錄中的許多內(nèi)容可以去掉)。
從 Django 工程 的同一個歷史紀(jì)錄點(diǎn)取出的不同部分的 clone,提供給我們這些數(shù)據(jù)。
| Git | Hg | Bzr | Bzr* | SVN |
Repo Alone | 24M | 34M | 45M | 89M |
|
Entire Directory | 43M | 53M | 64M | 108M | 61M |
* 第二個 Bar 數(shù)字是我執(zhí)行 'bzr pack' 后得到的,我本以為該命令會讓它體積變小,但結(jié)果反而讓它變得大得多。
hg bzr svn perforce
不同于其他系統(tǒng),Git 有它稱之為暫存區(qū)域("staging area")或 "index" 的東西。 這是一個用來在提交前對提交內(nèi)容進(jìn)行設(shè)置的臨時區(qū)域。
暫存區(qū)域最酷、也是讓 Git 不同于其他工具的地方,是在你完成一部分文件的修改后,可以方便地 stage 并提交它們,同時又不用提交工作目錄中其他已修改的文件或在提交命令中列出那些文件。
你還可以只 stage 已修改的一個文件的一部分內(nèi)容。再也不會發(fā)生這樣的事情了:對同一個文件中邏輯上并不相關(guān)的兩部分進(jìn)行修改后才發(fā)現(xiàn)沒有對它們進(jìn)行分別提交。 現(xiàn)在你可以先 stage 當(dāng)前提交要包括的修改,然后 stage 下次提交要包括的修改。這一特性適用于你需要對文件進(jìn)行的任意范圍的修改。
當(dāng)然,如果你不想控制這么多,你也可以很輕松的忽略這些特性 — 只需在提交命令上加上 '-a' ,就可以把所有修改過的文件加入到暫存區(qū)域中去了。
svn perforce
包括 Git 在內(nèi)的所有分布式 SCM 的最佳特性之一是分布式。這意味著你不是 "checkout" 源代碼的最新版,而是 "clone" 整個代碼庫。
這意味著即使使用中央集中式的工作流,每一個用戶都擁有一份主服務(wù)器的備份,每一份都可以在主服務(wù)器當(dāng)機(jī)或損壞時用來替換它。使用 Git 便不存在單點(diǎn)故障了,除非只有一個點(diǎn)。
同時這不會使操作變得太慢。平均來說,SVN checkout 只比任何一種分布式 SCM 快一點(diǎn)。在我測試過的分布式 SCM 中,Git 是最快的。
| Git | 1m 59s | Hg | 2m 24s | Bzr | 5m 11s | SVN | 1m 4s | |
svn perforce
Git 令人驚嘆的特性之一是,由于其天生的分布式特征及強(qiáng)大的分支系統(tǒng),可以輕而易舉的應(yīng)用任何想的到的工作流。
Subversion 式的工作流
集中式工作流是一種很常見的工作流,這對于那些從集中式系統(tǒng)遷移過來的人來說尤其如此。如果你上次 fetch 過后,已經(jīng)有其他人進(jìn)行了 push 操作,那么 Git 將不允許你直接 push; 所以這種所有開發(fā)者向同一臺服務(wù)器 push 的集中式模型可以工作的很好。
集成管理員工作流
另一種常見工作流是有一名集成管理員專門負(fù)責(zé)向 'blessed' 庫提交,其他開發(fā)者復(fù)制該庫,push 到他們自己獨(dú)立的庫,隨后請求集成管理員 pull 他們的修改。 這是開源工程或 GitHub 庫中很常見的一種開發(fā)模式。
司令官與副官工作流
對于規(guī)模更龐大的項(xiàng)目,你可以讓開發(fā)者使用類似 Linux 內(nèi)核開發(fā)的工作流,每一個子系統(tǒng)都有專人(副官)負(fù)責(zé)合并與該子系統(tǒng)相關(guān)的修改。 另有一名整合者(司令官)只從副官那里 pull ,然后 push 到 'blessed' 庫,其他所有人則再從 'blessed' 庫復(fù)制。
再次強(qiáng)調(diào),對于工作流 Git 非常有彈性,你可以混合及選用任何適合你的工作流。
hg bzr svn perforce
我本人在
GitHub 工作,所以這
可能 顯得有點(diǎn)偏頗, 不過我還是加入了這一部分,因?yàn)楹芏嗳苏f正是 GitHub 讓他們選擇了 Git 。
GitHub 是很多人使用 Git 的原因,相比簡單的托管網(wǎng)站,它更象一個社交網(wǎng)絡(luò)。 人們找到與他們在做的事相關(guān)(似)的其他開發(fā)人員或項(xiàng)目,然后輕松地 fork 和貢獻(xiàn),這樣形成了一個以 Git 和 各種項(xiàng)目為中心的活躍社區(qū)。
也有其他許多針對 Git 和其他 SCM 的服務(wù),但很少有用戶導(dǎo)向或社交導(dǎo)向的,更沒有哪個是基于用戶群的。 GitHub 的社交性是殺手級特性,上述特性使得 Git 和 GitHub 成為快速開發(fā)開源項(xiàng)目的最佳組合。
其他任何一種 SCM 都不提供這樣的社區(qū)。
perforce
本來并非如此 — 早期的 Git 并不是真正意義上的 SCM,而更象一套讓你可以用分布式的方式進(jìn)行版本控制的工具。 但是現(xiàn)在 Git 命令集和學(xué)習(xí)曲線已經(jīng)和其他 SCM 類似,甚至比其中一些更好。
不作針對性的研究很難證明這一點(diǎn),在此我僅僅演示一下 Mercurial 和 Git 命令中的默認(rèn)幫助菜單的區(qū)別。這兩個系統(tǒng)中相同(或相近)的命令將被高亮顯示。 (在 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 命令都存放在可執(zhí)行路徑下,這讓使用者非常迷惑。 現(xiàn)在雖然 Git 仍能識別所有這些命令,但存放在可執(zhí)行路徑下的只有 'git' 這一命令。 如果你比較 Mercurial 和 Git 會發(fā)現(xiàn),Git 的命令集與幫助系統(tǒng)與 Mercurial 幾乎完全一樣 — 從初學(xué)者的 UI 角度來說兩者幾乎沒有區(qū)別。
現(xiàn)在已經(jīng)很難說 Mercurial 或 Bazaar 比 Git 更易學(xué)了。
原文:http://zh-cn.whygitisbetterthanx.com/
http://zh-cn.whygitisbetterthanx.com/