TL;DR: 你只需要使用git add
命令。
详细说明
当我尝试合并时,我会在所有已经被删除(在我的分支上)和重命名(在主分支上)的文件夹的所有文件上遇到冲突...
是的:当你运行例如:
git checkout branch
git merge master
Git:
- 识别您当前的提交(
HEAD
,也称为分支:通过哈希 ID 选择一个特定的提交,这是您目前在索引和工作树中拥有的提交),也称为本地或--ours
,但我只称其为L(左侧/本地);
- 识别另一个提交(也称为
master
),也称为远程、其他和--theirs
等多种方式,但我只称其为R(右侧/远程);
- 找到这两个提交之间的合并基础。那是最近的共同提交。我将此称为B。
(请注意,如果您检出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中所做的所有更改,以及他们在
R中自相同基础版本
B以来所做的所有更改。Git然后合并这些更改。
如果您重命名了一个文件,而他们删除了“相同”的文件(由重命名检测检测到),则会出现重命名/删除冲突。如果他们重命名了一个文件,而您将其删除,则会出现相同的冲突。无论哪种情况,Git都会发生冲突。
在冲突的特殊情况下(但不是在普通情况下),Git会在您的索引中保留每个文件的三个版本:
B中的版本,Git会将其作为“stage 1”保留在索引中;来自
L的版本,Git将其作为“stage 2”或
--ours
保留在索引中;和来自
R的版本,Git将其作为“stage 3”或
--theirs
保留在索引中。
这些较高编号的阶段文件是Git记住您处于冲突合并中的方式。通常,索引中的所有文件都在“stage zero”。如果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将阶段2版本复制到工作树中。运行
git checkout --theirs
告诉Git将阶段3版本复制到工作树中。在任何一种情况下,阶段1条目不会发生任何变化,阶段0条目保持为空。
运行
git add
告诉Git将文件从工作树复制到阶段0插槽中,
完全抹去其余插槽。文件现在已经解决。
由于Git将重命名的文件留在工作树中(以新名称),因此在这种情况下,您只需要
git add
重命名的文件即可。
当然,这不是唯一的方法
如果您运行
git checkout commit-specifier -- path
,Git会从给定的
commit-specifier
中提取给定的路径
path
。当Git这样做时,它将路径复制到索引的零号槽中。这将清除该路径的任何1-3号槽位条目,因此从特定提交中检出文件的副作用是解析该文件。
这与
git checkout --ours
和
--theirs
不同,因为它们从现有的索引条目中提取,所以它们不会写入零号槽。
因此,您还可以使用
git checkout MERGE_HEAD -- paths
将重命名的文件提取到其重命名名称中,在此过程中解决合并冲突。