手冊

解決衝突

偶爾,當您從儲存庫更新/合併檔案,或將您的工作副本切換到不同的 URL 時,您會遇到衝突。衝突有兩種:

檔案衝突

當兩位(或更多)開發人員變更了同一個檔案的相同幾行程式碼時,就會發生檔案衝突。

樹狀衝突

當一位開發人員移動/重新命名/刪除了檔案或資料夾,而另一位開發人員也移動/重新命名/刪除了該檔案或資料夾,或只是修改了它時,就會發生樹狀衝突。

檔案衝突

當兩位或更多開發人員變更了同一個檔案的相同幾行程式碼時,就會發生檔案衝突。由於 Subversion 不了解您的專案,因此它將解決衝突的責任留給開發人員。文字檔案中發生衝突的區域會像這樣標記:

<<<<<<< filename
your changes
=======
code merged from repository
>>>>>>> revision
      

此外,對於每個發生衝突的檔案,Subversion 會在您的目錄中放置三個額外的檔案

filename.ext.mine

這是您在更新工作副本之前,工作副本中存在的檔案版本 - 也就是說,沒有衝突標記。此檔案包含您的最新變更,沒有其他內容。

filename.ext.rOLDREV

這是您更新工作副本之前,BASE 修訂版本的檔案。也就是說,這是您在進行最新編輯之前簽出的檔案。

filename.ext.rNEWREV

這是您的 Subversion 用戶端在您更新工作副本時,剛從伺服器收到的檔案。此檔案對應於儲存庫的 HEAD 修訂版本。

您可以啟動外部合併工具/衝突編輯器,方法是點擊TortoiseSVN編輯衝突,或者您可以使用任何文字編輯器手動解決衝突。您應該決定程式碼應該是什麼樣子,進行必要的變更並儲存檔案。使用合併工具(例如 TortoiseMerge 或其他流行的工具之一)通常是比較容易的選項,因為它們通常以 3 個窗格的視圖呈現相關檔案,而且您不必擔心衝突標記。如果您確實使用文字編輯器,那麼您應該搜尋以字串 <<<<<<< 開頭的行。

之後,執行指令 TortoiseSVN已解決 並提交您的修改到儲存庫。請注意,「已解決」指令實際上並未解決衝突。它只是移除 filename.ext.minefilename.ext.r* 檔案,以便讓您可以提交您的變更。

如果您與二進制檔案發生衝突,Subversion 不會嘗試自行合併檔案。本機檔案保持不變(完全與您上次變更時相同),並且您擁有 filename.ext.r* 檔案。如果您想捨棄您的變更並保留儲存庫版本,只需使用「還原」指令。如果您想保留您的版本並覆寫儲存庫版本,請使用「已解決」指令,然後提交您的版本。

如果您在父資料夾上按一下滑鼠右鍵並選取 TortoiseSVN已解決...,則可以對多個檔案使用「已解決」指令。這將會彈出一個對話方塊,列出該資料夾中所有發生衝突的檔案,您可以選取要標記為已解決的檔案。

屬性衝突

當兩位或更多開發人員變更了相同的屬性時,就會發生屬性衝突。與檔案內容一樣,解決衝突只能由開發人員完成。

如果其中一個變更必須覆寫另一個變更,則選擇使用本機屬性解決使用遠端屬性解決選項。如果必須合併變更,則選取手動編輯屬性,整理出屬性值應該是什麼,並標記為已解決。

樹狀衝突

當一位開發人員移動/重新命名/刪除了檔案或資料夾,而另一位開發人員也移動/重新命名/刪除了該檔案或資料夾,或只是修改了它時,就會發生樹狀衝突。有許多不同的情況可能導致樹狀衝突,所有這些情況都需要不同的步驟來解決衝突。

當檔案在本機 Subversion 中被刪除時,該檔案也會從本機檔案系統中刪除,因此即使它是樹狀衝突的一部分,它也無法顯示衝突覆蓋圖示,而且您也無法在它上面按一下滑鼠右鍵來解決衝突。請改用檢查修改對話方塊來存取編輯衝突選項。

TortoiseSVN 可以協助找到合併變更的正確位置,但可能需要額外的工作來整理衝突。請記住,在更新之後,工作 BASE 將始終包含每個項目在更新時儲存庫中的修訂版本。如果您在更新後還原變更,它會回到儲存庫狀態,而不是您開始進行本機變更時的狀態。

