git - 版本控制比較 - 軟體版本管理慣例




Mercurial和Git有什麼區別? (17)

Git是一個平台,Mercurial僅僅是一個應用程序。 Git是一個版本化的文件系統平台,恰巧在箱子裡裝有一個DVCS應用程序,但平常的平台應用程序更複雜,邊緣比專注的應用程序要粗糙。 但是這也意味著git的VCS非常靈活,並且您可以使用git進行非源代碼控制。

這是差異的本質。

Git最好從頭開始理解 - 從存儲庫格式開始。 Scott Chacon的Git Talk是一個很好的入門書。 如果你試圖在不知道引擎蓋下發生了什麼的情況下使用git,那麼最終你會在某個時候感到困惑(除非你只堅持非常基本的功能)。 這聽起來可能聽起來很愚蠢,當你想要的只是日常編程例程的DVCS時,但git的天才在於存儲庫格式實際上非常簡單,你可以很容易地理解git的整個操作。

對於一些更注重技術性的比較,我個人看到的最好的文章是Dustin Sallings':

他實際上廣泛使用了兩個DVCS,並且都很好地理解了它們,最終選擇了git。

我一直在Windows上使用git(使用msysGit),我喜歡分佈式源代碼管理的想法。 就在最近我一直在看Mercurial(hg),它看起來很有趣。 不過,我無法圍繞著hg和git之間的差異。

有沒有人在git和hg之間做過並排比較? 我很想知道什麼是不同的hg和git,而不必跳進fanboy討論。


mercurial網站對兩個系統的異同進行很好的描述 ,解釋了詞彙和底層概念的差異。 作為一個很長時間的git用戶,它確實幫助我理解了Mercurial的思維模式。



他們幾乎完全相同。 從我的觀點(我的意思是讓我選擇一個DVCS的原因)來看,最重要的不同是兩個程序如何管理分支機構。

要使用Mercurial啟動一個新分支,只需將該存儲庫克隆到另一個目錄並開始開發。 然後,你拉和合併。 使用git,你必須明確地給你要使用的新主題分支命名,然後你開始使用相同的目錄進行編碼。

簡而言之,Mercurial中的每個分支都需要自己的目錄; 在git中,你通常在單個目錄中工作。 在Mercurial中切換分支意味著更改目錄; 在git中,這意味著要求git使用git checkout更改目錄的內容。

我很誠實:我不知道是否可以對Mercurial做同樣的事情,但是因為我通常在web項目上工作,所以總是使用與git相同的目錄似乎對我來說很舒適,因為我不必重新配置Apache並重新啟動它,我不會每次分支時弄亂我的文件系統。

編輯:正如Deestan指出的那樣,Hg已經命名了分支 ,它可以存儲在單個存儲庫中,並允許開發人員在同一工作副本中切換分支。 git分支與Mercurial命名的分支並不完全一樣,無論如何:它們是永久性的,不會像git中一樣扔掉分支。 這意味著如果您使用命名分支進行實驗性任務,即使您決定永遠不合併它,它也會存儲在存儲庫中。 這就是為什麼Hg鼓勵使用克隆進行實驗性短期任務並為長期運行任務命名分支的原因,例如發布分支。

為什麼很多Hg用戶對命名分支的克隆比社交或文化更為技術化。 例如,在最後一個版本的Hg中,甚至可以關閉命名分支並遞歸地從變更集中刪除元數據。

另一方面,git邀請使用“命名分支”,這些分支不是永久的,並且不會作為元數據存儲在每個變更集上。

那麼,從我個人的角度來看,git的模型與命名分支的概念有很深的聯繫,並且在一個分支和另一個分支之間切換同一個目錄; hg可以對命名分支做同樣的事情,但它鼓勵使用克隆,我個人不太喜歡。


另一個有趣的比較mercurial和git: Mercurial vs Git 。 主要關注內部及其對分支過程的影響。




如果你對Mercurial和Git的性能比較感興趣,請看這篇文章 。 結論是:

Git和Mercurial的數量都很好,但是在速度和版本庫大小之間做了一個有趣的折衷。 Mercurial的增加和修改速度都很快,並且可以在同一時間控制存儲庫增長。 Git速度也很快,但是它的存儲庫通過修改後的文件快速增長,直到重新打包為止 - 而且這些重新打包的速度可能會非常慢。 但是打包的倉庫比Mercurial小得多。


如果您正在從SVN遷移,請使用Mercurial,因為SVN用戶的語法更容易理解。 除此之外,你也不會出錯。 但在選擇其中之一之前,請檢查GIT教程HGinit


如果我正確地理解了它們(並且我遠離每個專家),它們從根本上說都有不同的哲學。 我第一次使用了mercurial 9個月。 現在我已經使用git 6。

hg是版本控制軟件。 它的主要目標是跟踪一個軟件的版本。

git是基於時間的文件系統。 它的目標是為文件系統添加另一個維度。 大部分都有文件和文件夾,git增加了時間。 由於VCS是其設計的副產品,所以它恰好運行得非常好。

