svn檔案衝突,樹衝突詳解

y_keven發表於2014-06-23

解決衝突

偶爾,當你從版本庫更新、合併檔案時,或者切換工作副本至一個不同的 URL 時你會遇到衝突。有兩種衝突:

檔案衝突

當兩名(或更多)開發人員修改了同一個檔案中相鄰或相同的行時就會發生檔案衝突。

樹衝突

當一名開發人員移動、重新命名、刪除一個檔案或資料夾,而另一名開發人員也對它們進行了移動、重新命名、刪除或者僅僅是修改時就會發生樹衝突。

檔案衝突

當兩名或更多開發人員修改了同一個檔案中相鄰或相同的行時就會發生檔案衝突。由於 Subversion 不知道你的專案的具體情況,它把解決衝突的工作留給了開發人員。一旦出現衝突,你就應該開啟有問題的檔案,查詢以字串<<<<<<<開頭的行。有衝突的區域用如下的方式標記:

<<<<<<< 檔名
  你的修改
=======
  合併自版本庫中的程式碼
>>>>>>> 版本

 

對於每個衝突的檔案 Subversion 在你的目錄下放置了三個檔案:

檔名.mine

這是你的檔案,在你更新你的工作副本之前存在於你的的工作副本中——也就是說,沒有衝突標誌。這個檔案除了你的最新修改外沒有別的東西。

檔名.r 版本

這是在你更新你的工作副本之前的基礎版本(BASE revision)檔案。也就是說,它是在你做最後修改之前所檢出的檔案。

檔名.r 新版本

這個檔案是當你更新你的工作副本時,你的 Subversion 客戶端從伺服器接收到的。這個檔案對應於版本庫中的最新版本。

假設衝突的檔名是aa.java

你可以通過右擊檔案aa.java 開啟選單 TortoiseSVN編輯衝突 開啟後,編輯器會列出與版本庫檔案的衝突部分,你需要衝定哪些程式碼是需要的,做一些必要的修改然後儲存。

當我們再開啟aa.java時,裡面的<<<<< 符號便消除了,這標誌著衝突已經解決了。

然後,執行選單 TortoiseSVN已解決的...,此時便可以提交了。需要注意的是“已解決...”並不是真正的解決了衝突,它只是刪除了filename.ext.minefilename.ext.r*兩個檔案,允許你提交修改。如果剛開始就執行“已解決的”,檔案便可以提交,但是aa.java中的衝突依然沒有解決,內容還是

<<<<<<< 檔名
  你的修改
=======
  合併自版本庫中的程式碼
>>>>>>> 版本

 

所以在這之前一定要 開啟選單 TortoiseSVN編輯衝突 把衝突解決了再點選 “已解決”

如果你的二進位制檔案有衝突,Subversion不會試圖合併檔案。本地檔案保持不變(完全是你最後修改時的樣子),但你會看到filename.ext.r*檔案。如果你要撤消你的修改,保留版本庫中的版本,請使用還原(Revert)命令。如果你要保持你的版本覆蓋版本庫中的版本,使用已解決命令,然後提交你的版本。

你可以右擊父資料夾,選擇TortoiseSVN 已解決...,使用“已解決”命令來解決多個檔案。這個操作會出現一個對話方塊,列出資料夾下所有有衝突的檔案,你可以選擇將哪些標記成已解決。

樹衝突

當一名開發人員移動、重新命名、刪除一個檔案或資料夾,而另一名開發人員也對它們進行了移動、重新命名、刪除或者僅僅是修改時就會發生樹衝突。有很多種不同的情形可以導致樹衝突,而且不同的情形需要不同的步驟來解決衝突。

當一個檔案通過 Subversion 在本機刪除後,檔案也從本機檔案系統中刪除。因此即使它是樹衝突的一部分,卻既不能顯示衝突的疊加圖示也不能通過右鍵單擊來解決衝突。使用檢查修改對話方塊來獲得編輯衝突選項。

TortoiseSVN 能夠協助找到合併更改的正確位置,但是需要作一些額外的工作來整理衝突。請牢記: 當進行一次更新操作後,工作副本的基礎檔案將會包括每一個專案在執行更新操作時版本庫中的版本。如果你在進行更新後再撤銷更改,工作副本將返回到版本庫的狀態,而不是你開始進行更改前的狀態。

本地刪除,當更新時有更改進入

  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 的更改。

如果 TortoiseSVN 能夠找到被改名為 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 並將其提交至版本庫中

當資料夾改名時有類似的案例,但是在 Subversion 1.6 中還未被識別...

  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防止衝突的方法:

①儘量將分成多個類,每個人負責一些類的開發

② 每天都要更新

SVN使用說明:
更新功能:
當前我正在編輯一個java檔案,如果此時我更新整個工程,當前編輯的會被覆蓋嗎?
答案是否定的。