本機刪除,更新時傳入編輯

  1. 開發人員 A 修改了 Foo.c 並將其提交到儲存庫。

  2. 開發人員 B 同時將 Foo.c 移動到他的工作副本中的 Bar.c,或者只是刪除了 Foo.c 或其父資料夾。

開發人員 B 的工作副本的更新導致樹狀衝突

  • Foo.c 已從工作副本中刪除,但標記為樹狀衝突。

  • 如果衝突是由重新命名而不是刪除引起的,則 Bar.c 會標記為已新增,但不包含開發人員 A 的修改。

開發人員 B 現在必須選擇是否保留開發人員 A 的變更。如果是檔案重新命名,他可以將 Foo.c 的變更合併到重新命名的檔案 Bar.c 中。對於簡單的檔案或目錄刪除,他可以選擇保留包含開發人員 A 變更的項目並捨棄刪除。或者,透過將衝突標記為已解決而不執行任何操作,他可以有效地捨棄開發人員 A 的變更。

衝突編輯對話方塊提供合併變更的功能,如果它可以找到重新命名的 Bar.c 的原始檔案。如果有多個檔案可能是移動來源,則會顯示每個檔案的按鈕,讓您可以選擇正確的檔案。

本機編輯,更新時傳入刪除

  1. 開發人員 A 將 Foo.c 移動到 Bar.c 並將其提交到儲存庫。

  2. 開發人員 B 修改了他的工作副本中的 Foo.c

或者在資料夾移動的情況下...

  1. 開發人員 A 將父資料夾 FooFolder 移動到 BarFolder 並將其提交到儲存庫。

  2. 開發人員 B 修改了他的工作副本中的 Foo.c

開發人員 B 的工作副本的更新導致樹狀衝突。對於簡單的檔案衝突

  • Bar.c 作為一般檔案新增到工作副本中。

  • Foo.c 標記為已新增(具有歷史記錄)並具有樹狀衝突。

對於資料夾衝突

  • BarFolder 作為一般資料夾新增到工作副本中。

  • FooFolder 標記為已新增(具有歷史記錄)並具有樹狀衝突。

    Foo.c 標記為已修改。

開發人員 B 現在必須決定是否採用開發人員 A 的重組,並將她的變更合併到新結構中的對應檔案中,或者只是還原 A 的變更並保留本機檔案。

為了將她的本機變更與重新調整合併,開發人員 B 必須首先找出衝突檔案 Foo.c 在儲存庫中被重新命名/移動到哪個檔案名稱。這可以使用日誌對話方塊來完成。然後使用顯示正確來源檔案的按鈕來解決衝突。

如果開發人員 B 認為 A 的變更是錯誤的,那麼她必須在衝突編輯器對話方塊中選擇標記為已解決按鈕。這會將衝突檔案/資料夾標記為已解決,但開發人員 A 的變更需要手動移除。同樣,日誌對話方塊有助於追蹤移動了什麼。

本機刪除,更新時傳入刪除

  1. 開發人員 A 將 Foo.c 移動到 Bar.c 並將其提交到儲存庫。

  2. 開發人員 B 將 Foo.c 移動到 Bix.c

開發人員 B 的工作副本的更新導致樹狀衝突

  • Bix.c 標記為已新增並具有歷史記錄。

  • Bar.c 以「一般」狀態新增到工作副本中。

  • Foo.c 標記為已刪除並具有樹狀衝突。

為了解決此衝突,開發人員 B 必須找出衝突檔案 Foo.c 在儲存庫中被重新命名/移動到哪個檔案名稱。這可以使用日誌對話方塊來完成。

然後開發人員 B 必須決定保留哪個新的 Foo.c 檔案名稱 - 開發人員 A 完成的檔案名稱或他自己重新命名的檔案名稱。

在開發人員 B 手動解決衝突後,必須使用衝突編輯器對話方塊中的按鈕將樹狀衝突標記為已解決。

本機遺失,合併時傳入編輯

  1. 在主幹上工作的開發人員 A 修改了 Foo.c 並將其提交到儲存庫

  2. 在分支上工作的開發人員 B 將 Foo.c 移動到 Bar.c 並將其提交到儲存庫

