Reputation: 51
I am having trouble with the git revert
command. I use Ubuntu 12.04 Linux and Git version 1.7.9.5.
b_test_repo
on my local PC, having it tracked from a remote origin b_test_repo
.A
) with two lines of text and successfully committed it only in the local master
branch.In order to try out git revert
I generated 3 more commits, each of them adding one line of text. So my master
commit history looks like:
A - B - C - D
Where
A
- new file with lines 1 & 2B
- one line addedC
- one line addedD
- one line addedAfter all these commits the file contained 5 lines:
line1
line2
line3
line4
line5
Then, I wanted to revert commit B
, which would render the file without line3
, which was added by commit B
:
git status
# On branch master
nothing to commit (working directory clean)
I type:
git revert -n master~2
to revert the effect of commit B
without committing the changes, but get the following:
error: could not revert 1a13ad6... Adding one line
hint: after resolving the conflicts, mark the corrected paths
hint: with 'git add <paths>' or 'git rm <paths>'
hint: and commit the result with 'git commit'
I am puzzled why I am getting a conflict, i.e. why does Git have a problem figuring out what it needs to change in the file.
What am I missing here? Please enlighten me!
Upvotes: 5
Views: 5151
Reputation: 1328712
Removing that line will generate a conflict with later versions which would change the same line.
So as mention in "What should I do when git revert aborts with an error message?", you need to resolve the merge, add and commit.
A simpler way to revert that commit would be an interactive rebase:
git rebase -i <SHA1 commit a>
And you drop the commit b
.
But that is valid only if you didn't already pushed your branch to an upstream repo, because it does rewrite the history of commits.
If you did already push, then git revert
is the right approach, in order to generate a new commit cancelling b
(and push that new commit on the upstream repo).
In details: your example generates the following merge conflict:
C:\Users\VonC\prog\git\tests\18779372\r1>git lg
* 10b9953 - (HEAD)
* 07fff99 - c
* 3d888c4 - b
* 8c7155f - a
(git lg
is an alias for a fancy git log
)
If there is a conflict, I prefer seeing both the source (theirs), destination (ours) and the original section as before a merge or revert:
git config merge.conflictstyle diff3
Then revert:
git revert -n master~2
That would give:
line1
line2
<<<<<<< HEAD
line3
line4
line5
||||||| 3d888c4... b
line3
=======
>>>>>>> parent of 3d888c4... b
That way, you see what git revert
does: a merge between:
b
(which obviously doesn't contain b
modification)HEAD
The merge cannot decide what do for the section starting with third line:
a
(the === >>>>
part: 'theirs' side)b
(original part between ||||
and ====
, as before revert
, with just line3
)HEAD
(the <<<< ||||
part, with the addition of line4
and line5
, even though line3
looks unchanged)The merge conflict is even clearer if you start with commit a
as:
line1
line2
line3
line4
line5
And end up with commit d
as:
line1
line2
line3b
line4c
line5d
(commit b
add 'd
' to line3, commit c
adds 'c
' to line 4, commit d
adds 'd
' to line 5)
Then a revert will give you:
git config merge.conflictstyle diff3
git revert -n master~2
cat afile.txt
line1
line2
<<<<<<< HEAD
line3b
line4c
line5d
||||||| 4ddccc1... b
line3b
line4
line5
=======
line3
line4
line5
>>>>>>> parent of 4ddccc1... b
Here the section starting at line3:
line3 -line4 -line5
in 'theirs' === >>>
, which is the parent of b
, or commit a
)line3b-line4 -line5
in commit b
(original section ||| ===
, before merge/revert)line3b-line4c-line5d
in HEAD
'ours' <<< |||
Three different contents, and no way for the merge to know what to do.
Upvotes: 4