在hg中,它總是試圖維護整個項目的歷史。 默認情況下,我相信hg在推拉時希望所有用戶對所有對象進行的所有更改。

在git中,只有一組對象和這些跟踪文件(分支/頭),這些文件確定哪些對象集表示特定狀態下的文件樹。 當推或拉git時,只發送你推或拉的特定分支所需的對象,這是所有對象的一小部分。

就git而言,沒有“1個項目”。 你可以在同一個倉庫中有50個項目,git不會在意。 每個人都可以在同一回購協議中單獨管理並且生活良好。

Hg的分支概念是分支主要項目或分支機構等。Git沒有這樣的概念。 git中的一個分支只是樹的一個狀態,一切都是git中的一個分支。 哪個分支是官方的,最新的或最新的在git中沒有意義。

我不知道這是否有道理。 如果我可以畫圖片hg可能看起來像這樣每個提交是o

             o---o---o
            /        
o---o---o---o---o---o---o---o
         \         /
          o---o---o

一棵樹和一根樹枝從樹枝上分離出來。 雖然git可以做到這一點,並且人們經常以這種方式使用它,但這並不是強制執行的。 一張git圖片,如果有這樣的事情,很容易看起來像這樣

o---o---o---o---o

o---o---o---o
         \
          o---o

o---o---o---o

事實上,在某些方面,在git中顯示分支甚至沒有意義。

有一件事對於討論來說很混亂,git和mercurial都有一些叫做“分支”的東西,但它們並不是一回事。 在不同回購協議之間存在衝突時,會出現一個mercurial分支。 git中的分支顯然與hg中的克隆相似。 但是一個克隆,雖然它可能會給出類似的行為,但絕對不是一回事。 考慮我在git vs hg中使用鉻回購這是相當大的嘗試。

$ time git checkout -b some-new-branch
Switched to new branch 'some-new-branch'

real   0m1.759s
user   0m1.596s
sys    0m0.144s

現在在使用克隆的hg中

$ time hg clone project/ some-clone/

updating to branch default
29387 files updated, 0 files merged, 0 files removed, 0 files unresolved.
real   0m58.196s
user   0m19.901s
sys    0m8.957

這兩個都是熱門。 即,我跑了他們兩次,這是第二次。 hg clone與git-new-workdir實際上是一樣的。 這兩者都創建了一個全新的工作目錄,就像您鍵入了cp -r project project-clone 。 這與在git中創建新分支不一樣。 它的重量更重。 如果在gg中有真正的git分支,我不知道它是什麼。

我理解在某種程度上,hg和git 也許可以做類似的事情。 如果是這樣,那麼他們引導您的工作流程仍然存在巨大差異。 在git中,典型的工作流程是為每個功能創建一個分支。

git checkout master
git checkout -b add-2nd-joypad-support
git checkout master
git checkout -b fix-game-save-bug
git checkout master
git checkout -b add-a-star-support

剛剛創建了3個分支,每個分支都基於一個名為master的分支。 (我敢肯定git有一些方法可以讓每行代替2行)

現在去做一件我剛剛做的事

git checkout fix-game-save-bug

並開始工作。 提交事物等。即使在一個像鉻一樣大的項目中轉換分支幾乎是瞬間的。 我其實不知道如何在hg中這樣做。 這不是我讀過的任何教程的一部分。

另一個很大的區別。 Git的舞台。

Git有這個想法的舞台。 您可以將其視為隱藏文件夾。 當你承諾你只承擔舞台上的事情,而不是你工作樹上的變化。 這聽起來很奇怪。 如果你想提交工作樹中的所有更改,你可以做git commit -a ,它將所有已修改的文件添加到舞台上,然後提交它們。

那麼舞台的重點是什麼? 您可以輕鬆分離您的提交。 想像一下,你編輯joypad.cpp和gamesave.cpp,你想分開提交它們

git add joypad.cpp  // copies to stage
git commit -m "added 2nd joypad support"
git add gamesave.cpp  // copies to stage
git commit -m "fixed game save bug"

Git甚至有命令來決定要將同一文件中的哪些特定行複製到舞台,以便您可以分別將這些提交分開。 你為什麼想這麼做? 因為作為單獨的提交,其他人可以只提取他們想要的提交,或者如果出現問題,他們可以恢復提交問題。


我從事Mercurial的工作,但基本上我相信這兩個系統是等價的。 他們都使用相同的抽象:構成歷史的一系列快照(變更集)。 每個變更集知道它來自哪裡(父變更集),並且可以有許多子變更集。 最近的hg-git擴展為Mer​​curial和Git之間提供了一個雙向橋樑,並展示了這一點。

Git非常注重變更這個歷史圖表(帶來所有後果),而Mercurial並不鼓勵歷史重寫, 但無論如何這很容易做到而且這樣做的後果正是您應該期望它們的結果(即,如果我修改了你已有的變更集,那麼如果你從我那裡取得的話,你的客戶將會看到它是新的)。 所以Mercurial對非破壞性命令有偏見

