![](/img/trans.png)
[英]Git: Better way to rebase 3rd branch onto 1st branch after 2nd branch merged
[英]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
),也稱為remote , other和--theirs
,但我只稱其為R (右/遠程); (請注意,如果您檢出master
並運行git merge branch
,則只需要在過程的這一部分交換L和R。 )
實際上,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.