手冊

合併

分支用於維護個別的開發線,在某些階段您會想要將一個分支上所做的變更合併回主幹,或反之亦然。

在開始使用 Subversion 的分支與合併功能之前,務必先了解其運作方式,因為它可能會變得相當複雜。強烈建議您閱讀 Subversion 手冊中的 分支與合併 章節,其中完整描述了其使用方式並提供許多範例。

接下來要注意的重點是,合併永遠發生在工作副本中。如果您想要將變更合併分支中,您必須先檢出該分支的工作副本,並從該工作副本中使用TortoiseSVN合併...來調用合併精靈。

一般來說,最好在未修改的工作副本中執行合併。如果您在您的工作副本中做了其他變更,請先提交這些變更。如果合併不如您預期的順利,您可能想要還原變更,而還原命令將會捨棄所有變更,包括您在合併之前所做的任何變更。

有三種常見的合併使用情境,它們的處理方式略有不同,如下所述。合併精靈的第一頁會要求您選擇所需的方法。

合併修訂版本範圍

此方法涵蓋您對分支(或主幹)進行了一或多個修訂版本,並且想要將這些變更移植到不同分支的情況。

您要求 Subversion 執行的操作如下: 計算從分支 A 的修訂版本 1 [到] 分支 A 的修訂版本 7 所需的變更,並將這些變更應用於我的工作副本(主幹或分支 B)。

如果您將修訂版本範圍留空,Subversion 會使用合併追蹤功能來計算要使用的正確修訂版本範圍。這被稱為重新整合或自動合併。

合併兩個不同的樹狀結構

這是重新整合方法的更一般情況。您要求 Subversion 執行的操作如下: 計算從主幹的最新修訂版本 [到] 分支的最新修訂版本所需的變更,並將這些變更應用於我的工作副本(主幹)。 最終結果是主幹現在看起來與分支完全相同。

如果您的伺服器/儲存庫不支援合併追蹤,那麼這是將分支合併回主幹的唯一方法。另一種使用情境發生在您使用供應商分支,並且需要將新的供應商發佈後的變更合併到您的主幹程式碼中時。如需更多資訊,請閱讀 Subversion 手冊中關於 供應商分支 的章節。

合併修訂版本範圍

圖 4.56。 合併精靈 - 選擇修訂版本範圍

The Merge Wizard - Select Revision Range


從:欄位中,輸入包含您想要移植到工作副本之變更的分支或標籤的完整資料夾 URL。您也可以點擊...來瀏覽儲存庫並找到所需的分支。如果您之前曾從此分支合併過,那麼只需使用下拉式選單,其中顯示了先前使用過的 URL 歷史記錄。

如果您要從已重新命名或已刪除的分支合併,那麼您必須回到該分支仍然存在的修訂版本。在這種情況下,您還需要將該修訂版本指定為要合併的修訂版本範圍中的釘住修訂版本(如下所示),否則當合併在 HEAD 找不到該路徑時,合併將會失敗。

要合併的修訂版本範圍欄位中,輸入您想要合併的修訂版本清單。這可以是單個修訂版本、以逗號分隔的特定修訂版本清單、或以破折號分隔的修訂版本範圍,或是這些的任何組合。

如果您需要為合併指定釘住修訂版本,請在修訂版本的末尾添加釘住修訂版本,例如 5-7,10@3。在上面的範例中,將合併修訂版本 5、6、7 和 10,其中 3 是釘住修訂版本。

重要事項

TortoiseSVN 指定修訂版本範圍的方式與命令列用戶端相比存在重要差異。視覺化它的最簡單方法是將其視為帶有柱子和柵欄板的柵欄。

使用命令列用戶端,您可以使用兩個柵欄柱修訂版本來指定要合併的變更,這些修訂版本指定了之前之後的點。

使用 TortoiseSVN,您可以使用柵欄板指定要合併的變更集。當您使用日誌對話方塊來指定要合併的修訂版本時,原因就很清楚了,其中每個修訂版本都顯示為一個變更集。

如果您要分塊合併修訂版本,Subversion 手冊中顯示的方法會讓您這次合併 100-200,下次合併 200-300。使用 TortoiseSVN,您這次將合併 100-200,下次將合併 201-300。

這種差異在郵件列表中引起了很多爭議。我們承認它與命令列用戶端有所不同,但我們相信對於大多數 GUI 使用者來說,更容易理解我們實作的方法。

選擇所需修訂版本範圍的最簡單方法是點擊顯示日誌,因為這將列出最近的變更及其日誌註解。如果您想要合併來自單個修訂版本的變更,只需選擇該修訂版本。如果您想要合併來自多個修訂版本的變更,請選擇該範圍(使用常用的 Shift 修飾鍵)。點擊確定,要合併的修訂版本號碼清單將會為您填寫。

