问题描述
这个问题遵循。我试图了解 merge
做的过程,以避免发生不必要的错误。
我有两个分支:主
, b
。我看到了做一个奇怪的结果 git merge
。您可以在合并之前看到输出git log ,在这里:
* 148c970(HEAD,master)将master中的1重命名为1_master
| * ad18d9b(b)将b中的1重命名为1_b
| /
* 15cd89b在主
中添加1
因此,我在 master
和 b中有一个名为 1
的文件
。然后在 master
中将其重命名为 1_master
,并将其重命名为 1_b
in b
。然后我做了 git merge
:
git merge b
我猜这会导致冲突,因为合并基数必须是 15cd89b
并且两个分支都对 1
进行了更改,它们不匹配。 但是合并不会导致任何错误冲突
,合并后我看到 1_b
和 1_master
in工作目录。
注意:
我认为和在上述情况下的链接回复预测冲突。如果我试图重现你的问题,我会得到一个重命名/重命名冲突,正如我所期望的那样。首先,我创建了一个存储库和一些文件(包含独特的内容):
$ mkdir rename -ex
$ cd rename-exp /
$ git init
在/home/torek/tmp/rename-exp/.git/
$ cat>中初始化的空Git存储库。 1
这是初始状态下的文件1。
使用
文件测试
发生了什么,在Git中重命名冲突
。
文件需要一些内容
,以便git可以检测
重命名,当我们实际上
做重命名时。
$ cat> 2
这是文件2。
我们给它一些内容
,以便它具有唯一的SHA-1。
$ git add。
$ git commit -m初始
[master(root-commit)a4b6f52] initial
2个文件已更改,12个插入(+)
创建模式100644 1
create模式100644 2
接下来,我创建分支 b
并重命名。请注意,我是否使用 git mv
或 mv
进行重命名,然后是 git rm --cached
和 git add
(但 git mv
更容易,所以我用它)。但是,重要的是git能够检测到重命名。这要求文件完全匹配100%(简单情况)或匹配至少50%(该阈值可以调整,但50%是默认值),当diff-ed 和在 git merge
时,旧名称( 1
)在两棵树中不再存在。
$ git checkout -bb
转换到新分支'b'
$ git mv 1 1_b
$ git commit -m'在分支b'中重命名1到1_b
[b cc104b1]在分支中重命名1到1_b b
1个文件已更改,0个插入(+),0个删除( - )
重命名1 => 1_b(100%)
然后,我使用不同的名称目标在 master
:
$ git checkout master
切换到分支' master'
$ git mv 1 1_master
$ git commit -m'将master 1'重命名为1_master'
[master b891757]将master 1中的1重命名为1_master
更改了1个文件, 0个插入(+),0个删除( - )
重命名1 =>> 1_master(100%)
最后,我运行 git merge
$ b $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ CONFLICT(重命名):重命名1 - > HEAD分支中的1_master在b中重命名1 - >1_b
自动合并失败;修复冲突,然后提交结果。
$
您需要显示您的步骤(也可能是您的git版本)为了让我明白为什么你的合并认为每一个改变都是删除和创建(与非冲突创建),而不是重命名。
影响这个的其他变量:
-X重命名阈值
的任何参数如何调整50%的默认值);
的值
merge.renameLimit $ c $的设置,$ b
git config --get diff.renameLimit
的值c>。
This question follows this topic. I am trying to understand what merge
do to avoid unwanted mistakes during it.
I have two branches:master
,b
. I saw an strange result of doing git merge
. You can see output of git log before merging, here:
* 148c970 (HEAD, master) rename 1 in master to 1_master
| * ad18d9b (b) rename 1 in b to 1_b
|/
* 15cd89b add 1 in master
So I had a file with name 1
in master
and b
. Then rename it in master
to 1_master
and to 1_b
in b
. Then I did git merge
:
git merge b
I guess it causes a conflict, because merge base must be 15cd89b
and both branches introduce changes on 1
, which they don't match.
But merging did not cause any conflict
and after merging I saw both 1_b
and 1_master
in working directory.
Note:
I think both torek and twalberg in linked answers forecast conflict in above situation.
If I attempt to reproduce your issue I get a rename/rename conflict, as I would expect. First, I created a repository and some files (with unique contents):
$ mkdir rename-exp
$ cd rename-exp/
$ git init
Initialized empty Git repository in /home/torek/tmp/rename-exp/.git/
$ cat > 1
This is file "1" in its initial state.
The file is being used
for a test of what happens with
a rename vs rename conflict
in Git.
The file needs some contents
so that git can detect the
rename when we actually
do the rename.
$ cat > 2
This is file "2".
We give it some contents
so that it has a unique SHA-1.
$ git add .
$ git commit -m initial
[master (root-commit) a4b6f52] initial
2 files changed, 12 insertions(+)
create mode 100644 1
create mode 100644 2
Next, I create branch b
and rename. Note that it will not matter whether I do the rename with git mv
or with mv
followed by git rm --cached
and git add
(but git mv
is easier, so I use it). It is, however, important that git be able to detect the rename. This requires that either the files match 100% exactly (the easy case) or that they match "at least 50%" (this threshold can be adjusted, but 50% is the default) when diff-ed and that the old name (1
) is no longer present in both trees at the time of the git merge
.
$ git checkout -b b
Switched to a new branch 'b'
$ git mv 1 1_b
$ git commit -m 'rename 1 to 1_b in branch b'
[b cc104b1] rename 1 to 1_b in branch b
1 file changed, 0 insertions(+), 0 deletions(-)
rename 1 => 1_b (100%)
Then I do the same rename, with a different name-target, in master
:
$ git checkout master
Switched to branch 'master'
$ git mv 1 1_master
$ git commit -m 'rename 1 to 1_master in master'
[master b891757] rename 1 to 1_master in master
1 file changed, 0 insertions(+), 0 deletions(-)
rename 1 => 1_master (100%)
Finally, I run git merge
:
$ git merge b
CONFLICT (rename/rename): Rename "1"->"1_master" in branch "HEAD" rename "1"->"1_b" in "b"
Automatic merge failed; fix conflicts and then commit the result.
$
You'll need to show your steps (and perhaps your git version as well) in order for me to see why your merge thought each change was delete-and-create (with non-conflicting creates) rather than rename.
Other variables that affect this:
- any argument to
-X rename-threshold
during the merge (this is how you tune the 50% default); - the value from
git config --get merge.renameLimit
- the value from
git config --get diff.renameLimit
, if there is no setting formerge.renameLimit
.
这篇关于为什么合并不会导致冲突的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!