Git Rollback


Lately I've been spending some of my free time giving back to the Python community, sending in patches and doing patch reviews for the core Python project. The Python project uses Mercurial for its source code management. So I've been able to get a little more familiar with Mercurial as of late. This led me to learn about the rollback command, which I've found to be helpful.

A while ago I was lucky enough to watch the live stream of the “Fringes of Git” video by O'Rielly (which you can view here). In the video I learned about Git's reflog and how it keeps commits relative to the HEAD (or TIP for you hg users). So I had the bright idea of trying to implement Mercuial's rollback command by using an alias in Git.

For starters I put this alias into my .gitconfig file (avoid adding the alias block if you already have one):

  1. [alias]
  2. rollback = reset –hard HEAD@{1}

There... now you have the “git rollback” command.

Here was the process I used to test how similar the git version of rollback is to the mercurial one:
created two directories: test_hg and test_git
ran hg init in test_hg and git init in test_git:q
then just created a file called test.txt, added “test 1” into both directories, then committed appropriately.
Repeated the process for “line 2” and “line 3” and committing the additions.
This created a hg log like this:

  1. changeset: 2:fddfdadb02cc
  2. tag: tip
  3. user: Bryce Verdier <bryce@scrollingtext.org>
  4. date: Tue May 10 11:06:30 2011 -0700
  5. summary: test 3
  6.  
  7. changeset: 1:02ab8efc62ce
  8. user: Bryce Verdier <bryce@scrollingtext.org>
  9. date: Tue May 10 11:06:22 2011 -0700
  10. summary: test 2
  11.  
  12. changeset: 0:ca1341dfc464
  13. user: Bryce Verdier <bryce@scrollingtext.org>
  14. date: Tue May 10 11:06:14 2011 -0700
  15. summary: test 1

and a git log like this:

  1. commit 0357aa15e585692abda6e0c36213fce9f80523a4
  2. Author: Bryce Verdier <bryce@scrollingtext.org>
  3. Date: Tue May 10 11:07:31 2011 -0700
  4.  
  5. test 3
  6.  
  7. commit 7e2d21450b0e085ca57ac8e15b7f5b46314c1264
  8. Author: Bryce Verdier <bryce@scrollingtext.org>
  9. Date: Tue May 10 11:07:24 2011 -0700
  10.  
  11. test 2
  12.  
  13. commit d165a9825e96d40608b1da4319321c272424e019
  14. Author: Bryce Verdier <bryce@scrollingtext.org>
  15. Date: Tue May 10 11:07:15 2011 -0700
  16.  
  17. test 1

Next I ran “git rollback” and got a log like so:
  1. commit 7e2d21450b0e085ca57ac8e15b7f5b46314c1264
  2. Author: Bryce Verdier <bryce@scrollingtext.org>
  3. Date: Tue May 10 11:07:24 2011 -0700
  4.  
  5. test 2
  6.  
  7. commit d165a9825e96d40608b1da4319321c272424e019
  8. Author: Bryce Verdier <bryce@scrollingtext.org>
  9. Date: Tue May 10 11:07:15 2011 -0700
  10.  
  11. test 1
  12.  
  13. And when I did the same for mercurial, I got a similar result:
  14. changeset: 1:02ab8efc62ce
  15. tag: tip
  16. user: Bryce Verdier <bryce@scrollingtext.org>
  17. date: Tue May 10 11:06:22 2011 -0700
  18. summary: test 2
  19.  
  20. changeset: 0:ca1341dfc464
  21. user: Bryce Verdier <bryce@scrollingtext.org>
  22. date: Tue May 10 11:06:14 2011 -0700
  23. summary: test 1

A difference showed up though when I ran the command a second time. When I ran “git rollback” this was my log result:
  1. commit 0357aa15e585692abda6e0c36213fce9f80523a4
  2. Author: Bryce Verdier <bryce@scrollingtext.org>
  3. Date: Tue May 10 11:07:31 2011 -0700
  4.  
  5. test 3
  6.  
  7. commit 7e2d21450b0e085ca57ac8e15b7f5b46314c1264
  8. Author: Bryce Verdier <bryce@scrollingtext.org>
  9. Date: Tue May 10 11:07:24 2011 -0700
  10.  
  11. test 2
  12.  
  13. commit d165a9825e96d40608b1da4319321c272424e019
  14. Author: Bryce Verdier <bryce@scrollingtext.org>
  15. Date: Tue May 10 11:07:15 2011 -0700
  16.  
  17. test 1

