English 中文(简体)
How is this a conflict
原标题:

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?

问题回答

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	estsmergeLines> git init m0
PS D:git	estsmergeLines> cd m0
PS D:[...]m0> D:git	estsmergeLinesgenfile.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	estsmergeLinesgenfile.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	estsmergeLinesgenfile.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	estsmergeLines> git clone m0 m1
PS D:git	estsmergeLines> 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	estsmergeLines> git clone m0 m2
PS D:git	estsmergeLines> 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	estsmergeLinesm2> git co master
Switched to branch  master 
PS D:git	estsmergeLinesm2> git merge abranch
Updating c8f48b4..8bee1d2
Fast forward
 afile.txt |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

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.





相关问题
git confusion - cloning a repo is returning a past version

Im having some confusion with my git usage. I cloned a repo from one comp to the other, and the new clone is the state of the original that was active some time ago. So its cloning a past version. ...

Appropriate strategy for tagging and hotfixing with git

I was wondering if the strategy I m using for tagging and hotfixing tags (which then I use for deploying rails applications) with git is appropriate. For tagging I just tag a commit of the master ...

Tips on upgrading CVS to git/hg?

We still use CVS, I use git and hg for my personal use though I m still a novice at both, but I realize they re much more modern and better, faster, distributed, etc. It s just everyone is so ...

Using Git in a TFS shop

Using Git at home has spoiled me - I now find using TFS at work to be a bit of a drag and want to explore the possibility of using Git locally and syncing somehow with TFS. I figure there are a few ...

热门标签