Git - 两个分支上不同版本的相同文件,合并时不想覆盖
Git - Same file with different versions on two branches, when merge do not want to overwrite
我们有两个分支 -- 'master' 和 'release'
我们有一个文件,比如fileA
,我们想在这两个分支上保持不同的版本。
但是每次都要将'release'合并到'master',如何实现'master'中的fileA
不会被[=覆盖11=] 在分支 'release'.
Pro Git describes how to get this effect in the “Merge Strategies” section of 8.2 Customizing Git — Git Attributes.
Merge Strategies
You can also use Git attributes to tell Git to use
different merge strategies for specific files in your project. One
very useful option is to tell Git to not try to merge specific files
when they have conflicts, but rather to use your side of the merge
over someone else’s.
This is helpful if a branch in your project has diverged or is
specialized, but you want to be able to merge changes back in from it,
and you want to ignore certain files. Say you have a database settings
file called database.xml
that is different in two branches, and you
want to merge in your other branch without messing up the database
file. You can set up an attribute like this:
database.xml merge=ours
And then define a dummy ours
merge strategy with:
$ git config --global merge.ours.driver true
If you merge in the other branch, instead of having merge conflicts
with the database.xml
file, you see something like this:
$ git merge topic
Auto-merging database.xml
Merge made by recursive.
In this case, database.xml
stays at whatever version you originally
had.
将其应用到您的情况,首先创建 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” in the gitattributes documentation 部分解释。
The merge.*.driver
variable’s value is used to construct a command to
run to merge ancestor’s version (%O
), current version (%A
) and the
other branches' version (%B
). These three tokens are replaced with the
names of temporary files that hold the contents of these versions when
the command line is built …
The merge driver is expected to leave the result of the merge in the
file named with %A
by overwriting it, and exit with zero status if it
managed to merge them cleanly, or non-zero if there were conflicts.
自定义 ours
驱动程序使用了几乎 none 的这台机器,只有 true
command 以零状态退出。这达到了预期的效果,因为它从我们当前所在的任何分支的 fileA
开始——这是我们想要的结果——然后在合并覆盖阶段什么都不做(即, 忽略由 %B
) 命名的另一个分支的版本,最后告诉 git 一切都很好,退出状态成功。
我们有两个分支 -- 'master' 和 'release'
我们有一个文件,比如fileA
,我们想在这两个分支上保持不同的版本。
但是每次都要将'release'合并到'master',如何实现'master'中的fileA
不会被[=覆盖11=] 在分支 'release'.
Pro Git describes how to get this effect in the “Merge Strategies” section of 8.2 Customizing Git — Git Attributes.
Merge Strategies
You can also use Git attributes to tell Git to use different merge strategies for specific files in your project. One very useful option is to tell Git to not try to merge specific files when they have conflicts, but rather to use your side of the merge over someone else’s.
This is helpful if a branch in your project has diverged or is specialized, but you want to be able to merge changes back in from it, and you want to ignore certain files. Say you have a database settings file called
database.xml
that is different in two branches, and you want to merge in your other branch without messing up the database file. You can set up an attribute like this:database.xml merge=ours
And then define a dummy
ours
merge strategy with:$ git config --global merge.ours.driver true
If you merge in the other branch, instead of having merge conflicts with the
database.xml
file, you see something like this:$ git merge topic Auto-merging database.xml Merge made by recursive.
In this case,
database.xml
stays at whatever version you originally had.
将其应用到您的情况,首先创建 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
尽量克制自己的兴奋。
这是我们特殊的合并驱动程序发挥作用的地方。我们的主人公想要将 master
中的新代码合并到 release
中。首先切换分支。
$ git checkout release
Switched to branch 'release'
健全性检查 fileA
包含我们期望的内容。
$ cat fileA
release fileA
从 master
.
$ 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” in the gitattributes documentation 部分解释。
The
merge.*.driver
variable’s value is used to construct a command to run to merge ancestor’s version (%O
), current version (%A
) and the other branches' version (%B
). These three tokens are replaced with the names of temporary files that hold the contents of these versions when the command line is built …The merge driver is expected to leave the result of the merge in the file named with
%A
by overwriting it, and exit with zero status if it managed to merge them cleanly, or non-zero if there were conflicts.
自定义 ours
驱动程序使用了几乎 none 的这台机器,只有 true
command 以零状态退出。这达到了预期的效果,因为它从我们当前所在的任何分支的 fileA
开始——这是我们想要的结果——然后在合并覆盖阶段什么都不做(即, 忽略由 %B
) 命名的另一个分支的版本,最后告诉 git 一切都很好,退出状态成功。