如果您想要將變更移出您的工作副本,以還原已提交的變更,請選擇要還原的修訂版本,並確保勾選反向合併方塊。

如果您已經從此分支合併了一些變更,希望您在提交變更時,已在日誌訊息中記錄了上次合併的修訂版本。在這種情況下,您可以使用工作副本的顯示日誌來追蹤該日誌訊息。請記住,我們將修訂版本視為變更集,您應該使用上次合併的結束點之後的修訂版本作為這次合併的起點。例如,如果您上次合併了修訂版本 37 到 39,那麼這次合併的起點應該是修訂版本 40。

如果您使用 Subversion 的合併追蹤功能,您無需記住哪些修訂版本已經合併 - Subversion 會為您記錄。如果您將修訂版本範圍留空,則將包含所有尚未合併的修訂版本。閱讀名為「合併追蹤」的章節以了解更多資訊。

當使用合併追蹤時,日誌對話方塊將以灰色顯示先前合併的修訂版本,以及早於共同祖先點(即分支複製之前)的修訂版本。隱藏不可合併的修訂版本核取方塊可讓您完全篩選掉這些修訂版本,以便您只看到可以合併的修訂版本。

如果其他人可能正在提交變更,那麼請小心使用 HEAD 修訂版本。如果其他人在您上次更新後進行了提交,它可能不會指向您認為的修訂版本。

如果您將修訂版本範圍留空,或勾選了所有修訂版本單選按鈕,那麼 Subversion 會合併所有尚未合併的修訂版本。這被稱為重新整合或自動合併。

重新整合合併有一些適用條件。首先,伺服器必須支援合併追蹤。工作副本的深度必須是無限的(沒有稀疏檢出),並且它不能有任何本地修改、切換項目或已更新到 HEAD 以外修訂版本的項目。在分支開發期間對主幹所做的所有變更都必須合併到分支中(或標記為已合併)。要合併的修訂版本範圍將自動計算。

點擊下一步並前往名為「合併選項」的章節

合併兩個不同的樹狀結構

圖 4.57。 合併精靈 - 樹狀結構合併

The Merge Wizard - Tree Merge


如果您使用此方法將功能分支合併回主幹,則需要從主幹的工作副本中啟動合併精靈。

從:欄位中,輸入主幹的完整資料夾 URL。這聽起來可能很奇怪,但請記住,主幹是您想要在其中添加分支變更的起點。您也可以點擊...來瀏覽儲存庫。

到:欄位中,輸入功能分支的完整資料夾 URL。

從修訂版本欄位和到修訂版本欄位中,輸入兩個樹狀結構同步的最後一個修訂版本號碼。如果您確定沒有其他人正在進行提交,則可以在兩種情況下都使用 HEAD 修訂版本。如果有可能自從同步以來其他人可能進行了提交,請使用特定的修訂版本號碼,以避免遺失較新的提交。

您也可以使用顯示日誌來選擇修訂版本。

合併選項

精靈的這一頁可讓您在開始合併程序之前指定進階選項。大多數時候,您只需使用預設設定即可。

您可以指定用於合併的深度,即合併應深入到您的工作副本的程度。深度術語在名為「檢出深度」的章節中描述。預設深度為工作副本,它使用現有的深度設定,而且幾乎總是您想要的。

大多數時候,您都希望合併考慮檔案的歷史記錄,以便合併相對於共同祖先的變更。有時您可能需要合併可能相關但不在您的儲存庫中的檔案。例如,您可能已將第三方程式庫的版本 1 和版本 2 匯入到兩個不同的目錄中。雖然它們在邏輯上相關,但 Subversion 並不知道這一點,因為它只看到您匯入的壓縮檔。如果您嘗試合併這兩個樹狀結構之間的差異,您會看到完整的移除,然後是完整的添加。若要讓 Subversion 僅使用基於路徑的差異而不是基於歷史記錄的差異,請勾選忽略祖先方塊。在 Subversion 手冊中閱讀有關此主題的更多資訊, 注意或忽略祖先

您可以指定處理行尾和空白字元變更的方式。這些選項在名為「行尾和空白字元選項」的章節中描述。預設行為是將所有空白字元和行尾差異視為要合併的實際變更。

標記為強制合併的核取方塊用於避免樹狀結構衝突,其中傳入的刪除會影響本地修改或根本未版本化的檔案。如果檔案被刪除,則無法復原它,這就是為什麼預設情況下未勾選該選項的原因。

