3

I am learning git. I have the following scenario:

1) A file named test.txt the initial contents of the file :

one line

I commit the file with this content.

2) I add a new line to the file The contents of the file now is:

one line
two line

I commit the file with this content

3)I add a new line to the file The contents of the file now is:

one line
two line
three line

I commit the file with this content.

Now i want to revert the second commit. So the content of my file should be

one line

three line

but when i run : git revert commitid_2 I get the following error message:

error: could not revert 4d417ed... two 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'

When i open the test.txt file: i see the contents replaced by the following:

<<<<<<< HEAD
one line
two line
three line
=======
one line
>>>>>>> parent of 4d417ed... two line

What does this mean? How can i revert the changes made by commit 2 alone while keeping the changes made by commit 1 and commit 3 intact?

torek
  • 448,244
  • 59
  • 642
  • 775
newbie
  • 1,049
  • 5
  • 15
  • 29
  • 1
    "So the content of my file should be" --- how git is supposed to know that you want an empty line instead of the second line contents? – zerkms Dec 05 '13 at 00:26

1 Answers1

4

Here's what git revert does, simplified (hopefully not oversimplified). You give it a commit ID, or a name that resolves to a commit ID—in this case, apparently that was 4d417ed—and it finds out what changed in that commit, by diff-ing the files in the commit with those in the commit just before it. That is:

git diff 4d417ed^ 4d417ed

The diff reads:

diff --git a/test.txt b/test.txt
index [something]..[something] 100644
--- a/test.txt
+++ b/test.txt
@@ -1 +1,2 @@
 one line
+two line

(the index and mode are not so important; the key is that this shows the old and new versions, in a "unified diff"). The unified diff shows that there was (only) one line above the added line, and no lines below it.

In a unified diff, there are extra "context" lines on either side of each change. Here's a more typical unified-diff chunk, where I moved one line of code up a few lines:

@@ -12,9 +12,9 @@ class Peer(object):

     def _renew(self):
         self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+        self._sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
         self._sock.bind(self._local_addr)
         self._sock.setblocking(False)
-        self._sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
         self._state = 'bound'

     def is_open(self):

See how there are three lines before the +, and three lines after the -? For test.txt, though, since there's no "after" context line, the file must have ended after the added line. The absence of the three lines of "after" context mean "file ended here". (And, the single "before" line tells git—redundantly, it's obvious from the line numbers—that the file had only one line "before" the change.)

In any case, since you're doing a revert, git now attempts to "reverse patch" the current version of the file, using the change shown above.

To do a "forward patch", git would expect the file to look like the "before" version—that is, it would use the line numbers and the context lines, finding the nearest lines to the given line numbers that have the exact same context, and change those to look like the "after". To reverse a patch, git expects the to look like the "after", and would change it to look like the "before". But the current version of the file has "extra stuff" after the line two line. That is, the context doesn't match. If the file ended after the line reading two line, git would know what to do: remove the line two line. But git doesn't know what to do, so it leaves the modified file, with conflict markers, for you to resolve manually.

If you set merge.conflictstyle to diff3, git will leave you with this in your test.txt file:

one line
<<<<<<< HEAD
two line
three line
||||||| 4d417ed... add a line
two line
=======
>>>>>>> parent of 4d417ed... add a line

Some people find this easier to read (though in this case it does not really help much).

(Aside: I'm not sure why you don't want the file to read:

one line
three line

with no blank line in between, either. But that's a completely different issue.)

torek
  • 448,244
  • 59
  • 642
  • 775