將開發人員 A 的主幹變更合併到開發人員 B 的分支工作副本中會導致樹狀衝突

  • Bar.c 已在工作副本中,狀態為「一般」。

  • Foo.c 標記為遺失並具有樹狀衝突。

為了解決此衝突,開發人員 B 必須在衝突編輯器對話方塊中將檔案標記為已解決,這將會將其從衝突清單中移除。然後她必須決定是否要將遺失的檔案 Foo.c 從儲存庫複製到工作副本,是否要將開發人員 A 對 Foo.c 的變更合併到重新命名的 Bar.c 中,或者是否要忽略這些變更,方法是將衝突標記為已解決,然後什麼都不做。

請注意,如果您從儲存庫複製遺失的檔案,然後標記為已解決,則您的副本將再次被移除。您必須先解決衝突。

本機編輯,合併時傳入刪除

  1. 在主幹上工作的開發人員 A 將 Foo.c 移動到 Bar.c 並將其提交到儲存庫。

  2. 在分支上工作的開發人員 B 修改了 Foo.c 並將其提交到儲存庫。

  1. 在主幹上工作的開發人員 A 將父資料夾 FooFolder 移動到 BarFolder 並將其提交到儲存庫。

  2. 在分支上工作的開發人員 B 修改了她的工作副本中的 Foo.c

將開發人員 A 的主幹變更合併到開發人員 B 的分支工作副本中會導致樹狀衝突

  • Bar.c 標記為已新增。

  • Foo.c 標記為已修改並具有樹狀衝突。

開發人員 B 現在必須決定是否採用開發人員 A 的重組,並將她的變更合併到新結構中的對應檔案中,或者只是還原 A 的變更並保留本機檔案。

為了將她的本機變更與重新調整合併,開發人員 B 必須首先找出衝突檔案 Foo.c 在儲存庫中被重新命名/移動到哪個檔案名稱。這可以使用合併來源的日誌對話方塊來完成。衝突編輯器僅顯示工作副本的日誌,因為它不知道合併中使用了哪個路徑,因此您必須自行找到該路徑。然後必須手動合併變更,因為目前沒有任何方法可以自動化甚至簡化此過程。一旦變更被移植過來,衝突路徑就是多餘的,可以刪除。

如果開發人員 B 認為 A 的變更是錯誤的,那麼她必須在衝突編輯器對話方塊中選擇標記為已解決按鈕。這會將衝突檔案/資料夾標記為已解決,但開發人員 A 的變更需要手動移除。同樣,合併來源的日誌對話方塊有助於追蹤移動了什麼。

本機刪除,合併時傳入刪除

  1. 在主幹上工作的開發人員 A 將 Foo.c 移動到 Bar.c 並將其提交到儲存庫。

  2. 在分支上工作的開發人員 B 將 Foo.c 移動到 Bix.c 並將其提交到儲存庫。

將開發人員 A 的主幹變更合併到開發人員 B 的分支工作副本中會導致樹狀衝突

  • Bix.c 標記為正常(未修改)狀態。

  • Bar.c 標記為已新增並具有歷史記錄。

  • Foo.c 標記為遺失並具有樹狀衝突。

為了解決此衝突,開發人員 B 必須找出衝突檔案 Foo.c 在儲存庫中被重新命名/移動到哪個檔案名稱。這可以使用合併來源的日誌對話方塊來完成。

然後開發人員 B 必須決定保留哪個新的 Foo.c 檔案名稱 - 開發人員 A 完成的檔案名稱或他自己重新命名的檔案名稱。

在開發人員 B 手動解決衝突後,必須使用衝突編輯器對話方塊中的按鈕將樹狀衝突標記為已解決。

其他樹狀衝突

還有其他一些情況被標記為樹狀衝突,僅僅是因為衝突涉及資料夾而不是檔案。例如,如果您在主幹和分支中新增了同名的資料夾,然後嘗試合併,您將會遇到樹狀衝突。如果您想保留合併目標中的資料夾,只需將衝突標記為已解決。如果您想使用合併來源中的資料夾,那麼您需要先 SVN 刪除目標中的資料夾,然後再次執行合併。如果您需要更複雜的操作,則必須手動解決。

TortoiseSVN 首頁