如何通过保留双方的所有添加来解决 git 冲突?

out*_*ave 6 git git-merge git-rebase merge-conflict-resolution git-merge-conflict

我一直遇到以下问题,我想知道是否有使用现有 git 命令的简单解决方案,或者我是否需要编写自定义合并驱动程序

这是一个演示我的问题的示例:假设master我的 repo的分支具有以下文件:

$ cat animal.hpp 
#include <string>

class Animal
{
public:
  virtual std::string say() const = 0;
};
Run Code Online (Sandbox Code Playgroud)

我创建一个名为的新分支mybranch并进行以下更改:

diff --git a/animal.hpp b/animal.hpp
index e27c4bf..3bb691a 100644
--- a/animal.hpp
+++ b/animal.hpp
@@ -5,3 +5,13 @@ class Animal
 public:
   virtual std::string say() const = 0;
 };
+
+class Dog : public Animal
+{
+public:
+  virtual std::string
+  say() const override
+  {
+    return "woof";
+  }
+};
Run Code Online (Sandbox Code Playgroud)

与此同时,其他人添加了以下非常相似的更改master

diff --git a/animal.hpp b/animal.hpp
index e27c4bf..310d5a7 100644
--- a/animal.hpp
+++ b/animal.hpp
@@ -5,3 +5,13 @@ class Animal
 public:
   virtual std::string say() const = 0;
 };
+
+class Cat : public Animal
+{
+public:
+  virtual std::string
+  say() const override
+  {
+    return "meow";
+  }
+};
Run Code Online (Sandbox Code Playgroud)

现在,当我尝试mybranchmaster(或变基mybranchmaster)合并时,我遇到了冲突:

$ cat animal.hpp 
#include <string>

class Animal
{
public:
  virtual std::string say() const = 0;
};

<<<<<<< HEAD
class Dog : public Animal
=======
class Cat : public Animal
>>>>>>> master
{
public:
  virtual std::string
  say() const override
  {
<<<<<<< HEAD
    return "woof";
=======
    return "meow";
>>>>>>> master
  }
};
Run Code Online (Sandbox Code Playgroud)

解决此冲突的正确方法是:

$ cat animal.hpp 
#include <string>

class Animal
{
public:
  virtual std::string say() const = 0;
};

class Dog : public Animal
{
public:
  virtual std::string
  say() const override
  {
    return "woof";
  }
};

class Cat : public Animal
{
public:
  virtual std::string
  say() const override
  {
    return "meow";
  }
};
Run Code Online (Sandbox Code Playgroud)

我通过手动编辑文件、复制两个类共有的代码并删除冲突标记来创建上述解决方案。但我认为 git 应该能够自动创建此分辨率,因为它只需要添加一个分支中添加的所有行,然后添加另一个分支中添加的所有行,而无需对公共行进行重复数据删除。我怎样才能让 git 为我做这件事?

(允许我自定义订单的解决方案的奖励积分 -Dog首先或Cat首先。)

tor*_*rek 8

一种叫做联合合并的东西:

$ printf 'animal.hpp\tmerge=union\n' > .gitattributes
$ git merge --no-commit mybranch
Auto-merging animal.hpp
Automatic merge went well; stopped before committing as requested
Run Code Online (Sandbox Code Playgroud)

在这种特殊情况下,它实际上达到了预期的结果。然而,在许多情况下,它可能会严重失火,并且永远不会失败(我的意思是它永远不会认为自己失败,即使它产生了无意义的结果),所以毕竟设置它并不是明智的.gitattributes(除非你有一个非常罕见的案例)。

相反,最好在事后调用它,使用git merge-file

$ git merge --abort
$ rm .gitattributes
$ git merge mybranch
Auto-merging animal.hpp
CONFLICT (content): Merge conflict in animal.hpp
Automatic merge failed; fix conflicts and then commit the result.
$ git show :1:animal.hpp > animal.hpp.base
$ git show :2:animal.hpp > animal.hpp.ours
$ git show :3:animal.hpp > animal.hpp.theirs
$ mv animal.hpp.ours animal.hpp
$ git merge-file --union animal.hpp animal.hpp.base animal.hpp.theirs
Run Code Online (Sandbox Code Playgroud)

确保结果是您想要的,然后进行一些清理并添加最终的合并版本:

$ rm animal.hpp.base animal.hpp.theirs
$ git add animal.hpp 
Run Code Online (Sandbox Code Playgroud)

现在您已准备好提交结果。 编辑:这是我得到的结果(在两种情况下):

$ cat animal.hpp 
#include <string>

class Animal
{
public:
  virtual std::string say() const = 0;
};

class Cat : public Animal
{
public:
  virtual std::string
  say() const override
  {
    return "meow";
  }
};

class Dog : public Animal
{
public:
  virtual std::string
  say() const override
  {
    return "woof";
  }
};
Run Code Online (Sandbox Code Playgroud)


Mak*_*oto 5

Git无法在典型工作流程中为您处理这种合并。这就是为什么它要求你干预。它非常非常努力地不丢失任何一方的更改,但它并不真正知道您想要如何解决它或如何修复它。

您应该研究一个合并工具来帮助您解决此问题。或者,您可以手动执行此操作并删除 Git 合并冲突行,然后自行处理这两个文件的合并。