標記為允許混合修訂版本(不建議)的核取方塊用於允許合併到混合修訂版本的工作副本中(對應於命令列選項 --allow-mixed-revisions)。自 Subversion 1.7 以來的預設設定是不允許合併到混合修訂版本的工作副本中。原因在 Subversion 手冊中 保持分支同步 章節的末尾描述。如果您了解合併到混合修訂版本的工作副本中可能發生的問題,您可以選取此核取方塊以繼續執行合併。

如果您正在使用合併追蹤,並且想要將修訂版本標記為已合併,而實際上並未在此處執行合併,請勾選僅記錄合併核取方塊。您可能想要這樣做的原因有兩個。可能是合併對於合併演算法來說太複雜,因此您可以手動編寫變更,然後將變更標記為已合併,以便合併追蹤演算法知道它。或者您可能想要防止特定修訂版本被合併。將其標記為已合併將防止使用感知合併追蹤的用戶端進行合併。

現在一切都已設定完成,您只需點擊合併按鈕即可。如果您想要預覽結果,測試合併會模擬合併操作,但不會修改工作副本。它會向您顯示一個檔案清單,這些檔案將因實際合併而變更,並註記可能發生衝突的檔案。由於合併追蹤使合併程序變得更加複雜,因此無法保證提前找出合併是否會在沒有衝突的情況下完成,因此在測試合併中標記為衝突的檔案實際上可能會在沒有任何問題的情況下合併。

合併進度對話方塊會顯示合併的每個階段,以及相關的修訂版本範圍。這可能表示比您預期的多一個修訂版本。例如,如果您要求合併修訂版本 123,進度對話方塊將報告 正在合併修訂版本 122 到 123 。要理解這一點,您需要記住合併與差異密切相關。合併程序的工作原理是產生儲存庫中兩個點之間差異的清單,並將這些差異應用於您的工作副本。進度對話方塊只是顯示差異的起點和終點。

檢閱合併結果

合併現已完成。最好查看合併,看看它是否符合預期。合併通常相當複雜。如果分支偏離主幹太遠,則通常會發生衝突。

提示

每當將修訂版本合併到工作副本時,TortoiseSVN 都會從所有合併的修訂版本產生日誌訊息。這些訊息可以從提交對話方塊中的最近訊息按鈕取得。

若要自訂產生的訊息,請在您的工作副本上設定對應的專案屬性。請參閱名為「合併日誌訊息範本」的章節

對於 1.5 之前的 Subversion 用戶端和伺服器,不會儲存合併資訊,並且必須手動追蹤合併的修訂版本。當您測試變更並準備提交此修訂版本時,您的提交日誌訊息應始終包含已在合併中移植的修訂版本號碼。如果您想要稍後再次應用合併,您將需要知道您已合併的內容,因為您不想多次移植變更。如需更多相關資訊,請參閱 Subversion 手冊中 合併的最佳實務

如果您的伺服器和所有用戶端都執行 Subversion 1.5 或更高版本,則合併追蹤功能將記錄合併的修訂版本,並避免修訂版本被合併多次。這使您的生活變得更加簡單,因為您只需每次合併整個修訂版本範圍,並且知道實際上只會合併新的修訂版本。

分支管理非常重要。如果您想要使此分支與主幹保持同步,則應確保經常合併,以便分支和主幹不會偏離太遠。當然,您仍然應該避免重複合併變更,如上所述。

提示

如果您剛剛將功能分支合併回主幹,則主幹現在包含所有新的功能程式碼,並且該分支已過時。如果需要,您現在可以從儲存庫中刪除它。

重要事項

Subversion 無法合併檔案與資料夾,反之亦然 - 只能將資料夾合併到資料夾,檔案合併到檔案。如果您點擊檔案並開啟合併對話方塊,那麼您必須在該對話方塊中提供檔案的路徑。如果您選擇資料夾並開啟對話方塊,那麼您必須為合併指定資料夾 URL。

合併追蹤

Subversion 1.5 引入了合併追蹤功能。當您將變更從一個樹狀結構合併到另一個樹狀結構時,將會儲存合併的修訂版本號碼,並且此資訊可用於多種不同的用途。

  • 您可以避免重複合併相同修訂版本的危險(重複合併問題)。一旦修訂版本被標記為已合併,未來包含該修訂版本在範圍內的合併將會跳過它。

  • 當您將分支合併回主幹時,日誌對話方塊可以將分支提交顯示為主幹日誌的一部分,從而提供更好的變更追溯性。

  • 當您從合併對話方塊中顯示日誌對話方塊時,已合併的修訂版本會以灰色顯示。

  • 當顯示檔案的 blame 資訊時,您可以選擇顯示合併修訂版本的原始作者,而不是執行合併的人員。

  • 您可以將修訂版本標記為不要合併,方法是將它們包含在已合併的修訂版本清單中,而實際上不執行合併。

