我正在我删除了一些文件夹的分支机构上工作。与此同时,在master分支上,所有根文件夹都已重命名,因此所有文件的路径(包括我删除的文件)都已重命名。
当我尝试合并时,我的所有文件夹中的所有文件都被删除(在我的分支上)并重命名(在主服务器上)。我列出了这些(1000+)文件,这些文件在git status的Unmerged路径中显示如下:
added by them: FolderRenamed/File1.ext
added by them: FolderRenamed/File2.ext
我想在这个场合恢复它们,当我尝试在我的分支中合并master时,从“他们的”版本恢复它们(尽管你可能希望我想要反过来,并且已经确认了文件删除;这与“我们的”而不是“他们的”是相同的概念。
我以为我可以简单地为每个文件调用以下命令:
git checkout --theirs FolderRenamed/File1.ext
但似乎不会在文件上调用此命令实现任何更改。我的文件仍在“Umerged paths”列表中。
有人可以帮我确定我做错了什么吗? git checkout是否按预期工作,因为本地版本已被删除?
答案 0 :(得分:3)
TL; DR:你只需要git add
他们。
当我尝试合并时,我的所有文件夹中的所有文件都被删除(在我的分支上)并重命名(在主设备上)...
是:当你跑步时,例如:
git checkout branch
git merge master
GIT中:
HEAD
又名branch
:这些通过哈希ID选择一个特定提交,这也是您现在在索引和工作树中提交的提交,也称为作为本地或--ours
,但我只是称之为 L (左/本地); master
),也称为远程,其他和--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
结果是您在 L 以及 L 中所做的所有事情的列表,以及他们在 R 中所做的一切,因为它们是相同的基础乙。然后Git结合了这些变化。
如果您重命名文件并删除了“相同”文件(通过重命名检测检测到),则这是重命名/删除冲突。如果他们重命名了一个文件并将其删除,则会发生同样的冲突。无论哪种方式,Git都有冲突。
在冲突的特殊情况下(但在普通情况下不是这样),Git会在你的索引中留下每个文件的所有三个版本:来自< em> B ,Git在索引中留下“第1阶段”;来自 L 的那个,Git在索引中留下“第2阶段”或--ours
;以及来自 R 的那个,Git在索引中留下“第3阶段”或--theirs
。
这些编号较高的舞台文件是Git记得您处于冲突合并中的方式。通常,索引中的所有文件都处于“阶段0”。如果Git能够自行解决冲突,它将删除三个更高的阶段,只留下一个阶段零解析文件。
work-tree 中的文件(大部分)独立于索引中的文件,当然,工作树没有阶段插槽编号。只能有一个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会从给定的 path
中提取给定的 commit-specifier
。当Git执行此操作时,它会将路径复制到索引的插槽零中。这会清除该路径的任何插槽1-3条目,因此从特定提交中检出文件的副作用是解析该文件。
这与git checkout --ours
和--theirs
不同,因为它们从现有索引条目中提取 ,因此它们不会写入插槽零。
因此,您还可以使用git checkout MERGE_HEAD -- paths
将重命名的文件解压缩到其重命名的名称中,从而解决流程中的合并冲突。
答案 1 :(得分:2)
git checkout --theirs
会结帐&#34;他们的&#34;版本,但它从索引中检出,而不是更新它,并且没有标记冲突已解决。
从命名提交中签出更新索引,以及飞行中合并的名称&#34;他们的&#34;提示是MERGE_HEAD
。所以
git checkout MERGE_HEAD -- paths/to/files`
简单地声明那些正确的版本。
当然git add
也会更新索引,因此您可以git checkout --theirs
检查结果,确保结果符合您的意思,然后git add
。
答案 2 :(得分:1)
原来这样做的正确方法很简单(正如git所建议的那样......):
git add FolderRenamed/File1.ext
或者,因为我想要恢复我重命名的文件夹中的所有文件,只需:
git add FolderRenamed
(如果我想删除文件夹及其内容,我会使用git rm ...)
Git非常强大:)。