【问题标题】:Dealing with conflicts when merging from development to master从开发合并到主控时处理冲突
【发布时间】:2013-10-22 11:03:06
【问题描述】:

我开始了一个工作流程,我的目标是在 development 分支中完成所有新功能,而 master 分支将仅用于生产就绪代码。

执行以下操作后:

git checkout master
git merge staging

我收到了一堆这样的冲突:

CONFLICT (rename/add): Rename app/assets/stylesheets/mobile.css->app/assets/stylesheets/application.css in HEAD. app/...
CONFLICT (modify/delete): app/views/organizers/mobile.html.erb deleted in HEAD and modified in staging. Version stagi...
CONFLICT (modify/delete): app/views/events/mobile.html.erb deleted in HEAD and modified in staging. Version staging of app/v...

当我现在一直在谷歌上搜索时,我所读到的只是审查每个文件、解决冲突并提交更改。但是我看不出做这一切有什么意义,因为我知道代码而且它只是对同一代码集的改进。

如何以简单的方式将staging 中所做的更改合并到master 中,而无需审查和解决每一项更改?

【问题讨论】:

  • 在创建暂存分支后对 master 进行了更改?你看过变基吗?
  • 当我尝试变基时,也会出现很多冲突......
  • 如果您向我们展示您最近的历史,将会很有帮助。否则,就没有办法回答这个问题了。
  • 确实这是一个非常常见的用例。
  • 有一个非常相似的问题。樱桃采摘对我帮助很大

标签: git merge conflict git-merge merge-conflict-resolution


【解决方案1】:

这是一个复杂的问题,因为它基本上意味着git 无法直观地弄清楚如何组合这两个分支。似乎在master 上删除了一些文件,然后在staging 中修改(并因此被使用),而另一个在master 中重命名但添加到staging。以下内容主要是在黑暗中拍摄,您可能仍需要手动解决一些(但希望更少)冲突。

git 可以选择多种不同的合并算法,因此我们将使用最简单、易于自定义且通常默认使用的一种:递归策略。我们将通过选项-s recursive 强制使用它。

帮助git 的第一步是让它花更多时间完善补丁,所以我们将使用选项-Xdiff-algorithm=histogram。这将花费最长的时间,但会迫使 git-merge 产生更好的差异输出(这有望减少冲突)。

下一步是告诉git-merge 花更多时间进行正确的合并。我们将使用 -Xpatience 选项来执行此操作。

由于master 将依赖于重命名/修改后的文件,而staging 将依赖于旧文件,我们可以尝试欺骗git,使其认为该文件并未真正使用选项@987654336 重命名@(因此文件必须相同才能被视为重命名)。请注意,您可能会留下一些多余的文件,并且需要注意其他文件名的文件的任何更改都不会记录旧名称(仅记录新名称),因此您可能希望返回并修复那些一旦你'已完成合并。您还可以将 100% 调整为更小的值(默认为 50%,这目前会导致问题)。

现在要包含staging 所需的文件,我们可以使用以下选项强制添加它们:-Xtheirs警告:此选项将默认忽略所有合并冲突,并默认使用staging 的内容。确保运行完整的测试套件以检查是否存在任何不一致。如果您在合并后确实在测试套件中遇到问题,请使用 git reset --hard HEAD^ 撤消它并在不使用此选项的情况下重新进行合并。您可能会有少量必须手动解决的合并冲突,但您会知道错误的根源来自其中一个(无限多)冲突,这与之前的猜测相比是一个巨大的飞跃一个调试器。

最后,我们把它们放在一起得到

git checkout master
git merge staging -s recursive -Xdiff-algorithm=histogram -Xpatience -Xrename-threshold=100% -Xtheirs

最后,我建议您尝试使用这些选项。在合并上花费的额外时间可能会使最后两个选项无用(甚至更糟)。

以后,我建议您定期将master 中的任何更改拉到您的主题分支中。这不仅会更早地呈现冲突(因此一次出现的冲突更少),而且还会让您及时了解最新情况,甚至可以在冲突发生之前解决冲突。这很好的另一个原因是git 有一个名为git-rerere 的功能,它记录您手动解决的冲突,然后学习稍后如何为您自动解决这些相同的冲突。因此,一旦您解决了一次,您就不必再次解决相同/相似的冲突。

【讨论】:

  • 感谢您提供最全面的答案。对于我的情况,我最终决定删除其中一个分支而不是合并。
【解决方案2】:

使用git merge 选项,称为“策略”-s ours(或他们的)。这意味着 git 将更喜欢来自开发分支(或来自 master)的更改。这意味着,如果您在 master 和 staging 中对一个代码字符串进行了不同的更改,那么它将进行 staging 更改。 另外,我建议您使用 --no-commit 选项,这样您就可以在提交合并之前检查一次代码(不是每次更改)。

【讨论】:

  • 仍然产生冲突。
【解决方案3】:

我使用下一个策略。 首先,从开发分支结帐到其他分支:

  git checkout -b feature/resolve-conflicts

下一步,您必须将代码从 master 拉到功能分支:

  git pull origin master

接下来解决冲突并将功能分支推送到 git:

  git add --all
  git commit -am 'resolve conflicts'
  git push -u origin feature/resolve-conflicts

然后创建拉取请求并将功能/解决冲突与主分支进行比较。在不同的平台上,它以不同的方式制作。将功能分支合并到主分支后,创建新的拉取请求,将开发分支合并到主分支。

现在,develop 中的更改通常必须通过提交合并到 master 分支中。

它对我有用,希望我能帮上忙。

【讨论】:

  • 请注意,您最终会在您的主分支中进行额外的合并,而该合并不在您的开发分支中。在大多数情况下,这可能不是问题,但确实会导致 master 和 development 之间存在一些分歧,最终可能导致问题发生。
  • 是的,我同意你的看法。它在许多情况下都有效,但根本不起作用。在复杂的项目中,您应该在做某事之前考虑一下。 @majorobot 实际上是对的。请记住这种情况。
【解决方案4】:

这是一个非常常见的问题,并且有一个简单的解决方案。一旦发生合并冲突,您可以通过

在文件到文件的基础上执行此操作
Keep master's file
git checkout --ours myfile.html

Keep development's file
git checkout --theirs myfile.html

你可以很容易地将它应用到整个文件夹

git checkout --ours ./
git checkout --theirs ./

这比git merge 更好,因为您也可以看到冲突的文件。 更多详情在这里https://www.kernel.org/pub/software/scm/git/docs/git-checkout.html

【讨论】:

  • 结帐到“.”如果某些文件是新的/删除的,则会失败。真的很烦人的错误恕我直言。
  • @AlexR 也许你可以先git stash它?
  • 如果您有 1000 个文件,并且您确信当前的“开发”分支状态完全符合您的要求,该怎么办。有没有一种简单的方法可以将最新的开发提交“复制”到 master 中?>
  • @rolls 我和你的情况一样(我知道开发分支中的更改是我想要保留的一次),你有没有找到一种方法将开发“复制”到没有冲突的主人?
  • 我想我使用了内存中的变基
猜你喜欢
  • 2017-10-27
  • 1970-01-01
  • 1970-01-01
  • 2012-05-09
  • 2023-03-25
  • 1970-01-01
  • 2012-12-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多