22

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 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?

Gino Mempin
  • 25,369
  • 29
  • 96
  • 135
CrazySynthax
  • 13,662
  • 34
  • 99
  • 183
  • 2
    _"...create a new commit that will be identical to the past commit in the hash-code"_ - this is incorrect. Revert creates a new commit that undoes the changes introduced in that commit. – 1615903 Sep 18 '17 at 08:47
  • _“I know that: `git revert ` is used to create a new commit that will be identical to the past commit in the hash-code.”_ No, that’s [`git cherry-pick`](https://git-scm.com/docs/git-cherry-pick). – Melebius Sep 18 '17 at 09:28
  • 1
    No, that's not `git cherry-pick` either. – Edward Thomson Sep 18 '17 at 11:15

3 Answers3

37

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 
Edward Thomson
  • 74,857
  • 14
  • 158
  • 187
  • 7
    What if I have a large range of commits to revert (not reset), which include conflicts individually, but not when put together? In other words, say I want to revert the last 100 commits, so I do `git revert 531a..HEAD`. How do I do that large revert and avoid the spurious conflicts that git wants me to resolve in order? – Patrick Szalapski Dec 09 '19 at 16:33
7

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)
Diogo
  • 842
  • 2
  • 11
  • 15
0

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
hspandher
  • 15,934
  • 2
  • 32
  • 45
  • 1
    No, this error is because revert _caused_ conflicts. If you had conflicts to begin with, revert would refuse to even start, and would give you an error message that "`Reverting is not possible because you have unmerged files`". – Edward Thomson Sep 18 '17 at 09:06