Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do I get conflicts when I do git revert?

Tags:

git

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

like image 797
CrazySynthax Avatar asked Sep 18 '17 08:09

CrazySynthax


People also ask

Why do I keep getting merge conflicts?

Often, merge conflicts happen when people make different changes to the same line of the same file, or when one person edits a file and another person deletes the same file. You must resolve all merge conflicts before you can merge a pull request on GitHub.

What causes conflicts in git?

A conflict arises when two separate branches have made edits to the same line in a file, or when a file has been deleted in one branch but edited in the other. Conflicts will most likely happen when working in a team environment. There are many tools to help resolve merge conflicts.


2 Answers

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 
like image 178
Edward Thomson Avatar answered Sep 29 '22 19:09

Edward Thomson


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)
like image 32
Diogo Avatar answered Sep 29 '22 17:09

Diogo