可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
When there's a collison during git merge
, I open a mergetool called Meld. It opens three files LOCAL, BASE and REMOTE. As I've read LOCAL is my local branch, BASE is common ancestor and REMOTE is the branch to be merged.
Now to my question: which version of the file will be finally used? Is it REMOTE? If so, can I edit it as I want, regardless what's in the BASE branch for example?
回答1:
It's the one in the middle : BASE
.
In fact, BASE
is not the common ancestor, but the half-finished merge where conflicts are marked with >>>>
and <<<<
.
You can see the file names on the top of meld editing window.
See the screenshot here
You can edit the BASE
file as you want with or without using meld commands.
You can also get rid of meld and just edit the file with your favorite text editor.
- The code between
<<<< HEAD
and =====
markers is the one of your local file before the merge.
- The code between
====
and >>>> <branch name>
is the one of the remote file.
回答2:
Meld has a hidden 3-way merge feature activated by passing in the 4th parameter:
meld $LOCAL $BASE $REMOTE $MERGED
The right and left panes are opened in read-only mode, so you can't accidentally merge the wrong way around. The middle pane shows the result of merge. For the conflicts it shows the base version so that you can see all the important bits: original text in the middle, and conflicting modifications at both sides. Finally, when you press the "Save" button, the $MERGED file is written - exactly as expected by git.
The ~/.gitconfig file I use contains the following settings:
[merge]
tool = mymeld
conflictstyle = diff3
[mergetool "mymeld"]
cmd = meld --diff $BASE $LOCAL --diff $BASE $REMOTE --diff $LOCAL $BASE $REMOTE $MERGED
this opens meld with 3 tabs, 1st and 2nd tab containing the simple diffs I'm trying to merge, and the 3rd tab, open by default, shows the 3-way merge view.
Now, the reason the feature is hidden is that it's not polished enough yet. It's very useful as it is now, but Kai Willadsen, the meld author, pointed to few wrinkles that need ironing out. For example there's no GUI to start the 3-way merge mode, command line syntax is a bit arcane, and such. If you speak python and have some time on your hands - you know what to do.
Edit:
In newer versions of Meld, the synax has changed slightly. This was in the comments, but it belongs in the answer.
The meld command now uses the --output option, so the last line from the snippet above should be:
cmd = meld --diff $BASE $LOCAL --diff $BASE $REMOTE --diff $LOCAL $BASE $REMOTE --output $MERGED
回答3:
There are 4 files involved:
$LOCAL
The file on the branch where you are merging; untouched by the merge process when shown to you
$REMOTE
The file on the branch from where you are merging; untouched by the merge process when shown to you
$BASE
The common ancestor of $LOCAL and $REMOTE, ie. the point where the two branches started diverting the considered file; untouched by the merge process when shown to you
$MERGED
The partially merged file, with conflicts; this is the only file touched by the merge process and, actually, never shown to you in meld
The $MERGED
file is the one that contains the <<<<<<
, >>>>>>
, =====
(and, maybe, ||||||
) markers (that delimit conflicts). This is the file that you edit manually to correct conflicts.
The manual conflicts editing and the visual conflicts editing are done on different files and presented different informations.
When using the mergetool (assume meld
), the files that are seeing therein are: $LOCAL
, $BASE
, $REMOTE
. Note that you don't see the $MERGED
file, although this is passed as a hidden parameter to meld
to write the result of the edit there.
In other words, in meld
, you are editing the file in the middle, the $BASE
file, and you pick all the changes from left or from the right manually. It is a clean file, not touched by the merge process. The only glitch is that, when you save, you do not save into the $BASE
file, but in the fourth hidden parameter of meld
, that is the $MERGED
file (that you do not even see). The $BASE
file does not contain any conflicts or partial successful merges because it is not the $MERGED
file.
In the visual editing, when presenting to you the $BASE
file (instead of the $MERGED
file) git
basically discards all its attempts to do the merging (those attempts are visible, if you want, in the $MERGED file) and lets you to completely do the merging from scratch.
The bottom line is that in manual and visual merging conflicts you are not looking at the same files, but the final result is written in the same file (that is the $MERGED
file).
The manual correction of the conflicts is done on $MERGED
because git
has no mean to present you three files, so it squashes the information from the three files ($LOCAL
, $BASE
, $REMOTE
) in that $MERGED
file.
But the visual tools have the means to show you three files: they show you the $LOCAL
, $BASE
, $REMOTE
files. You are picking changes from the $LOCAL
and $REMOTE
files and you are bringing those into the $BASE
file, completely re-building and even overwriting the failed attempt of merging that is the $MERGED
file.
回答4:
Cosmin's solution works, but the $BASE file is updated--not $MERGED. This will update the $MERGED file:
Meld: v1.8.4
[merge]
conflictstyle = diff3
tool = mymeld
[mergetool "mymeld"]
cmd = meld --auto-merge --output $MERGED $LOCAL $BASE $REMOTE --diff $BASE $LOCAL --diff $BASE $REMOTE
回答5:
With Meld 1.7 the Solution by Tomek Bury does not work anymore.
The default settings didn't satisfy me:
Instead for Meld >=1.7 I suggest one of two other solutions.
First solution:
meld $LOCAL $BASE $REMOTE --auto-merge
Second solution:
meld $LOCAL $MERGED $REMOTE
.gitconfig
Copy & paste this in your .gitconfig
file to get the solutions as described above:
[merge]
tool = meld16
[mergetool "meld17"]
# use this for Meld >=1.7
# see http://stackoverflow.com/a/22911793/859591
# second solution:
cmd = meld $LOCAL $MERGED $REMOTE
# first solution:
#cmd = meld $LOCAL $BASE $REMOTE --auto-merge
[mergetool "meld16"]
cmd = meld --diff $BASE $LOCAL --diff $BASE $REMOTE --diff $LOCAL $BASE $REMOTE --output $MERGED
[include]
# requires git v1.7.10+
path = .gitconfig.local
Copy & paste this in a .gitconfig.local
file to set meld17 or meld16 only for this machine in case you use your .gitconfig on multiple machines:
# This is a host specific config file!
# Note that git 1.7.10+ is needed
# http://stackoverflow.com/a/9733277/859591
[merge]
tool = meld17
回答6:
I found that none of the default files shown was being saved.
meld was showing $LOCAL
, $REMOTE
and $BASE
by default. To make it work, I needed to make meld show $MERGED
instead of $BASE
. Putting this in my ~/.gitconfig
fixed it for me:
[merge]
tool = mymeld
[mergetool "mymeld"]
cmd = meld "$LOCAL" "$MERGED" "$REMOTE"
I'm using Arch, with:
$ git --version
git version 1.8.2
$ meld --version
meld 1.7.1
回答7:
For some reason newest versions of meld does not display marker lines added for conflicts (<<<<<<<, =======, >>>>>>>) . If you want to see those lines, you should to install meld v 1.3.3 or previous.
回答8:
Please see Saad's answer for the correct answer.
With meld 1.8.1 on Ubuntu I was getting the
wrong number of arguments supplied to --diff
and adding the --output before $MERGED fixed it for me:
[mergetool "mymeld"]
cmd = meld --diff $BASE $LOCAL --diff $BASE $REMOTE --diff $LOCAL $BASE $REMOTE --output $MERGED