偶爾,當您從儲存庫更新/合併檔案,或將您的工作副本切換到不同的 URL 時,您會遇到衝突。衝突有兩種:
當兩位(或更多)開發人員變更了同一個檔案的相同幾行程式碼時,就會發生檔案衝突。
當一位開發人員移動/重新命名/刪除了檔案或資料夾,而另一位開發人員也移動/重新命名/刪除了該檔案或資料夾,或只是修改了它時,就會發生樹狀衝突。
當兩位或更多開發人員變更了同一個檔案的相同幾行程式碼時,就會發生檔案衝突。由於 Subversion 不了解您的專案,因此它將解決衝突的責任留給開發人員。文字檔案中發生衝突的區域會像這樣標記:
<<<<<<< filename your changes ======= code merged from repository >>>>>>> revision
此外,對於每個發生衝突的檔案,Subversion 會在您的目錄中放置三個額外的檔案
這是您在更新工作副本之前,工作副本中存在的檔案版本 - 也就是說,沒有衝突標記。此檔案包含您的最新變更,沒有其他內容。
這是您更新工作副本之前,BASE 修訂版本的檔案。也就是說,這是您在進行最新編輯之前簽出的檔案。
這是您的 Subversion 用戶端在您更新工作副本時,剛從伺服器收到的檔案。此檔案對應於儲存庫的 HEAD 修訂版本。
您可以啟動外部合併工具/衝突編輯器,方法是點擊<<<<<<<
開頭的行。
之後,執行指令 filename.ext.mine
和 filename.ext.r*
檔案,以便讓您可以提交您的變更。
如果您與二進制檔案發生衝突,Subversion 不會嘗試自行合併檔案。本機檔案保持不變(完全與您上次變更時相同),並且您擁有 filename.ext.r*
檔案。如果您想捨棄您的變更並保留儲存庫版本,只需使用「還原」指令。如果您想保留您的版本並覆寫儲存庫版本,請使用「已解決」指令,然後提交您的版本。
如果您在父資料夾上按一下滑鼠右鍵並選取
→ ,則可以對多個檔案使用「已解決」指令。這將會彈出一個對話方塊,列出該資料夾中所有發生衝突的檔案,您可以選取要標記為已解決的檔案。當兩位或更多開發人員變更了相同的屬性時,就會發生屬性衝突。與檔案內容一樣,解決衝突只能由開發人員完成。
如果其中一個變更必須覆寫另一個變更,則選擇使用本機屬性解決或使用遠端屬性解決選項。如果必須合併變更,則選取手動編輯屬性,整理出屬性值應該是什麼,並標記為已解決。
當一位開發人員移動/重新命名/刪除了檔案或資料夾,而另一位開發人員也移動/重新命名/刪除了該檔案或資料夾,或只是修改了它時,就會發生樹狀衝突。有許多不同的情況可能導致樹狀衝突,所有這些情況都需要不同的步驟來解決衝突。
當檔案在本機 Subversion 中被刪除時,該檔案也會從本機檔案系統中刪除,因此即使它是樹狀衝突的一部分,它也無法顯示衝突覆蓋圖示,而且您也無法在它上面按一下滑鼠右鍵來解決衝突。請改用檢查修改對話方塊來存取編輯衝突選項。
TortoiseSVN 可以協助找到合併變更的正確位置,但可能需要額外的工作來整理衝突。請記住,在更新之後,工作 BASE 將始終包含每個項目在更新時儲存庫中的修訂版本。如果您在更新後還原變更,它會回到儲存庫狀態,而不是您開始進行本機變更時的狀態。
開發人員 A 修改了 Foo.c
並將其提交到儲存庫。
開發人員 B 同時將 Foo.c
移動到他的工作副本中的 Bar.c
,或者只是刪除了 Foo.c
或其父資料夾。
開發人員 B 的工作副本的更新導致樹狀衝突
Foo.c
已從工作副本中刪除,但標記為樹狀衝突。
如果衝突是由重新命名而不是刪除引起的,則 Bar.c
會標記為已新增,但不包含開發人員 A 的修改。
開發人員 B 現在必須選擇是否保留開發人員 A 的變更。如果是檔案重新命名,他可以將 Foo.c
的變更合併到重新命名的檔案 Bar.c
中。對於簡單的檔案或目錄刪除,他可以選擇保留包含開發人員 A 變更的項目並捨棄刪除。或者,透過將衝突標記為已解決而不執行任何操作,他可以有效地捨棄開發人員 A 的變更。
衝突編輯對話方塊提供合併變更的功能,如果它可以找到重新命名的 Bar.c
的原始檔案。如果有多個檔案可能是移動來源,則會顯示每個檔案的按鈕,讓您可以選擇正確的檔案。
開發人員 A 將 Foo.c
移動到 Bar.c
並將其提交到儲存庫。
開發人員 B 修改了他的工作副本中的 Foo.c
。
或者在資料夾移動的情況下...
開發人員 A 將父資料夾 FooFolder
移動到 BarFolder
並將其提交到儲存庫。
開發人員 B 修改了他的工作副本中的 Foo.c
。
開發人員 B 的工作副本的更新導致樹狀衝突。對於簡單的檔案衝突
Bar.c
作為一般檔案新增到工作副本中。
Foo.c
標記為已新增(具有歷史記錄)並具有樹狀衝突。
對於資料夾衝突
BarFolder
作為一般資料夾新增到工作副本中。
FooFolder
標記為已新增(具有歷史記錄)並具有樹狀衝突。
Foo.c
標記為已修改。
開發人員 B 現在必須決定是否採用開發人員 A 的重組,並將她的變更合併到新結構中的對應檔案中,或者只是還原 A 的變更並保留本機檔案。
為了將她的本機變更與重新調整合併,開發人員 B 必須首先找出衝突檔案 Foo.c
在儲存庫中被重新命名/移動到哪個檔案名稱。這可以使用日誌對話方塊來完成。然後使用顯示正確來源檔案的按鈕來解決衝突。
如果開發人員 B 認為 A 的變更是錯誤的,那麼她必須在衝突編輯器對話方塊中選擇標記為已解決按鈕。這會將衝突檔案/資料夾標記為已解決,但開發人員 A 的變更需要手動移除。同樣,日誌對話方塊有助於追蹤移動了什麼。
開發人員 A 將 Foo.c
移動到 Bar.c
並將其提交到儲存庫。
開發人員 B 將 Foo.c
移動到 Bix.c
。
開發人員 B 的工作副本的更新導致樹狀衝突
Bix.c
標記為已新增並具有歷史記錄。
Bar.c
以「一般」狀態新增到工作副本中。
Foo.c
標記為已刪除並具有樹狀衝突。
為了解決此衝突,開發人員 B 必須找出衝突檔案 Foo.c
在儲存庫中被重新命名/移動到哪個檔案名稱。這可以使用日誌對話方塊來完成。
然後開發人員 B 必須決定保留哪個新的 Foo.c
檔案名稱 - 開發人員 A 完成的檔案名稱或他自己重新命名的檔案名稱。
在開發人員 B 手動解決衝突後,必須使用衝突編輯器對話方塊中的按鈕將樹狀衝突標記為已解決。
在主幹上工作的開發人員 A 修改了 Foo.c
並將其提交到儲存庫
在分支上工作的開發人員 B 將 Foo.c
移動到 Bar.c
並將其提交到儲存庫
將開發人員 A 的主幹變更合併到開發人員 B 的分支工作副本中會導致樹狀衝突
Bar.c
已在工作副本中,狀態為「一般」。
Foo.c
標記為遺失並具有樹狀衝突。
為了解決此衝突,開發人員 B 必須在衝突編輯器對話方塊中將檔案標記為已解決,這將會將其從衝突清單中移除。然後她必須決定是否要將遺失的檔案 Foo.c
從儲存庫複製到工作副本,是否要將開發人員 A 對 Foo.c
的變更合併到重新命名的 Bar.c
中,或者是否要忽略這些變更,方法是將衝突標記為已解決,然後什麼都不做。
請注意,如果您從儲存庫複製遺失的檔案,然後標記為已解決,則您的副本將再次被移除。您必須先解決衝突。
在主幹上工作的開發人員 A 將 Foo.c
移動到 Bar.c
並將其提交到儲存庫。
在分支上工作的開發人員 B 修改了 Foo.c
並將其提交到儲存庫。
在主幹上工作的開發人員 A 將父資料夾 FooFolder
移動到 BarFolder
並將其提交到儲存庫。
在分支上工作的開發人員 B 修改了她的工作副本中的 Foo.c
。
將開發人員 A 的主幹變更合併到開發人員 B 的分支工作副本中會導致樹狀衝突
Bar.c
標記為已新增。
Foo.c
標記為已修改並具有樹狀衝突。
開發人員 B 現在必須決定是否採用開發人員 A 的重組,並將她的變更合併到新結構中的對應檔案中,或者只是還原 A 的變更並保留本機檔案。
為了將她的本機變更與重新調整合併,開發人員 B 必須首先找出衝突檔案 Foo.c
在儲存庫中被重新命名/移動到哪個檔案名稱。這可以使用合併來源的日誌對話方塊來完成。衝突編輯器僅顯示工作副本的日誌,因為它不知道合併中使用了哪個路徑,因此您必須自行找到該路徑。然後必須手動合併變更,因為目前沒有任何方法可以自動化甚至簡化此過程。一旦變更被移植過來,衝突路徑就是多餘的,可以刪除。
如果開發人員 B 認為 A 的變更是錯誤的,那麼她必須在衝突編輯器對話方塊中選擇標記為已解決按鈕。這會將衝突檔案/資料夾標記為已解決,但開發人員 A 的變更需要手動移除。同樣,合併來源的日誌對話方塊有助於追蹤移動了什麼。
在主幹上工作的開發人員 A 將 Foo.c
移動到 Bar.c
並將其提交到儲存庫。
在分支上工作的開發人員 B 將 Foo.c
移動到 Bix.c
並將其提交到儲存庫。
將開發人員 A 的主幹變更合併到開發人員 B 的分支工作副本中會導致樹狀衝突
Bix.c
標記為正常(未修改)狀態。
Bar.c
標記為已新增並具有歷史記錄。
Foo.c
標記為遺失並具有樹狀衝突。
為了解決此衝突,開發人員 B 必須找出衝突檔案 Foo.c
在儲存庫中被重新命名/移動到哪個檔案名稱。這可以使用合併來源的日誌對話方塊來完成。
然後開發人員 B 必須決定保留哪個新的 Foo.c
檔案名稱 - 開發人員 A 完成的檔案名稱或他自己重新命名的檔案名稱。
在開發人員 B 手動解決衝突後,必須使用衝突編輯器對話方塊中的按鈕將樹狀衝突標記為已解決。