And when I ran “hg rollback” a second time I received an error:
“no rollback information available”

At this moment I'm not very knowledgeable in how Mercurial deals with its logs. But at this cursory glance it appears as if the rollback command completely removes all traces of the last commit. (Someone please correct me if I'm wrong.) Also, the rollback does not go back any further than one commit. I honestly think that this might be a good thing because it could keep you from blindly shooting yourself in the foot, if you need to go further back than one commit there is always the revert command.

While I don't know much about Git's internals either. However I can at least make sense as to why the rollback alias functions this way. By using the reflog to revert to the last commit, I end up undoing my undue. Which can be seen when we review the reflog after running the rollback command twice:

  1. 0357aa1 HEAD@{0}: HEAD@{1}: updating HEAD
  2. 7e2d214 HEAD@{1}: HEAD@{1}: updating HEAD
  3. 0357aa1 HEAD@{2}: commit: test 3
  4. 7e2d214 HEAD@{3}: commit: test 2
  5. d165a98 HEAD@{4}: commit (initial): test 1

This makes sense to me if I focus on two things in particular in the log above. 1) Git's SHA1 hashes in the first column. And 2) looking at the log in reverse. Starting with the last line, we see the first commit. And going up to the second to last line we have the second commit. If you notice the hash values for “commit: test 2” and “commit: test 3”, those are the same hashes used for both of the git rollback commands, the second and first lines of the log. So instead of removing an entry from the log, git is just moving the head to the last commit.

While my alias isn't a complete copy of Mercurial's rollback command. I do feel that the abstract idea behind it is still correct. And hopefully I've done something to help make Git a little easier to use for someone out there besides myself.

Project Euler: Problem 10

Thank you for your patience as you all (I'm sure) anxiously await my next posting.

Not only has it been a really long time since I posted something technical, it's also been a really long time since I posted a Project Euler solution. On that note, let's go over the challenge:

The sum of the primes below 10 is 2 + 3 + 5 + 7 = 17.
Find the sum of all the primes below two million.

Seems simple enough doesn't it? Let's find out. For Python the code is:

  1. #!/usr/bin/python
  2. """
  3. Python based code solution to problem 10 of project euler.
  4. """
  5. import math
  6.  
  7. def is_prime(divided):
  8. divisor = 3
  9. sqrt_divided = int(math.sqrt(divided))
  10. while divisor <= sqrt_divided:
  11. if divided % divisor == 0:
  12. return False
  13.  
  14. divisor += 2
  15.  
  16. return True
  17.  
  18. if __name__ == "__main__":
  19. print sum([2] + [x for x in xrange(3,2000000+1, +2) if is_prime(x)])

And for Haskell the code looks like:

  1. module Main where
  2.  
  3. prime_wrapper:: Int -> [Int]
  4. prime_wrapper divided = prime 3 divided (round . sqrt. fromIntegral $ divided)
  5.  
  6. prime:: Int -> Int -> Int -> [Int]
  7. prime divisor divided sqrt_divided
  8. | divisor > sqrt_divided = [divided]
  9. | mod divided divisor == 0 = []
  10. | otherwise = next_prime
  11. where next_prime = prime (divisor + 2) divided sqrt_divided
  12.  
  13. main :: IO ()
  14. main = print $ sum primes
  15. where primes = 2 : [ x | x <- [3,5..2000000], prime_wrapper x /= [] ]

I will be the first to admit that this problem is a little on the easy side. Mostly because you can reuse the code you created for problems 3 and 7, or at least I did. :)

Even though you and I know that Haskell will execute this code faster than Python, I feel I still need to uphold the tradition of posting my highly inaccurate execution times:

Python: 34.054s
Haskell: 20.690s

And I'm Back!!!

After about a month of fighting with ISP's and registrars the blog has returned. I haven't stopped writing during this time and I plan on posting a new post next week. Once all the DNS servers are done propigating my server's IP around the interwebs of course.

I hope everyone has been well and I look forward to your comments as I continue to expand the content of this blog.

Changing hosting providers

I'm sorry for the delay in writing. Unfortunately I am not updating the site with another blog post. I am giving everyone a quick heads up that I am changing web hosts and the site might be having issues over the next few days. You have been warned.

Syndicate content