至於輕量級的分支機構,Mercurial支持自多個分支機構以來的存儲庫,總是我認為。 具有多個分支的Git存儲庫正是這樣的:在一個存儲庫中存在多個不同的開發鏈。 然後Git為這些鏈添加名稱,並允許您遠程查詢這些名稱。 Mercurial的Bookmarks擴展添加了本地名稱,在Mercurial 1.6中,您可以在推/拉時移動這些書籤。

我使用Linux,但顯然TortoiseHg比Windows上的Git等效物更快更好(由於更好地使用了較差的Windows文件系統)。 http://github.comhttp://bitbucket.org都提供在線託管服務,Bitbucket的服務非常棒,反應迅速(我還沒有嘗試過github)。

我選擇了Mercurial,因為它感覺乾淨而優雅 - 我被Git獲得的shell / Perl / Ruby腳本推遲了。 如果您想知道我的意思,請嘗試查看git-instaweb.sh文件 :它是一個生成Ruby腳本的shell腳本,我認為該腳本運行Web服務器。 shell腳本生成另一個shell腳本來啟動第一個Ruby腳本。 還有一些Perl ,這是一個很好的方法。

我喜歡將Mercurial和Git與James Bond和MacGyver進行比較的博客文章 - Mercurial比Git更低調。 在我看來,使用Mercurial的人並不那麼容易被打動。 這體現在每個系統如何做Linus所說的“最酷的合併! 。 在Git中,您可以通過執行以下操作與不相關的存儲庫合併:

git fetch <project-to-union-merge>
GIT_INDEX_FILE=.git/tmp-index git-read-tree FETCH_HEAD
GIT_INDEX_FILE=.git/tmp-index git-checkout-cache -a -u
git-update-cache --add -- (GIT_INDEX_FILE=.git/tmp-index git-ls-files)
cp .git/FETCH_HEAD .git/MERGE_HEAD
git commit

這些命令對我來說看起來非常神秘。 在Mercurial中我們這樣做:

hg pull --force <project-to-union-merge>
hg merge
hg commit

注意Mercurial命令是簡單的而不是特殊的 - 唯一不尋常的是 - hg pull--force標誌,這是需要的,因為當你從一個不相關的倉庫中取出時,Mercurial將會中止。 正是這種差異使得Mercurial看起來更加優雅。


我意識到這不是答案的一部分,但是在這個筆記中,我也認為像NetBeans和Eclipse這樣的平台提供穩定的插件可以更好地適應這個任務,或者說更適合哪種工具是最適合“你”的人。 也就是說,除非你真的想用CLI的方式來做。

Eclipse(以及基於它的所有東西)和NetBeans有時在遠程文件系統(如SSH)和文件的外部更新方面都存在問題; 這是你為什麼選擇“無縫”工作的另一個原因。

我現在也想為自己回答這個問題..我已經把候選人歸結為Git或Mercurial ..謝謝大家提供有用的投入在這個主題沒有去宗教。



最大的區別是在Windows上。 Mercurial是本地支持的,Git不是。 您可以通過bitbucket.org獲得與github.com非常相似的主機(實際上,當您獲得免費的私有存儲庫時,效果會更好)。 我使用了msysGit一段時間,但轉移到了Mercurial並對它感到非常滿意。


有人認為VCS系統必須複雜。 他們鼓勵在該領域發明術語和概念。 他們可能會認為關於這個問題的許多博士學位會很有趣。 其中可能是設計Git的人。

Mercurial的設計思路不同。 開發人員不應該太在意VCS,他們應該把時間花在他們的主要功能上:軟件工程。 Mercurial允許用戶使用並愉快地濫用系統,而不會讓他們犯任何不可恢復的錯誤。

任何專業工具都必須帶有清晰設計和直觀的CLI。 Mercurial用戶可以通過發出簡單的命令來完成大部分工作,而無需任何奇怪的選項。 在Git的雙重衝刺中,瘋狂的選項是常態。 如果你是一個CLI人員(說實話,任何自我尊重的軟件工程師應該),Mercurial具有很大的優勢。

舉一個例子,假設你犯了一個錯誤提交。 你忘了編輯一些文件。 要在Mercurial中撤銷您的操作,只需輸入:

$ hg rollback

然後您會收到一條消息,說明系統會撤銷您最後的交易。

在Git中你必須輸入:

$ git reset --soft HEAD^

所以好吧,假設你有一個想法是什麼重置是關於。 但除此之外,你必須知道“軟”和“硬”重置是什麼(任何直觀的猜測?)。 哦,當然,最後不要忘記'^'字符! (現在里奇的名字是......)

Mercurial與第三方工具如kdiff3和meld的整合也好得多。 生成你的補丁合併你的分支沒有太多的大驚小怪。 Mercurial還包含一個簡單的http服務器,您可以通過鍵入來激活它

hg serve

並讓其他人瀏覽您的存儲庫。

底線是,Git以更複雜的方式和更低劣的CLI進行Mercurial的工作。 如果您想將項目的VCS轉化為科研領域,請使用Git。 如果您希望完成VCS工作而不關心它,請使用Mercurial並專注於您的真實任務。







dvcs