合併追蹤資訊由用戶端在執行合併時儲存在 svn:mergeinfo 屬性中。提交合併時,伺服器會將該資訊儲存在資料庫中,當您請求合併、日誌或 blame 資訊時,伺服器可以適當地回應。為了使系統正常運作,您必須確保伺服器、儲存庫和所有用戶端都已升級。較早的用戶端不會儲存 svn:mergeinfo 屬性,而較早的伺服器不會提供新用戶端請求的資訊。

從 Subversion 的 合併追蹤文件 中了解有關合併追蹤的更多資訊。

處理合併後的衝突

重要事項

衝突解決器對話方塊中的文字由 SVN 程式庫提供,因此可能(尚未)像 TortoiseSVN 對話方塊一樣被翻譯。對此感到抱歉。

合併並非總是順利進行。有時會發生衝突。TortoiseSVN 會透過顯示合併衝突對話方塊來協助您完成此程序。

圖 4.58。 合併衝突對話方塊

The Merge Conflict Dialog


可能某些變更已順利合併,而其他本地變更與已提交到儲存庫的變更發生衝突。所有可以合併的變更都會合併。合併衝突對話方塊為您提供了處理衝突行的不同方法。

對於因檔案內容或其屬性變更而發生的正常衝突,對話方塊會顯示按鈕,讓您可以選擇保留或拒絕哪些衝突部分。

延後

現在不處理衝突。讓合併繼續進行,並在合併完成後解決衝突。

接受基礎版本

這會使檔案保持原樣,既沒有來自合併的變更,也沒有您在工作副本中所做的變更。

接受傳入變更

這會捨棄您所有的本地變更,並使用從合併來源傳入的檔案。

拒絕傳入變更

這會捨棄來自合併來源的所有變更,並使檔案保留您的本地編輯。

接受衝突的傳入變更

這會捨棄您的本地變更,這些變更與來自合併來源的變更發生衝突。但它會保留所有不衝突的本地變更。

拒絕衝突

這會捨棄來自合併來源的變更,這些變更與您的本地變更發生衝突。但它會保留所有不與您的本地變更衝突的變更。

標記為已解決

將衝突標記為已解決。此按鈕在您使用編輯按鈕手動編輯衝突並將這些變更儲存回檔案之前,會停用。儲存變更後,按鈕將會啟用。

編輯

啟動合併編輯器,以便您可以手動解決衝突。別忘了儲存檔案,以便標記為已解決按鈕啟用。

如果發生樹狀結構衝突,請先參閱關於各種樹狀結構衝突類型以及它們如何以及為何發生的名為「樹狀結構衝突」的章節

若要在合併後解決樹狀結構衝突,會顯示一個對話方塊,其中包含關於如何解決衝突的各種選項

圖 4.59。 合併樹狀結構衝突對話方塊

The Merge Tree Conflict Dialog


由於存在各種可能的樹狀結構衝突情況,對話方塊將顯示按鈕來解決這些衝突,具體取決於特定的衝突。按鈕文字和標籤說明了解決衝突的選項的作用。如果您不確定,請取消對話方塊或使用延後按鈕稍後解決衝突。

功能分支維護

當您在單獨的分支上開發新功能時,最好制定一個策略,以便在功能完成時重新整合。如果在 trunk 中同時進行其他工作,您可能會發現隨著時間的推移,差異變得很大,並且合併回變得像一場噩夢。

如果功能相對簡單且開發時間不長,那麼您可以採用簡單的方法,即將分支完全隔離,直到功能完成,然後將分支變更合併回主幹。在合併精靈中,這將是一個簡單的合併修訂版本範圍,修訂版本範圍是分支的修訂版本跨度。

如果功能需要更長的時間,並且您需要考慮 trunk 中的變更,那麼您需要保持分支同步。這僅僅意味著您定期將主幹變更合併到分支中,以便分支包含所有主幹變更加上新功能。同步程序使用合併修訂版本範圍。當功能完成時,您可以使用重新整合分支合併兩個不同的樹狀結構將其合併回 trunk

將主幹的所有變更合併到功能分支的另一種(快速)方法是使用擴充內容選單中的TortoiseSVN全部合併...(按住 Shift 鍵,同時右鍵點擊檔案)。

圖 4.60。 全部合併對話方塊

The Merge-All Dialog


此對話方塊非常容易使用。您只需設定合併選項,如名為「合併選項」的章節中所述。其餘的工作由 TortoiseSVN 使用合併追蹤自動完成。

TortoiseSVN 首頁