25

我们有两个分支——“master”和“release”

我们有一个文件,例如fileA,我们想在这两个分支上保留不同的版本。

但是每次都要把'release'合并到'master'中,如何才能实现,fileAin'master'不会被fileAin分支'release'覆盖。

4

1 回答 1

17

Pro Git在8.2 自定义 Git - Git 属性的“合并策略”</a>部分中描述了如何获得这种效果。

合并策略

您还可以使用 Git 属性来告诉 Git 对项目中的特定文件使用不同的合并策略。一个非常有用的选项是告诉 Git 在发生冲突时不要尝试合并特定文件,而是使用您的合并方而不是其他人的合并方。

如果您的项目中的某个分支出现分歧或专门化,但您希望能够从其中合并更改,并且您希望忽略某些文件,这将很有帮助。假设您有一个名为database.xml在两个分支中不同的数据库设置文件,并且您希望在不弄乱数据库文件的情况下合并到另一个分支中。您可以像这样设置属性:

database.xml merge=ours

然后定义一个虚拟ours合并策略:

$ git config --global merge.ours.driver true

如果您在另一个分支中合并,而不是与database.xml文件发生合并冲突,您会看到如下内容:

$ git merge topic
Auto-merging database.xml
Merge made by recursive.

在这种情况下,database.xml保持在您最初拥有的任何版本。

将其应用于您的情况,首先创建fileA

$ echo 'master fileA' > fileA
$ git add fileA ; git commit -m "master fileA"
[master (root-commit) fba9f1a] master fileA
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 fileA

并让它变得特别。

$ echo fileA merge=ours > .gitattributes
$ git add .gitattributes ; git commit -m 'fileA merge=ours'
[master 98e056f] fileA merge=ours
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 .gitattributes
$ git config --global merge.ours.driver true

现在我们创建一个代表release分支。

$ git checkout -b release
Switched to a new branch 'release'
$ echo 'release fileA' > fileA
$ git add fileA ; git commit -m 'release fileA'
[release 53f3564] release fileA
 1 files changed, 1 insertions(+), 1 deletions(-)

还没有发生什么特别的事情:版本控制只是按其应有的方式工作。

现在,我们master.

$ git checkout master
Switched to branch 'master'
$ touch featureB ; echo 'With Feature B' >> fileA
$ git add featureB fileA ; git commit -m 'Feature B'
[master 443030f] Feature B
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 featureB

试着控制你的兴奋。

这是我们特殊的合并驱动程序发挥作用的地方。我们的英雄想要将新代码从合并masterrelease. 首先切换分支。

$ git checkout release
Switched to branch 'release'

fileA包含我们期望的健全性检查。

$ cat fileA
release fileA

从合并特征masterB。

$ git merge master
Auto-merging fileA
Merge made by recursive.
 0 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 featureB

这条线Auto-merging fileA是一个线索,表明发生了一些特别的事情。的确:

$ cat fileA
release fileA

这个怎么运作

gitattributes文档中的“定义自定义合并驱动程序”部分</a>进行了解释。

merge.*.driver变量的值用于构造一个命令以运行以合并祖先的版本 ( %O)、当前版本 ( %A) 和其他分支的版本 ( %B)。在构建命令行时,这三个标记被替换为保存这些版本内容的临时文件的名称……</p>

合并驱动程序应通过覆盖将合并结果保留在名为 with 的文件中%A,如果成功合并它们,则以零状态退出,如果存在冲突,则以非零状态退出。

自定义ours驱动程序几乎不使用这种机制,只使用以零状态退出的true命令。这达到了预期的效果,因为它fileA从我们当前所在的任何一个分支开始——这是我们想要的结果——然后在合并覆盖阶段什么都不做(忽略另一个分支的版本%B),最后告诉 git一切顺利,退出状态成功。

于 2017-12-22T19:16:08.880 回答