为什么Git只将分支部分合并到master中?

时间:2020-10-01 01:38:32

标签: git

我最近将一个分支合并到master分支中。有一些冲突,但是我已经解决了,现在VS Code和GitHub Desktop都显示分支已完全合并。但是,并不是我在分支中所做的所有更改都反映在master分支中。

This因此,邮局建议您进行rebase,但是我收到一条消息,提示Current branch master is up to date.

关于我可以从这里去哪里的任何想法?

1 个答案:

答案 0 :(得分:0)

不存在部分合并这样的东西,尽管可以使用该短语来描述进行中不完整合并。但是在Git中,merging actually takes place in Git's index。在您(或Git)提交合并之前,它只是在进行中。当您(或Git)进行 merge commit 时,您已经完成了合并: merge commit ,这是具有两个或多个父级的提交。每个提交都会保存Git在进行提交的那个人知道的所有文件的快照。和合并提交没有什么不同。 git commit命令从Git索引中的文件构建新的提交。因此,一旦在Git的索引中全部设置了合并,您或Git就会运行git commit,Git将从Git的索引中的文件构建合并提交。这些就是合并提交中的内容,即快照。

但是,并不是我在分支中所做的所有更改都反映在master分支中。

也就是说,如果将master中较早的提交与合并提交中的快照进行比较,您将看不到想要看到的内容。这肯定是可能的:合并提交将包含您进行合并提交时位于Git索引中的文件,如果这些文件不是您想要包含的文件,则合并提交的快照不会是您想要的。

这是怎么回事的问题很重要且很有用(以避免以后再重复该问题),但是尽管有评论,但这不是您要问的:

关于我可以从这里去哪里的任何想法?

您有两个选择:

  1. 删除合并。这是可能的,但并不总是那么容易。如果您没有发送将合并提交提交到任何其他Git存储库,并不是很困难。如果有的话,那就很难了。

  2. 添加新的提交。这很简单!但是,想出您想要在其中添加哪些内容可能并不那么容易。

删除合并,您可以使用git rebase;变基通常会删除合并提交,您可以在此处使用它来取得良好的效果。 The question to which you linked很老,可以追溯到2011年初Git版本1.7.4的时候,但是仍然支持这些方法。但这使我们回到了删除您已提交给其他人的提交的一般问题:您必须说服所有的人(em)删除该提交。

要更正问题并添加新的提交,您需要提供新提交的内容。 的最简单方法可能只是重新执行合并,但这次正确。

您可以通过在要进行新合并的提交处创建新的分支名称来重新执行合并。这需要对Git提交图的工作原理有一点了解,但是假设您当前拥有以下知识:

...---J---M--N--O   <-- master
         /
...--K--L   <-- feature

这是将feature合并到master中,产生合并提交M,然后又向master中添加了多个提交(N和{ {1}}),此后,将基于错误的合并。让我们以不同的方式绘制以上内容,即表示同一张图:

O

现在,我们只需查找提交...-----J \ M--N--O <-- master / ...--K--L <-- feature 的哈希ID,然后创建一个指向该提交的新分支名称。让我们使用名称J。我们将运行:

redo

这给了我们这张图:

git checkout -b redo <hash-of-J>

我们现在可以运行...-----J <-- redo (HEAD) \ M--N--O <-- master / ...--K--L <-- feature ,或者,如果我们不再具有 name git merge feature来定位提交feature,我们可以找到其哈希ID和运行L

Git会磨掉一点并产生与上次相同的合并冲突。这次,当您解决合并冲突并提供一组文件供Git放入新提交时,请小心生成您确实想要的文件。这通常包括在它们上运行测试, 1 检查Git自己的合并结果,等等。尽量不要依赖git merge hashours标志:例如,theirs意味着放弃其更改,甚至git checkout --ours或{{ {} {1}}命令中的1}}不一定正确。

一旦您具有正确的合并,就可以运行-X ours-X theirs 2 进行新的合并提交:

git merge

例如,此时您可以运行git merge --continue,以查看 new 合并的外观。或者,git commit产生相同的差异,因为名称...-----J-----M2 <-- redo (HEAD) \ / M-/--N--O <-- master /_/ ...--K--L <-- feature 与特殊名称git diff hash-of-M HEAD指的是相同的提交(git diff hash-of-M redo)。

这时,您有多个选择,具体取决于提交redoM2是否实际存在。无论它们是否存在,一个可行的选择是在此处采用HEAD生成的差异,然后在分支N上实际应用该差异。当然,O会更改git diff hash-of-M HEAD所引用的提交,因此我们可以这样做:

master

(请注意,git checkout master选项允许HEAD使用三向合并,如果git checkout master git diff <hash-of-M> redo | git apply -3 -3与您将通过更新的git apply合并带来的更改)。

假设所有这些工作正常,您现在就可以NO结果了,产生:

M2

保留提交git add作为不正确合并的修复程序。

请注意,您可以代替以上的git commit,而只是合并提交...-----J-----M2 <-- redo \ / M-/--N--O--P <-- master (HEAD) /_/ ...--K--L <-- feature (通过P)。不幸的是,这种合并对于Git内部来说非常棘手,因为diff ... | apply -3M2的合并基础都是提交git checkout master; git merge redoO。递归策略是默认设置,它将合并这两个提交以生成虚拟合并库,并且特定的合并始终会产生您已经在此点上看到过两次的冲突。内部递归合并仅会提交冲突,从而保证与M2的进一步冲突。这会诱使人们使用J,但这是完全错误的,或者是要找到等效的L,但这也是错误的,因为它会撤消提交M2git merge -s ours

您可以使用git merge -s theirs中的N。这将选择Ogit merge -s resolve redo中的一个作为合并基础。但是,这仍然可能会产生一些合并冲突。这就是为什么我建议使用master方法的原因:合并冲突可能最少。不幸的是,如果您此时删除分支名称J,这将使存储库的将来用户有些神秘,因为他们没有重新合并的记录。

还有另一种解决方法,在完成Lgit diff ... | git apply -3之后使用redo代替git commit-tree。不过,我暂时将此选项留给其他人。


1 当运行测试的唯一方法是使用某些远程CI系统时,这可能会很困难!这是我不喜欢无法在本地测试的CI系统的原因之一。

2 运行git commit只是确保您要完成一个暂停的合并,然后运行git apply,所以这时它们将执行相同的操作。