svn extension 什麼使DVCS中的合併變得容易?



mercurial vs git (6)

我在Joel上閱讀了軟件

使用分佈式版本控制,分佈式部分實際上不是最有趣的部分。

有趣的是,這些系統考慮的是變化,而不是版本。

HgInit

當我們必須合併時,Subversion會嘗試查看兩個版本 - 我的修改後的代碼和修改後的代碼 - 它會嘗試猜測如何在一個大的邪惡混亂中將它們粉碎在一起。 它通常會失敗,產生並非真正衝突的“合併衝突”的頁面和頁面,只是Subversion無法弄清楚我們做了什麼的地方。

相比之下,當我們在Mercurial中單獨工作時,Mercurial正在忙於保留一系列變更集。 因此,當我們想要將我們的代碼合併在一起時,Mercurial實際上有更多的信息:它知道我們每個人都改變了什麼並且可以重新應用這些更改,而不僅僅是查看最終產品並嘗試猜測如何將其放入一起。

通過查看SVN的存儲庫文件夾,我的印像是Subversion將每個修訂版維護為變更集 。 據我所知,Hg正在使用變更集快照,而Git純粹使用快照來存儲數據。

如果我的假設是正確的,那麼必須有其他方法使DVCS中的合併變得容易。 那些是什麼?

*更新:

  • 我對技術角度更感興趣,但非技術角度的答案是可以接受的
  • 更正:
    1. Git的概念模型純粹基於快照。 快照可以存儲為其他快照的差異,只是差異純粹用於存儲優化。 - RafałFowgird的comment
  • 從非技術角度來看:
    1. 它只是文化:如果合併困難,DVCS根本不會工作,因此DVCS開發人員投入大量時間和精力來簡化合併。 CVCS用戶OTOH習慣於糟糕的合併,因此開發人員沒有動力讓它工作。 (為什麼當你的用戶為同樣的事情付出同樣的代價時,能夠做些好事?)
      ...
      回顧一下:DVCS的重點是擁有許多分散的存儲庫,並不斷地來回合併變更。 如果沒有良好的合併,DVCS根本就沒用。 然而,CVCS仍然可以通過糟糕的合併來生存,特別是如果供應商可以調整其用戶以避免分支。 - JörgWMittag的answer
  • 從技術角度來看:
    1. 錄製真實DAG的歷史確實有幫助! 我認為主要區別在於CVCS並不總是將合併記錄為與幾個父母的變更集,從而丟失了一些信息。 - tonfa的comment
    2. 因為合併跟踪 ,以及每個修訂都知道其父母的更基本的事實。 ...當每個修訂(每次提交),包括合併提交,知道其父項(對於合併提交,意味著擁有/記住多個父項,即合併跟踪),您可以重建圖(DAG =直接非循環圖)的修訂歷史。 如果您知道修訂圖,則可以找到要合併的提交的共同祖先。 當你的DVCS知道如何找到共同的祖先時 ,你不需要提供它作為參數,例如在CVS中。

      請注意,可能有兩個(或更多)提交的共同祖先不止一個。 Git利用所謂的“遞歸”合併策略,它合併了合併基礎(共同的祖先),直到你留下一個虛擬/有效的共同祖先(在某種簡化中),並且可以做簡單的3路合併。 - JakubNarębski的answer

檢查Git中的合併方式和/或原因是否比SVN更好?

https://ffff65535.com


作為一個歷史記錄,現在陳舊的PRCS系統也知道共同的祖先並且可以有效地合併,雖然它沒有分佈(它是建立在RCS文件之上!)。 但這意味著它可以有效地遷移到git,同時保留歷史記錄。


可能是DVCS用戶從不做那些使得合併變得困難的事情,例如改變和重命名/複製項目中的大多數文件的重構,或者從文件的變化中使用的stratch API重新設計。


在DVCS中沒有什麼特別的東西可以讓合併變得更容易。 它只是文化:如果合併困難,DVCS 根本不會工作 ,因此DVCS開發人員投入大量時間和精力來簡化合併。 CVCS用戶OTOH習慣於糟糕的合併,因此開發人員沒有動力讓它工作。 (為什麼當你的用戶為同樣的事情付出同樣的代價時,能夠做些好事?)

Linus Torvalds在他的一個Git談話中說,當他在Transmeta使用CVS時,他們在合併的開發週期中留出了整整一周的時間。 每個人都認為這是正常的事態。 如今,在合併窗口期間,Linus在短短幾個小時內完成了數百次合併。

