这怎么冲突了

发布于 2024-08-11 19:22:46 字数 513 浏览 4 评论 0原文

我只是测试 git 来看看我是否可以将它用于我的工作。我遇到了一个看似很小的问题,但如果使用真实的代码,可能会变成一个真正的问题。 我的文件如下所示: 文本.txt 1 2 3 4 我有一个本地分支“branch1”,并在分支和主分支中提交了更改。 在主控中,我更改了分支中的第一行第二行。 所以 master 的 diff 看起来像这样:

+1 master
 2
 3
 4

对于分支来说是:

 1
-2
+2b1
 3
 4

运行 git mergebranch1 解决了冲突:

<<<<<<< HEAD
1 master
2
=======
1
2b1
>>>>>>> branch1
3
4

我知道这个可以很容易地解决。但无论如何,这怎么会是冲突呢? git 不应该能够合并这个吗?

i'm just testing git to find out if i could use it for my work. I ran into a problem that seems small but could become a real one with the real code.
My file looks like:
text.txt
1
2
3
4
I've a local branch "branch1" and commited changes in both branch and master.
In master i changed the first line in the branch the second.
So the diff for master looks like this:

+1 master
 2
 3
 4

For the branch it is:

 1
-2
+2b1
 3
 4

Running git merge branch1 resolves in a conflict:

<<<<<<< HEAD
1 master
2
=======
1
2b1
>>>>>>> branch1
3
4

I know this one can be resolved easily. But how is this a conflict, anyway. Shouldn't git be able to merge this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

硪扪都還晓 2024-08-18 19:22:46

几点评论:

  • 首先,这么小的例子无论如何都不会被合并:

    警告:无法合并二进制文件:afile.txt(HEAD vs. abranch)
  • 然后,如果您有许多“小”合并冲突,你知道应该独立于上下文来解析,你可以尝试首先在 master 之上重新调整你的分支,忽略上下文:

    git rebase -C0 master

然后将您的分支合并到master中。

一般来说,忽略变基的所有上下文并不是一个好主意,但如果您对修改有把握(如“根本不需要上下文的修改”),它会起作用的。

来自 git rebase 手册页

-C<n>

确保每次更改之前和之后至少 行周围上下文匹配。
当周围上下文的行数较少时,它们都必须匹配。
默认情况下,不会忽略任何上下文。


您可以很容易地对其进行测试(此处在 PowerShell 会话中,在 Xp 上使用 Git1.6.5.1)

首先创建一个小型 bat 实用程序 genfile.bat

echo hello, World %1 > afile.txt
echo hello, World %2 >> afile.txt
echo hello, World 3 >> afile.txt
echo hello, World 4 >> afile.txt
echo hello, World 5 >> afile.txt

,然后创建一个存储库并添加一个文件:

PS D:\git\tests\mergeLines> git init m0
PS D:\git\tests\mergeLines> cd m0
PS D:\[...]\m0> D:\git\tests\mergeLines\genfile.bat 1 2
PS D:\[...]\m0> git add -A
PS D:\[...]\m0> git ci -m "afile to be modified concurrently"

您的文件看起来像这样:

hello, World 1
hello, World 2
hello, World 3
hello, World 4
hello, World 5

在分支中修改它

PS D:\[...]\m0> git co -b abranch
PS D:\[...]\m0> D:\git\tests\mergeLines\genfile.bat 1 2_modified
PS D:\[...]\m0> git ci -a -m "afile modified in abranch"

您将拥有:

hello, World 1
hello, World 2_modified
hello, World 3
hello, World 4
hello, World 5

然后在 master 中修改它

PS D:\[...]\m0> git co master
PS D:\[...]\m0> D:\git\tests\mergeLines\genfile.bat 1_master 2
PS D:\[...]\m0> git ci -a -m "afile modified in master"

这将为您提供:

hello, World 1_master
hello, World 2
hello, World 3
hello, World 4
hello, World 5

克隆该存储库以进行第一个实验(即:将 abranch 合并到 master)

PS D:\[...]\m0> cd ..
PS D:\git\tests\mergeLines> git clone m0 m1
PS D:\git\tests\mergeLines> cd m1
PS D:\[...]\m1> git co -b abranch origin/abranch
PS D:\[...]\m1> git co master
PS D:\[...]\m1> git merge abranch

这会给你带来冲突:

Auto-merging afile.txt
CONFLICT (content): Merge conflict in afile.txt
Automatic merge failed; fix conflicts and then commit the result.

PS D:\[...]\m1> type afile.txt
<<<<<<< HEAD
hello, World 1_master 
hello, World 2 
=======
hello, World 1 
hello, World 2_modified 
>>>>>>> abranch
hello, World 3 
hello, World 4 
hello, World 5 

再次克隆第一个存储库,这次是在 master 之上重新设置第一个 abranch 的基础,没有上下文:

PS D:\[...]\m1> cd ..
PS D:\git\tests\mergeLines> git clone m0 m2
PS D:\git\tests\mergeLines> cd m2
PS D:\[...]\m2> git co -b abranch origin/abranch
PS D:\[...]\m2> git rebase -C0 master

您的文件被静默合并:

hello, World 1_master
hello, World 2_modified
hello, World 3
hello, World 4
hello, World 5

当然,如果您切换回master现在合并abranch,结果将是快进合并。

