簡體   English   中英

如何解決在第一個分支中刪除並在第二個分支中重命名的文件的合並沖突?

[英]How to resolve a merge conflict on a file that has been deleted in 1st branch and renamed in 2nd branch?

我正在刪除某些文件夾的分支上工作。 同時,在master分支上,所有根文件夾都已重命名,因此所有文件(包括我已刪除的文件)的路徑都已重命名。

當我嘗試合並時,所有已刪除(在我的分支上)和重命名(在母版上)的所有文件夾的所有文件都發生沖突。 我列出了這些(1000多個)文件的列表,這些文件在git status的Unmerged path中顯示為:

added by them:   FolderRenamed/File1.ext
added by them:   FolderRenamed/File2.ext

我想在此時恢復它們,當我嘗試在分支中合並master時從“ theirs”版本恢復(盡管您可能希望我做相反的事情,並且已確認文件刪除;這將是相同的概念,用“我們的”代替“他們的”)。

我以為我可以為每個文件簡單地調用以下命令:

git checkout --theirs FolderRenamed/File1.ext

但是在文件上調用此命令似乎並沒有實現任何更改。 我的文件仍在“合並路徑”列表中。

有人可以幫助我確定我在做什么錯嗎? git checkout是否無法正常工作,因為本地版本已被刪除?

TL; DR:您只需要git add它們。

更長

當我嘗試合並時,所有已刪除(在我的分支上)和重命名(在主文件上)的所有文件夾的所有文件都發生沖突...

是:運行時,例如:

git checkout branch
git merge master

Git的方法:

  • 標識您當前的提交( HEAD aka branch :它們通過哈希ID選擇一個特定的提交,這也是您現在在索引和工作樹中的提交),也稱為local--ours ,但我只是調用L (左/本地);
  • 標識另一個提交(也稱為master ),也稱為remoteother--theirs ,但我只稱其為R (右/遠程);
  • 查找這兩個提交之間的合並基礎 這是最新的commit-in-common。 我稱其為B。

(請注意,如果您檢出master並運行git merge branch ,則只需要在過程的這一部分交換LR。

實際上,Git運行兩個啟用了重命名檢測的git diff

git diff --find-renames B L > /tmp/b-vs-l.patch
git diff --find-renames B R > /tmp/b-vs-r.patch

結果列出了自基B以來您在L中所做的所有操作的列表,以及自相同基B以來他們在R中所做的所有操作的列表。 然后,Git結合了這些更改。

如果重命名文件,並且他們刪除了“相同”文件(通過重命名檢測檢測到),則這是重命名/刪除沖突。 如果他們重命名了文件而您刪除了該文件,則會遇到相同的沖突。 無論哪種方式,Git都有沖突。

在發生沖突的特殊情況下 (但在通常情況下則不是),Git將在您的索引中保留每個文件的所有三個版本B中的一個,Git在索引中保留為“階段1”; L中的一個,Git在索引中--ours為“階段2”或--ours R中的一個,Git在索引中--theirs為“ stage 3”或--theirs

這些編號較高的舞台文件是Git記住您處於沖突合並中的方式。 通常,索引中的所有文件都處於“零階段”。 如果Git能夠自行解決沖突,它將擦除三個較高的階段,僅保留零階段解決文件。

工作樹中的文件(大多數)獨立於索引中的文件,當然,工作樹沒有階段插槽號。 只能有一個somepath/file1.ext 如果發生重命名/刪除沖突,則基本文件有一個階段1條目, --ours--theirs文件有一個階段2或階段3條目。 另一個級插槽(分別為3或2)保留為空。 git status命令向您顯示這是added by us (1和2占用,3個為空)或added by them (1和3占用,2個為空)。

運行git checkout --ours告訴Git將stage-slot-2版本復制到工作樹中。 運行git checkout --theirs告訴Git將stage-slot-3版本復制到工作樹中。 在這兩種情況下,stage-slot-1條目都沒有任何反應,stage-slot-zero條目保持為空。

運行git add告訴Git將文件從工作樹復制到階段0插槽,完全清除剩余的插槽。 現在文件已解析。

由於Git將重命名的文件保留在工作樹中(使用新名稱),因此在這種情況下,您需要做的就是git add重命名的文件。

雖然這不是唯一的方法

如果運行git checkout commit-specifier -- path ,則Git將從給定的commit-specifier提取給定的path 當Git執行此操作時,它將路徑復制到索引的插槽0中。 這會清除該路徑的所有插槽1-3條目,因此從特定提交中檢出文件的副作用是可以解析該文件。

這與git checkout --ours--theirs不同,因為它們是從現有索引條目中提取 ,因此它們不會寫入插槽0。

因此,您還可以使用git checkout MERGE_HEAD -- paths將重命名的文件提取到其重命名的名稱中,從而解決了該過程中的合並沖突。

git checkout --theirs會檢出“其”版本,但它是從索引中檢出,而不是對其進行更新,並且這並不表示已解決沖突。

從命名提交中檢出將更新索引,並且運行中合並的“其”提示的名稱為MERGE_HEAD 所以

git checkout MERGE_HEAD -- paths/to/files`

簡單地聲明那些正確的版本。

當然git add也會更新索引,因此您可以git checkout --theirs ,檢查結果以確保它是您的意思,然后git add它。

事實證明,正確進行此操作的方式很簡單(如git ...所建議):

git add FolderRenamed/File1.ext

或者,由於我要還原重命名文件夾中的所有文件,因此只需:

git add FolderRenamed

(如果我想刪除文件夾及其內容,我將使用git rm ...)

Git非常強大:)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM