I have upvoted poke's answer since that is normally the way you would deal with this.
Since there is no commit before the problematic point, though, you are left with the git checkout --orphan
trick as the only way to do that. This is actually a reasonable trick and you might consider it. However, there's still a problem; see below.
For completeness, let me also note that nisevi's answer's link to Git-Tools-Advanced-Merging contains the other way to deal with this in git. Specifically, the git suite includes the command git merge-file
, which is basically a clone of the old RCS file merge command.
Using git merge-file
You must feed git merge-file
three input files: the current version, the common base version, and the "other" version that is to be merged-in.
You need not create a new branch or commit to use this. Simply check out both the current and previous versions.
In this case, what git would do is to use an empty file as the common base version (since there is no version previous to these two). Let's take a look at what happens:
$ git show HEAD~1:file > file.v1
$ git show HEAD:file > file.v2
$ : > file.base # or cp /dev/null, or use /dev/null directly
$ cp file.v1 file.merged && git merge-file file.merged file.base file.v2
The flaw, and how to fix it
Note that I have merge.conflictstyle
set to diff3
, so that I get the common base version here.
$ cat file.merged
<<<<<<< file.merged
This is a file
that has some text.
This is the
version that
I call
v2,
which was
created from
scratch in
the editor.
||||||| file.base
=======
This is a file
that has some text.
This is the
version that
I call
v1,
which was
created from
scratch in
the editor.
>>>>>>> file.v1
Ugh! Git treats the entire addition (from the empty base) as the two sides of the change, and finds that the entire v1
version conflicts with the entire v2
version.
The solution is simple: pick out all the common lines in the two initial versions as the common base. Actually achieving that is a bit trickier. Here are a few hints:
$ git diff --no-index -- file.v1 file.v2
[output omitted]
$ diff file.v1 file.v2
6c6
< v1,
---
> v2,
These show that line 6 is the (single) problematic line, so let's make a file.base
that omits it:
$ cp file.v1 file.base && printf '6d\nw\nq\n' | ed file.base
117
113
$ cp file.v1 file.merged && git merge-file file.merged file.base file.v2
$ cat file.merged
This is a file
that has some text.
This is the
version that
I call
<<<<<<< file.merged
v1,
||||||| file.base
=======
v2,
>>>>>>> file.v2
which was
created from
scratch in
the editor.
(Note: besides git merge-file
, there is git merge-one-file
, which allows you to extract the files directly from the repository, but its use is not well documented, and git merge-file
does what we need here, at the expense of having to clean up a bit later: namely, removing the base, v1, v2, and merged temporary files. And of course you can get away with one fewer temporary files; I used the method I did to try to make the action clearer.)
P.S.: You could automate creation of the common base by parsing the output of (plain) diff, or using python's difflib
. I would probably choose the latter to write such a tool. It was also tempting to try to use comm
somehow, but comm
requires sorted inputs, and that's far too destructive. :-)