Git - automatically create distinct files for versions on conflict
When Git detects a conflict during merge, the default behaviour is to fill the file with <<<
>>>
===
markers.
This is OK most of the time, but sometimes I'd like to resolve conflicts differently and I'd just like Git to create distinct files:
- original version,
- changed version A,
- changed version B.
How to achieve that?
If there's no simple command to create those files in one go (which is somewhat surprising), maybe there is a way to extend Git so that it would do it? A custom mergetool
or something? Just an idea.
Solution:
I've settled for a variant of @Karl Bielefeldt's answer:
savefiles.sh
#!bash
BASE=$1
LOCAL=$2
REMOTE=$3
MERGED=$4
cp "$BASE" "开发者_如何转开发$MERGED.git_BASE"
cp "$LOCAL" "$MERGED.git_LOCAL"
cp "$REMOTE" "$MERGED.git_REMOTE"
# never mark the conflict as merged
exit 1
config
mergetool.savefiles.cmd=/path/to/savefiles.sh $BASE $LOCAL $REMOTE $MERGED
mergetool.savefiles.trustexitcode=true
Create a file called savefiles.sh
with the following contents:
#!/usr/bin/bash
cp $1 /path/to/BASE
cp $2 /path/to/LOCAL
cp $3 /path/to/REMOTE
Execute the following command inside your repository:
git config mergetool.savefiles.cmd "/path/to/savefiles.sh \$BASE \$LOCAL \$REMOTE"
Add a --global
if you want to change it for other than this repository.
Then to run this custom mergetool, use:
git mergetool --tool=savefiles
If you want to go without mergetool, and just display or save the files in the states you mention, the index holds the different states of the conflicted file. You can display (and redirect to a file if you want) with:
$ git show :1:file.txt # the file in a common ancestor of both branches
$ git show :2:file.txt # the version from HEAD.
$ git show :3:file.txt # the version from MERGE_HEAD.
However, using a graphical merge tool shows you a 3-pane view of the conflicted file. That's usually what people do, so just pick up your favorite tool and see how to link it with git mergetool
call.
Summary
git mergetool -y -t bogus <file>
Works for me with git 1.7.9.5 / Ubuntu 12.04 and msysgit 1.9.4 / Windows 7 x64.
Explanation
I'd just like Git to create distinct files
I was looking for the same thing. Case in point: when invoking git mergetool -t kdiff3
, git apparently tries to outsmart me by invoking kdiff3 with a hard-coded --auto
flag that instructs kdiff3 to automatically resolve conflicts and exit without showing me the GUI or allowing me to participate in the process (see also). When that happened and kdiff3 resolved the conflicts wrong, I went looking for this.
When I invoke mergetool
like so (where bogus
is a string that is not a valid merge tool identifier [e.g. not in the output of git mergetool --tool-help
if your version of git has that]), the following happens:
It reports "Unknown merge tool bogus"
The index and
file
are untouchedThe following files are generated (where
{num}
is an integer that is the same in all files created by this invocation):file.BACKUP.{num} file.BASE.{num} file.LOCAL.{num} file.REMOTE.{num}
file.BACKUP.{num}
is identical to file
.
Notes
I think the -y
should be unnecessary if mergetool.prompt
is set to false
. And, according to the documentation, it looks like in newer versions of git -t
implies -y
.
The -t
part can be further shortened, e.g. -t x
or -t 0
.
If you have multiple unmerged files, there doesn't appear to be any way to get this to generate these versions for more than one file at a time. E.g. if you have unmerged files files/file1
and files/file2
, any of the following will still only generate these versions (backup, base, local, remote) for file1
:
git mergetool -y -t x
git mergetool -y -t x files
git mergetool -y -t x files/file1 files/file2
However, if you resolve the conflicts in file1
and run git mergetool
again, it'll move on to the next file.
精彩评论