【问题标题】:Git - Same file with different versions on two branches, when merge do not want to overwriteGit - 两个分支上具有不同版本的相同文件,合并时不想覆盖
【发布时间】:2015-02-24 08:59:25
【问题描述】:

我们有两个分支——'master'和'release'

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

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

【问题讨论】:

  • 可能已经回答here

标签: git branching-and-merging multiple-versions


【解决方案1】:

Pro Git 在8.2 Customizing Git — Git Attributes 的“Merge Strategies” 部分描述了如何获得这种效果。

合并策略

你也可以使用 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 上实现功能 B。

$ 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

尽量抑制你的兴奋。

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

$ git checkout release
Switched to branch 'release'

检查fileA 是否包含我们期望的内容。

$ cat fileA
release fileA

从master合并特征B。

$ 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 documentation 中的“Defining a custom merge driver” 部分解释。

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

合并驱动程序应将合并的结果留在 通过覆盖以%A命名的文件,如果它以零状态退出 设法干净地合并它们,或者如果存在冲突则非零。

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

【讨论】:

  • 感谢精彩的解释,这就是我一直在寻找的东西,你拯救了我的一天@GregBacon
  • @ChiragKhatri 不客气!我很高兴我的回答有所帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-24
  • 1970-01-01
  • 2017-12-31
  • 1970-01-01
  • 2019-08-04
  • 2010-11-20
相关资源
最近更新 更多