为啥合并后GIT会说“已经是最新的”,但分支之间的差异仍然存在?
Posted
技术标签:
【中文标题】为啥合并后GIT会说“已经是最新的”,但分支之间的差异仍然存在?【英文标题】:Why after merge does GIT say "Already up-to-date", but differences between branches still exist?为什么合并后GIT会说“已经是最新的”,但分支之间的差异仍然存在? 【发布时间】:2013-03-22 02:54:44 【问题描述】:我最初在“newfeature”分支工作,我被要求紧急修复实时分支上的错误。我为名为“generalmaintenance”的分支创建了一个分支,完成了这项工作,然后切换到开发并将其合并。我现在想返回“newfeature”分支并合并我之前合并到其中的更改。
当我切换到'newfeature'并合并到'develop'时,有3个文件发生冲突。
我陷入了解决冲突的纠结中,最终决定使用 Aptana Studio 3(这是我的 IDE)的“团队”菜单中的“恢复”命令。我希望这会让我回到合并之前,它似乎已经完成了。
无论如何,当我再次合并'develop'时,它会显示Already-up-to-date
,但是在比较两个分支之间的文件时,它们非常不同,并且我在另一个分支中添加的更改没有被合并。
请问我现在如何合并这两个分支?
【问题讨论】:
【参考方案1】:恢复合并与重置合并
我猜你实际上是是Already-up-to-date
。
问题在于git revert 不会撤消合并,它只会撤消合并带来的更改。创建合并提交时,您将合并这两个分支的提交历史记录。
合并
develop
|
A---B---C
\ \
E---F---M
|
newfeature
在上面的例子中,develop
被合并到newfeature
,创建了M
提交。如果您要运行git log newfeature
,您会看到来自两个分支的所有提交,但是从newfeature
分支的角度来看,所有这些更改都是由M
提交执行的。
还原
git revert
命令不会删除任何提交,而是创建一个新的提交来撤消提交所包含的更改。例如,如果您有一个包含此差异的提交...
-This is the old sentence.
+This is the new sentence.
然后将其还原,revert 命令将创建一个新的提交,该提交刚刚执行了相反的差异,它只是翻转了符号。
-This is the new sentence.
+This is the old sentence.
这对于撤消其他开发人员已经拥有的提交造成的损害非常有用。它推动历史前进,而不是改变历史。
还原合并
但是,在非快进合并的上下文中,它可能会产生不良影响。
develop
|
A---B---C
\ \
E---F---M---W
|
newfeature
假设 W 是一个反向提交,你可以看到运行 git log newfeature
仍然会包含来自开发分支的所有提交。因此,来自develop
的其他合并将不起作用,因为它没有看到您的分支中缺少任何内容。
使用git reset 而不是revert。
将来,如果合并尚未与其他开发人员共享,您可能会考虑使用git reset --hard <ref>
(其中<ref>
是合并的提交哈希)撤消合并。在上面的示例中,在创建合并提交 M
后,运行命令 git reset --hard F
将导致以下结果。
develop
|
A---B---C
\ \
E---F---M
|
newfeature
正如您所见,这种技术并没有像某些人认为的那样消除提交,它只是将您的分支移回您选择的提交。现在如果你运行git log newfeature
,你只会得到提交F
、E
和A
。现在合并实际上已从您的分支历史记录中消失,因此稍后尝试在 develop
中重新合并不会导致任何问题。
这种方法并非没有复杂性。意识到您现在正在修改历史记录,因此如果在进行 M
合并之后将 newfeature
分支推送到远程分支,那么 git 会认为您只是过时并告诉您需要运行git pull
。如果只是你在那个远程分支上工作,那么请随时 force-push
- git push -f <remote> <branch>
。这将具有与重置相同的效果,但在远程分支上。
如果这个分支正在被多个开发人员使用,而他们现在已经从中撤出 - 那么这是一个坏主意。这正是git revert
有用的原因,因为它在不更改实际历史记录的情况下撤消更改。
对历史记录使用重置实际上仅适用于尚未共享的提交。
解决方案 - 还原还原。
如果合并提交已经被共享,那么最好的方法可能是在该合并上使用git revert
。但是,正如我们之前所说,您不能简单地将分支合并回来并期望该分支的所有更改重新出现。答案是还原还原提交。
假设您在尊重 newfeature
中的合并之后在 develop
分支上做了一些工作。您的历史记录将如下所示。
develop
|
A---B---C---D
\ \
E---F---M---W
|
newfeature
如果你现在将develop
合并到newfeature
中,你只会得到D
,因为它是唯一一个不属于newfeature
分支历史的提交。你还需要做的是恢复W
commit - git revert W
应该做的伎俩,然后是git merge develop
。
develop
|
A---B---C-----------D
\ \ \
E---F---M---W---M---G
|
newfeature
这将恢复原始合并提交所做的所有更改 - 实际上是由 C
和 B
进行但在 W
中恢复的,然后通过新的合并提交 G
引入 D
我建议在合并最近对develop
的更改之前 还原revert,我怀疑按此顺序执行此操作会降低触发冲突的可能性。
TL;DR
还原会创建一个“还原提交”。撤消还原时,您需要对第一次还原时创建的还原提交运行还原命令。它应该很容易找到,git 倾向于自动评论恢复,以便它们以“Reverted”一词开头。
git revert <commit>
【讨论】:
非常感谢 Eddie 对此的详细解释 (+1)。将再次研究它以消化它并在接受您的答案之前尝试您的解决方案。我“非常有信心”这将是解决方案。 仅供参考:我进行了一些次要但重要的编辑以纠正一些事情。最重要的是,我更正了关于恢复合并提交的示例。它是git revert M
,我将其更正为git revert W
。此外,第二个差异是错误的。解释还原提交的那个。修正了 +/- 符号。
吸取了我们的教训 - 如果从生成恢复的 PR 的同一分支合并,请仔细 git diff 和审查提交!
我遇到了一个问题。我合并的分支没有任何新的提交。并且还原还原提交不会让我将开发分支合并到新功能分支并说“已经是最新的”。请帮忙。
@AstitvaSrivastava 你合并的分支没有新的提交,但你还需要合并吗?我对这些说法感到困惑。如果没有新的提交,那么就没有什么可以合并的了。但是,您所说的方式给了我一个可能的线索来解决您的问题。 “合并发展成为新功能”。您可能以错误的方式合并它们。如果 newfeature 是基于 develop 的,并且 develop 没有变化,那么 newfeature 并没有什么新的东西。尝试将新功能合并到开发中-如果您需要的话。我不能确定。【参考方案2】:
找到了一个 hacky 解决方案。但它有效。
eddiemoya 回答的任何内容都是完全有帮助的。非常感谢您的解释。我遇到了类似的情况。在哪里,我可以在 git diff <branch>
中看到很多内容,但 git merge 说已经是最新的了。
由于日志中有很多还原,我无法找到确切的还原提交。 (是的,坏事。一开始就不应该发生)
解决方案
git checkout branchX -- .
这会将所有从 branchX 的更改暂存到我当前的分支。 使用您最喜欢的 git 客户端,取消暂存和还原任何不打算使用的内容。
做一个新的提交并开心:)
【讨论】:
【参考方案3】:我也遇到过同样的情况。我所做的是我刚刚创建了一个新分支,并从不同的提交中挑选了所有需要的文件,然后合并了这个分支。
动作如下所示:
创建了一个新分支 使用git cherry-pick -n xxxxxxx
从不同的提交中获取所需的文件
然后提交这些文件git commit -m 'Your commit message'
然后将这个樱桃采摘的分支合并到所需的分支中
【讨论】:
以上是关于为啥合并后GIT会说“已经是最新的”,但分支之间的差异仍然存在?的主要内容,如果未能解决你的问题,请参考以下文章