Git - 当合并不想覆盖时,在两个分支上具有不同版本的相同文件

时间:2015-02-24 08:59:25

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

我们有两个分支 - “主人”和“释放”

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

但每次,我们必须将'release'合并为'master',我们如何实现,'master'中的fileA不会被分支'release'中的fileA覆盖

2 个答案:

答案 0 :(得分:3)

Pro Git介绍了如何在“Merge Strategies”8.2 Customizing Git — Git Attributes部分中获得此效果。

  

合并策略

     

您还可以使用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

如何运作

“Defining a custom merge driver”中的gitattributes documentation部分解释了这一点。

  

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

     

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

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

答案 1 :(得分:0)

如果要将发布分支合并到主服务器中,请在主服务器上首先使用rebase release分支。

这样你的历史就会有一个“干净”的历史。你将避免在树的所有地方分支,并得到一个简洁的提交行。

Rebase会将所有“新”内容带入您的主分支。 如果更改有冲突,那么您可以忽略文件的“发布”版本(但要注意,如果您的其他文件需要更改),那么合并将是而不会发生冲突。

git checkout release
git rebase master
// deal with conflicts during rebase
git checkout -b release.tomerge
git checkout master
git merge release.tomerge