如果CVCS用戶只是去他們的供應商並說這個廢話是不可接受的,那麼CVCS可以和DVCS一樣具有良好的合併能力。 但他們陷入了Blub悖論:他們根本不知道這是不可接受的,因為他們從未見過有效的合併系統。 他們不知道那裡有更好的東西。

當他們嘗試DVCS時,他們神奇地將所有的善良歸因於“D”部分。

從理論上講,由於集中性,CVCS應該具有更好的合併能力,因為它們具有整個歷史的全局視圖,不像DVCS,每個存儲庫只有一個小片段。

回顧一下:DVCS的重點是擁有許多分散的存儲庫,並不斷地來回合併變更。 如果沒有良好的合併,DVCS根本就沒用。 然而,CVCS仍然可以通過糟糕的合併來生存,特別是如果供應商可以調整其用戶以避免分支。

所以,就像軟件工程中的其他一切一樣,這是一個努力的問題。


在Git和其他DVCS合併很容易,因為一些神秘的變更集視圖(除非你使用Darcs,其補丁理論,或一些Darcs啟發的DVCS;但它們是少數,但是)Joel討論,但是因為合併跟踪 ,以及每個修訂都知道其父母的更基本的事實。 為此,您需要(我認為)整個樹/完整存儲庫提交...但遺憾的是,它限制了部分檢出的能力,並且只提交了文件子集。

當每個修訂(每次提交),包括合併提交,知道其父項(對於合併提交,意味著擁有/記住多個父項,即合併跟踪 ),您可以重建修訂歷史的圖(DAG =直接非循環圖)。 如果您知道修訂圖,則可以找到要合併的提交的共同祖先。 當你的DVCS知道如何找到共同的祖先時 ,你不需要提供它作為參數,例如在CVS中。

請注意,可能有兩個(或更多)提交的共同祖先不止一個。 Git利用所謂的“遞歸”合併策略,它合併了合併基礎(共同的祖先),直到你留下一個虛擬/有效的共同祖先(在某種簡化中),並且可以做簡單的3路合併。

創建了Git使用重命名檢測 ,以便能夠處理涉及文件重命名的合併。 (這支持JörgWMittag的論點,即DVCS有更好的合併支持,因為他們必須擁有它,因為合併比CVCS更常見,其合併隱藏在'update'命令中,在update-then-commit工作流中,參見了解版本控制 (WIP)由Eric S. Raymond提供)。


我認為其他人提到的變革集DAG會產生很大的不同。 DVCS:es需要在基礎級別拆分歷史記錄(和合併),而我認為CVCS:es(較舊)從第1天開始構建,首先跟踪修訂和文件,並在事後添加合併支持。

所以:

  • 當標記/分支與源目錄樹分開跟踪時,合併很容易並且跟踪,因此整個倉庫可以一次合併。
  • 由於DVCS:es有本地回購,這些很容易創建,所以事實證明,很容易將不同的模塊保存在不同的回購中,而不是在大型回購中跟踪它們。 (因此,repo-wide合併不會導致與svn / cvs中相同的中斷,其中一個repo通常包含許多不需要的模塊,這些模塊需要具有單獨的合併歷史記錄。)
  • CVS / SVN允許工作目錄中的不同文件來自不同的修訂版,而DVCS:es通常對整個WC都有一個修訂版(即使文件被恢復為早期版本,它也會顯示為已修改)狀態與已簽出修訂中的文件不同.SVN / CVS不會始終顯示此內容。)

我相信,混合這些概念(如Subversion所做的那樣)是一個很大的錯誤。 例如,在源樹中有分支/標籤,因此您必須跟踪哪些文件修訂已合併到其他文件。 這顯然比跟踪哪些修訂已合併更複雜。

所以,總結一下:

  • DVCS:需要輕鬆合併,基於此功能集。 設計決策,使這些合併很容易做和跟踪(通過DAG),並實現其他功能(分支/標籤/子模塊),而不是相反。
  • CVCS:es從一開始就有一些功能(例如模塊),這些功能使一些事情變得簡單,但是使repo-wide合併非常棘手。

至少這是我對cvs,svn,git和hg的體驗。 (可能還有其他CVCS:es也有這個東西。)


有一點是svn合併被巧妙地打破了; 請參閱http://blogs.open.collab.net/svn/2008/07/subversion-merg.html我懷疑這與svn記錄mergeinfo一起,即使是在挑選合併時也是如此。 在處理邊界情況時添加一些簡單的錯誤,並且作為CVCS的當前海報子項的svn使它們看起來很糟糕而不是所有正確的DVCS。





dvcs