我正在努力理解为什么会发生这种情况:
我已经从
master
分支了mybranch
,并进行了几个涉及文件A
、B
和C
的提交。同时,其他人向master
推送了一个提交,该提交删除了文件X
和Y
以及一些其他更改。当我将master
合并到mybranch
时,git status
告诉我X
"未合并",Y
"已删除"。为什么这些文件会有不同的处理
我相信这会减少我在现实生活中发生的事情http://github.com/borglab/SwiftFusion,
[编辑:我错了,所以上面的描述不准确。@torek下面的回答很好,很有启发性,所以我不会试图删除这个问题]
master
在标签conflict-merge-source
,mybranch
在标签conflict-merge-target
,但我会发布实际的回购,以防我错过了什么。这两个文件是Sources/SwiftFusion/Core/FixedShapeTensor.swift
(冲突)和Tests/SwiftFusionTests/Core/FixedShapeTensorTests.swift(已删除)。
TL;DR
正如您所指出的,这两个文件中的一个存在修改/删除冲突,而另一个根本没有冲突。两个文件中的一个没有冲突的原因是;侧面";合并的一方根本没有接触到文件,但另一方接触到了。
对于有冲突的文件,Git会将修改后的文件留在您的工作树中,并将冲突留在Git的索引中,您必须在索引中解决它;保持删除";您可以在该名称上使用git rm
,如果要保留修改后的文件,则可以使用git add
。无论哪种方式,Git的索引——建议的next提交——现在都被更新了,并且这个特定的冲突得到了解决。
Long
我克隆了有问题的存储库,发现了以下内容:
$ git merge-base --all conflict-merge-source conflict-merge-target
a07af749bdd416c5217c363b3f1da509c58d2d14
$ base=$(git merge-base --all conflict-merge-source conflict-merge-target)
$ git diff --find-renames --name-status $base conflict-merge-source
M Sources/BeeDataset/BeeFrames.swift
M Sources/SwiftFusion/Core/DataTypes.swift
D Sources/SwiftFusion/Core/FixedShapeTensor.swift
M Sources/SwiftFusion/Core/MathUtil.swift
A Sources/SwiftFusion/Core/TensorVector.swift
M Sources/SwiftFusion/Image/OrientedBoundingBox.swift
A Sources/SwiftFusion/Inference/AppearanceTrackingFactor.swift
M Sources/SwiftFusion/Inference/FactorGraph.swift
M Sources/SwiftFusion/Inference/FactorsStorage.swift
M Sources/SwiftFusion/Inference/JacobianFactor.swift
A Sources/SwiftFusion/Inference/PPCA.swift
M Sources/SwiftFusion/Inference/PPCATrackingFactor.swift
M Sources/SwiftFusion/Optimizers/CGLS.swift
M Sources/SwiftFusion/Optimizers/LM.swift
M Sources/SwiftFusionBenchmarks/Patch.swift
M Tests/BeeDatasetTests/BeeDatasetTests.swift
A Tests/BeeDatasetTests/BeePPCATests.swift
D Tests/SwiftFusionTests/Core/FixedShapeTensorTests.swift
M Tests/SwiftFusionTests/Image/PatchTests.swift
M Tests/SwiftFusionTests/Inference/FactorGraphTests.swift
R062 Tests/SwiftFusionTests/Inference/PPCATrackingFactorTests.swift
Tests/SwiftFusionTests/Inference/PPCATests.swift
M Tests/SwiftFusionTests/Inference/SwitchingMCMCTests.swift
M Tests/SwiftFusionTests/Optimizers/LMTests.swift
$ git diff --find-renames --name-status $base conflict-merge-target
M Sources/SwiftFusion/Core/FixedShapeTensor.swift
M Sources/SwiftFusion/Inference/AnyArrayBuffer+Differentiable.swift
R050 Sources/SwiftFusion/Inference/ValuesStorage.swift
Sources/SwiftFusion/Inference/AnyArrayBuffer+Vector.swift
M Sources/SwiftFusion/Inference/ArrayBuffer+Differentiable.swift
M Sources/SwiftFusion/Inference/ArrayBuffer+Vector.swift
M Sources/SwiftFusion/Inference/PenguinExtensions.swift
M Tests/SwiftFusionTests/Inference/AnyArrayBufferTests.swift
请注意R062
和R050
行:Git已经检测到,自从合并基提交$base
(a07af749...
)以来,这些文件在两个选定的提交中被重命名。这在这里并没有那么重要,但他们排起了长队,我把他们分开发布。
我不完全确定您已将两个提交中的哪一个签出为分支,以及使用git merge
命令选择了哪一个,但由于合并过程大多是对称的,因此1并不重要。
我们可以用分离的HEAD进行合并,但我喜欢有一个分支名称,所以我现在创建了一个:
$ git checkout -b t1 conflict-merge-source
Switched to a new branch 't1'
$ git merge conflict-merge-target
CONFLICT (modify/delete): Sources/SwiftFusion/Core/FixedShapeTensor.swift
deleted in HEAD and modified in conflict-merge-target. Version
conflict-merge-target of Sources/SwiftFusion/Core/FixedShapeTensor.swift
left in tree.
Automatic merge failed; fix conflicts and then commit the result.
(同样,为了张贴,我排起了长队。)
1任何不对称都是将一个提交视为"提交"的结果;我们的";另一个作为";他们的";。例如,-X
扩展选项本身必须选择一个我们的与他们的,而重命名/重命名冲突(如果有)必须选择要进行的重命名(如果有的话)。这些平局决胜局引入了不对称性。
git merge
如何合并更改
在git merge
的所有情况下,Git将合并基(我们在上面发现)与要合并的每个提交进行比较。这使得这两个快照中的每一个都变成了变化——从一个共同的起点开始。我们可以使用git diff
(参见上面的示例)来找出哪些文件包含哪些类型的更改。
发现这些更改后,合并代码的工作现在是合并这些更改。对";侧面";在合并的另一个上使没有改变的情况下;"侧";,就是全盘接受零钱。这些文件中的大多数都是这种情况——例如,所有22个M
文件。因此,在这种情况下,git merge
可以从更改文件的任何一侧获取文件的副本。合并的这一部分很容易:有时,合并必须从合并基本提交的文件的基本版本开始,并将双方的更改添加到其中。
但我们列出了其他八个状态文件(不是M
),其中7个在一侧,1个在另一侧:
从底部到一侧有四个
A
文件(新文件)。这些文件在另一个文件上没有相同的命名操作,所以合并操作只是将这些新文件作为新文件。有两个
R
文件。它们位于另一方没有接触的不同文件上,因此Git只保留重命名后的副本:我们只获得新名称(如果内容也发生了更改,则会有新内容);合并基提交中原始文件的原始副本将被完全删除。(如果合并更加困难,情况可能并非如此。)有两个
D
文件,仅在一侧。这些是:D Sources/SwiftFusion/Core/FixedShapeTensor.swift D Tests/SwiftFusionTests/Core/FixedShapeTensorTests.swift
(和你提到的一样)。以下是我们在另一个侧看到的内容,用于这两个文件:
M Sources/SwiftFusion/Core/FixedShapeTensor.swift
也就是说,第二个文件根本没有出现:它没有被触摸。
应该如何Git组合"删除";用";未被触及";?Git的回答是";保持删除";。应该如何Git组合"删除";用";修改的";?Git的答案是将修改后的文件保留在工作树中,并在索引中将该文件标记为冲突。这并不总是正确的答案,但如果不是,您可以手动调整索引内容,例如,从HEAD
或MERGE_HEAD
恢复已删除的文件。
最终的合并提交一旦完成,将包含Git复制到Git索引中的任何文件。文件的工作树副本对Git来说并不重要;他们就在那里,这样你就可以和他们一起工作了。每个文件的索引副本都是Git自己的内部压缩和消除重复的形式