2014-02-20 75 views
7

我早就聽說過svn的合併衝突問題。什麼是SVN實際使用mergeinfo?

當我得知svn幾個發行版之前實現了一個名爲mergeinfo的功能時,我感到寬慰。看起來好像它的引入會讓svn有足夠的信息來解決它出現的合併問題。直到我鑽進了以下情況:

enter image description here

上圖中的

腳本例子:

SVN=${SVN:-svn} 
SVNADMIN=${SVNAMDIN:-svnadmin} 

rm -rf repo wc 

$SVNADMIN create repo 

$SVN co file://$PWD/repo wc 
cd wc 

# r1 
$SVN mkdir trunk branches 
$SVN ci -m 'structure' 
$SVN up 

# r2 
echo 2 > trunk/t.txt 
$SVN add trunk/t.txt 
$SVN ci -m 'add t.txt' 
$SVN up 

# r3 
$SVN cp trunk branches/A 
$SVN ci -m 'create branch A' 
$SVN up 

# r4 
echo 4 > branches/A/a.txt 
$SVN add branches/A/a.txt 
$SVN ci -m 'add a.txt' 
$SVN up 

# r5 
$SVN cp trunk branches/B 
$SVN ci -m 'create branch B' 
$SVN up 

# r6 
echo 6 > branches/B/b.txt 
$SVN add branches/B/b.txt 
$SVN ci -m 'add b.txt' 
$SVN up 

# r7 
$SVN merge ^/branches/B branches/A 
$SVN ci -m 'merge branch B into A' 
$SVN up 

# r8 
echo 8 > branches/A/d.txt 
$SVN add branches/A/d.txt 
$SVN ci -m 'add d.txt' 
$SVN up 

# r9 
$SVN merge ^/branches/A branches/B 

如果SVN是保持每一個分支可以是從哪裏來的歷史,爲什麼就不能明白那b.txt保持不變@branch A

如果它不能弄清楚,svn做的mergeinfo的實際用途是什麼?

如果svn無法處理這個問題,難道不可能在這個方面創建一個工具來幫助我(即自動解決這種無腦的問題..)嗎?我猜可能會有人存在?

感謝

+0

顯示真實的輸出,而不是圖片 - 我看不到您的圖紙中可能存在的問題 –

+1

我添加了一個我認爲與askers圖形匹配的示例。有些地方不清楚。這些文件是否已經存在或是否是新的(我將它們製作成新的,如果發生衝突,其差異將會按照您獲得的衝突類型而定)?合併究竟是如何完成的?他們是櫻桃選擇還是全分支合併。 –

+0

BenReser說得沒錯。他們是新文件,我正在做一個完整的分支合併。 –

回答

12

有兩種類型在顛覆合併的:

  1. 三點合併
  2. 兩點合併(又名重返合併)

假設您正在使用trunk,並且您需要完成一項特定功能。您創建一個功能A分支。當您使用該功能時,您需要將中繼所做的工作納入功能A,以便您可以跟上其他人的工作。 Subversion將使用三點合併。

Subversion將從分支發生的位置查看樹幹和分支特徵A之間的區別。最近的共同祖先。然後它會考慮已完成的功能A上的所有更改(您不想觸及的)以及中繼線上完成的代碼更改。

Subversion然後將合併主幹上的更改而不覆蓋分支上所做的更改。標準的合併過程,Subversion做得很好。

svn:mergeinfo在哪裏?您不想合併兩次相同的更改,因此Subversion使用svn:mergeinfo屬性跟蹤更改。如果Subversion看到版本5中主幹的變化已經被合併,它不會重新發生這種變化。這是非常好的。

現在,您已完成了您的功能,並且希望將這些更改合併回主幹。你做最後一個主幹分支合併,提交這些更改,現在從Feature分支合併回主幹。

這是一個問題。我們通過svn:mergeinfo跟蹤我們從幹線合併到Feature分支中的內容。但是,由於我們尚未從Feature分支合併到主幹,因此在那裏沒有svn:mergeinfo。如果我們嘗試從Feature分支進入正常的三點合併到主幹,則主幹將假定Feature分支中的所有更改都應合併回主幹。但是,其中許多功能實際上是已合併的主幹更改。

