CrazySynthax
CrazySynthax

Reputation: 14998

Why do I get conflicts when I do git revert?

I use Git, and I know that:

git revert <hash-code>

is used to create a new commit that will be identical to the past commit in the hash-code.

For example, I have the following commits:

1f74a0e second commit
e72d8b8 first commit  

I wanted to revert to the first commit, so I used:

git revert 1f74a0e

Still, I got the following error:

error: could not revert 1f74a0e... first commit hint: after resolving the conflicts, mark the corrected paths hint: with 'git add ' or 'git rm ' hint: and commit the result with 'git commit'

As for the conflicts, I type:

$ git diff --name-only --diff-filter=U
file.txt

When I open file.txt I see no signs for conflicts.

Of course there will be conflicts. I expect git to take the "first commit" and copy it on top of the second commit. How can I do it?

Upvotes: 26

Views: 37130

Answers (4)

George Shuklin
George Shuklin

Reputation: 7877

I found this question while trying to revert a commit from a linear history of many adjacent removals. Git refuses to do git revert and propose to do conflict resolution. But I know that it's only removals, and they are safe to revert. It's configuration files, so I'm fine to put lines back on any line in relation to other lines.

My solution:

git show 458d9d0a7b | patch --fuzz=999 -p1 -R

(magic is with --fuzz=999, 458d9d0a7b is a commit hash for reversal).

patch has put lines in a slightly different position (because original 'position' were removed), but for my case of configuration file that was okay.

Upvotes: 0

Diogo
Diogo

Reputation: 871

I am complementing @Edward's answer. First of all, the revert command requires "your working tree to be clean (no modifications from the HEAD commit)" (see documentation here). The revert command will revert the changes of a given commit, and it will compare your current state with the PARENT of that commit whose changes you are reverting. If current state and that PARENT conflict, git will indicate that. If not, you will get not conflict.

Here is an example based on @Edward's:

Suppose you have three commits that modify a file:

commit1:

One
Two

commit2

One
2       # < we introduced this changed in commit 2

commit3

One
2
three   # < we introduced this change in commit 3

If you revert changes introduced by commit 2 from the current state (commit 3, assuming clear three, i.e, no modifications from the HEAD commit), git will

  1. remove the modification introduced by that commit 2, changing 2 back to two
  2. keep the line three introduced in commit 3. No conflict will occur because the current state (commit 3) does not conflict with parent (commit 1) of the commit whose changing we are reverting (commit 2)

Now, suppose you have a different situation:

commit1:

One
Two
three

commit2

One
2       # < we introduced this changed in commit 2
three

commit3

One
2
3   # < we introduced this change in commit 3

If you revert changes introduced by commit 2 from the current state (commit 3, assuming clear three, i.e, no modifications from the HEAD commit), git will

  1. remove the modification introduced by that commit 2, changing 2 back to two`
  2. Compare the line introduced in commit 3 with the parent of commit 2 and indicate conflict: the line three changed to 3 and conflicts with parent (commit 1) of the commit whose changing we are reverting (commit 2)

Upvotes: 8

hspandher
hspandher

Reputation: 16733

Most likely you already have unresolved conflicts in your index, probably because of certain merge that has been left in between, or the revert itself is causing a conflict. In any case, you need to resolve the conflicts and commit.

git status
# You would find files with conflicts
# resolve the commits

git add -u
git commit

Upvotes: 0

Edward Thomson
Edward Thomson

Reputation: 78653

That's actually not what revert does. Revert doesn't "take you back to" that commit and pretend that subsequent commits didn't happen. It applies a logical negation of a single commit - and that commit alone - leaving subsequent commits in place.

Let's say you have some initial commit of some file - let's call it commit #1 for simplicity - and the file looks like this:

One
Two
Three
Four

Now let's say you have a commit #2 that changes one line:

One
2
Three
Four

And finally, commit #3 that changes a different line:

One
2
Three
4

If you try to revert commit #2, it will undo only the line changed in that commit, and leave the changes introduced in commit #3, so the result will be:

One
Two
Three
4

Now, if there was a subsequent commit that had changed the same line as the commit that you're trying to revert, then you'll have a conflict. For example, let's say you have a commit #4 that also changed the second line:

One
TWO
THREE
4

Now if your HEAD is commit #4 and you try to revert commit #2, you will have a conflict. Revert expects to take second line back - to undo the changes made in commit #2. So it expects the second line to currently be 2, and it will then revert it to what it was in the previous commit, setting it to Two.

However, that expectation was invalidated, since commit #4 had also changed it. So you have a conflict.

If your goal isn't to revert at all, but to get back to commit #1 and ignore all the changes that have gone on since then, then you want to reset instead of revert.

git reset --hard 1 

Upvotes: 45

Related Questions