PS D:\git\tests\mergeLines\m2> git co master
Switched to branch 'master'
PS D:\git\tests\mergeLines\m2> git merge abranch
Updating c8f48b4..8bee1d2
Fast forward
 afile.txt |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

Couple of comments:

  • first, such a small example would never be merged anyway:

    warning: Cannot merge binary files: afile.txt (HEAD vs. abranch)
  • then, if you have many "small" merge conflicts which you know should be resolved independently of the context, you could try rebasing first your branch on top of master, ignoring the context:

    git rebase -C0 master

and then merge your branch into master.

This is generally not a good idea to ignore all context for a rebase, but if you are certain about your modifications (as in "modifications needing no context at all"), it will work.

From git rebase man page:

-C<n>

Ensure at least <n> lines of surrounding context match before and after each change.
When fewer lines of surrounding context exist they all must match.
By default no context is ever ignored.


You can test it easily enough (here in a PowerShell session, with Git1.6.5.1, on Xp)

First create a small bat utility genfile.bat

echo hello, World %1 > afile.txt
echo hello, World %2 >> afile.txt
echo hello, World 3 >> afile.txt
echo hello, World 4 >> afile.txt
echo hello, World 5 >> afile.txt

then create a repo and add a file:

PS D:\git\tests\mergeLines> git init m0
PS D:\git\tests\mergeLines> cd m0
PS D:\[...]\m0> D:\git\tests\mergeLines\genfile.bat 1 2
PS D:\[...]\m0> git add -A
PS D:\[...]\m0> git ci -m "afile to be modified concurrently"

Your file looks like this:

hello, World 1
hello, World 2
hello, World 3
hello, World 4
hello, World 5

Modify it in a branch

PS D:\[...]\m0> git co -b abranch
PS D:\[...]\m0> D:\git\tests\mergeLines\genfile.bat 1 2_modified
PS D:\[...]\m0> git ci -a -m "afile modified in abranch"

You will have:

hello, World 1
hello, World 2_modified
hello, World 3
hello, World 4
hello, World 5

Then modify it in master

PS D:\[...]\m0> git co master
PS D:\[...]\m0> D:\git\tests\mergeLines\genfile.bat 1_master 2
PS D:\[...]\m0> git ci -a -m "afile modified in master"

Which gives you:

hello, World 1_master
hello, World 2
hello, World 3
hello, World 4
hello, World 5

Clone that repo for a first experiment (i.e.: a merge of abranch into master)

PS D:\[...]\m0> cd ..
PS D:\git\tests\mergeLines> git clone m0 m1
PS D:\git\tests\mergeLines> cd m1
PS D:\[...]\m1> git co -b abranch origin/abranch
PS D:\[...]\m1> git co master
PS D:\[...]\m1> git merge abranch

That gives you a conflict:

Auto-merging afile.txt
CONFLICT (content): Merge conflict in afile.txt
Automatic merge failed; fix conflicts and then commit the result.

PS D:\[...]\m1> type afile.txt
<<<<<<< HEAD
hello, World 1_master 
hello, World 2 
=======
hello, World 1 
hello, World 2_modified 
>>>>>>> abranch
hello, World 3 
hello, World 4 
hello, World 5 

Clone the first repo again, this time to rebase first abranch on top of master, with no context:

PS D:\[...]\m1> cd ..
PS D:\git\tests\mergeLines> git clone m0 m2
PS D:\git\tests\mergeLines> cd m2
PS D:\[...]\m2> git co -b abranch origin/abranch
PS D:\[...]\m2> git rebase -C0 master

Your file is silently merged:

hello, World 1_master
hello, World 2_modified
hello, World 3
hello, World 4
hello, World 5

Off course, if you switch back to master and now merge abranch, the result will be a fast-forward merge.

PS D:\git\tests\mergeLines\m2> git co master
Switched to branch 'master'
PS D:\git\tests\mergeLines\m2> git merge abranch
Updating c8f48b4..8bee1d2
Fast forward
 afile.txt |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
┾廆蒐ゝ 2024-08-18 19:22:46

没有上下文可以隔离这两个更改,因此不清楚正确的解决方案应该是什么。对于一行上下文,更改为:将块“1/2”更改为“1 master/2”,并将块“1/2/3”更改为“1/2b1/3”。

尝试将第二个“补丁”应用到第一个补丁的结果会导致错误,因为成功应用补丁所需的上下文不匹配。该补丁需要“1/2/3”,但有“1 master/2/3”。

在更复杂的场景中,足够的上下文非常重要,因为如果没有它,如果本地分支已经移动了足够多的行并且在原始位置检查的最小上下文量足够,则合并很容易在错误的位置应用补丁,而不会发出警告不明确的是,该补丁在不应该应用的情况下仍然应用。

There's no context that isolates the two changes so it's not clear what the the correct resolution should be. With one line of context the changes are: change the block "1/2" to "1 master/2" and change the block "1/2/3" to "1/2b1/3".

Trying to apply the second 'patch' to the result of the first patch resolves in an error because the context needed to successfully apply the patch is not a match. The patch needs "1/2/3", but has "1 master/2/3".

Sufficient context is important in more complex scenarios as without it, it would be easy for merge to apply the patch in the wrong place without warning if the local branch had moved enough lines around and the minimal amount of context checked at the original location was sufficiently non-specific that the patch still applied when it shouldn't.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文