事實上,在這一點上,我們想要做一個兩點合併。我們希望trunk和Feature分支在我們進行合併時完全匹配。畢竟,我們現在已經定期將樹幹合併到Feature分支中。我們想要做的就是將這些功能重新加入後備箱。因此,主幹將與特徵分支相同。

在Subversion 1.8之前,您必須通過運行svn merge --reintegration來強制執行重新集成合並。現在,Subversion會查看合併歷史記錄,並確定何時應該進行重新合併合併。


現在這裏是棘手的部分。仔細查看版本號。這些將會非常非常重要!

  • 修訂10:這是我最後變成樹幹,我需要將這些合併到功能分支。
  • 修訂11:我合併中繼到功能分支。 svn:mergeinfo將顯示從版本1到版本10的所有主幹都位於特徵分支中。由於主幹上的最後更改是版本10,因此這非常合理。
  • 修訂12:我將Feature Branch的版本11合併到主幹中。這是一個重新整合合併。在此之後,Feature分支上的內容和Trunk中的內容應該完全一致。

現在,這裏是踢球者!

  • 修訂13:我在中繼線上做了另一個改變。

現在,我想合併到我的功能分支(創建修訂14)。現在,功能部件上的svn:mergeinfo說什麼?它表示從版本1到版本10的主幹已經合併到Feature分支中。不過,主幹版本12和版本13沒有。因此,Subversion需要將版本12和版本13重新合併到Feature分支中。

但等一下!

版本12的主幹是我的功能分支中的所有更改合併回主幹!也就是說,版本12已經包含了我在Feature分支中所做的所有版本更改。如果我將版本12合併到我的Feature分支中,我會說所有這些在主幹上修訂版本12的變化(這些變化是在特徵分支上進行的,並且合併到主幹中)需要合併到特徵分支上。但是,這些更改也是在Feature分支上進行的。你能說合並衝突嗎?我知道你可以!


有處理這種雙向的:

  • 推薦的方法:一旦你重返社會的特性分支回主幹,刪除分支。鎖定它。切勿再次使用它。不要碰!這並不像聽起來那麼糟糕。重新整合合併後,您的主幹和該功能分支無論如何都會匹配。從trunk中刪除和重新創建分支並不會那麼糟糕。
  • 工作的棘手方式:我們需要做的是讓Subversion認爲修訂版#12(或重新整合合併更改)已經合併到我們的Feature分支中。我們可以與svn:mergeinfo財產爭執。而且,我用它來做那件事。它說trunk:1-11,我會手動將其更改爲trunk:1-12

    這很棘手,但方式太棘手,並且有風險,因爲Subversion已經爲您提供了一種操作svn:mergeinfo而無需手動更改的方法。

它被稱爲記錄只有合併。

$ svn co svn://branches/feature_a 
$ cd feature_a 
$ svn merge --record-only -c 12 svn://trunk 
$ svn commit -m "Adding in the reintegration merge back into the feature branch." 

這改變了功能分支上的svn:mergeinfo而不影響文件的實際內容。沒有真正的合併完成,但Subversion現在知道中繼線的版本12已經在Feature分支中。一旦你這樣做,你可以重用功能分支。


現在看看你的圖表:當你合併分公司B插入到A分支,你合併所有的從B變成A,並svn:mergeinfo追蹤到。當您將分支B合併回分支A時,您已經擁有分支A中分支B的所有更改,並且您不希望將這些更改帶回分支B.您應該使用重新集成合併:現在

$ cd $branch_a_working_dir 
$ svn merge $REPO/branches/B 
$ svn commit -m "Rev 7: All of my changes on Branch B are now in A" 
$ vi d.txt 
$ svn add d.txt 
$ svn commit -m"Rev 8: I added d.txt" 
$ cd $branch_b_working_dir 
$ svn merge --reintegrate svn://branch/A # Note this is a REINTEGRATION merge! 
$ svn commit -m"Rev 9: I've reintegrated Branch A into Branch B 

,如果我們想繼續使用分支用於進一步的修改:

$ cd $branch_a_working_dir 
$ svn merge -c 9 --record-only $REPO/branches/b 
$ svn commit -m"I've reactivated Branch A and can make further changes" 

我希望這解釋了一些關於如何svn:mergeinfo的作品,爲什麼你要知道你是否正在使用正常的三點合併與兩點重新合併合併,以及如何能夠重新激活分支後r你已經完成了重新整合合併。

只要你牢記這一點,Subversion合併工作就會很好。

0

你誤會合並信息的意義和用法 - 它僅保存已(此節點),合併,以便不合並修訂了兩次,沒有什麼有關內容的修改和合並,起源

7

David W.'s答案是相當不錯的,但我會提供我自己的答案,從更現代的方法回答這個問題。大衛告訴你的是真實的,在閱讀我的答案時理解他的答案是有用的,所以如果你還沒有閱讀,你應該閱讀他的第一個答案。我的回答對David所指出的問題和解決方案提供了更現代的理解。

因此,首先簡單的答案是,如果您使用Subversion 1.8,那麼您呈現的情況工作得很好。使用Subversion 1.8運行時,添加到問題中的示例腳本沒有衝突。只有客戶需要更新才能獲得此功能。

這裏較長的答案是,對於較舊版本的Subversion,您需要知道何時使用命名不清的--reintegrate選項(1.8數字表示適合您)。儘管名稱爲--reintegrate不僅適用於將分支重新集成到主幹時。

人們經常遇到的問題之一是當他們使用功能分支時,他們想要將功能分支合併回主幹,然後繼續使用該分支。正如大衛的回答所表明的那樣,有兩種方法可以解決這個問題。首先刪除分支,然後使其新鮮。其次,只記錄合併。我的Subversion開發人員之一Julian Foad在向1.8工作時意識到這兩種技術都不是必需的。他在his presentation on merging at the Subversion Live 2012 conference中報道了這一點。他的演講幻燈片可以在這裏在線獲得(注意這是會議所有幻燈片的PDF文件,因此它不是很小),關於這個問題的部分從第123頁開始。

總結他的演講典型特徵分支工作流程是關閉主幹創建分支。向您的功能分支提交提交,並定期從中繼線合併到您的功能分支,以便與中繼線上的內容同步。 svn merge ^/trunk $BRANCH_WC。然後,當您準備好合併回主幹時,您可以使用svn merge --reintegrate ^/branches/myfeature $TRUNK_WC。現在你已經到了傳統智慧的地步,你必須刪除你的功能分支或者只做一個記錄合併。相反,朱利安發現,如果你遵循這些規則,你可以繼續使用分支。

  • 你在相同的方向兩支之間的最後合併合併每次你做使用--reintegrate選項。將分支的創建視爲與創建位置的合併。

  • 每次更改您在兩個分支之間合併的方向時,都會使用--reintegrate進行合併。

在你的具體情況下,你正在改變你已經合併的方向。 r7正在從分支B合併到分支A. r9從分支A合併到分支B.因此,當您開始進行r9合併時,您需要使用--reintegrate。這個邏輯正是Subversion爲1.8所做的。

最後,我不建議你在這裏做兄弟分支之間的合併。很多簡單的例子,比如你在這裏做的事情都能很好地工作。但是,如果您例如分割一個文件(svn cp file file2,將文件1的一部分和file2中的不同部分刪除),那麼當您嘗試將兩個功能分支的最後一個合併回到trunk時會遇到問題(假設您已將拆分合併到兩個兄弟分行)。最好將合併限制在兩個分支(兒童和父母)之間。您可以在轉到其父母的父母之前將其他分支關閉分支併合並回父母等,並且沒問題。我們希望即使這些事情在未來也能正常工作,但現在情況就是這樣,情況目前在1.8(現在遠比過去好,但不如我們想要的好)。