Blog

18
January 2014

Gavin Pickin

Git for Dummies - Rolling back a Commit - Power of Git

Source Control

Welcome back to our Git for Dummies, or introduction to Git series. Its been a while since my last post on this, but today I had to write one. One of the reasons we should really use source control was made very evident today, so I decided to share my story, albeit, at my own expense, you'll find out why, soon. So I got a text message today, asking if I could restore a folder on one of our servers. Some how, the folder got zapped, not sure by who, not sure how, but we need to restore it, so it can be business as usual. Should we restore from backup? We could, but we have Git setup for this project, so we can check the commits, and restore the folder from the last good commit, simple enough... so lets go through it.

Now, first, I wanted to know when did this folder suddenly disappear. You can use command line for all of this stuff, and we have been so far in this dummies series, but sometimes, there is a time and a place for GUI, and using BitBucket (this is where we host our private git repos) and BitBucket's website is a perfect example for this, instead of looking through command line readout.

So I login to BitBucket.org, pull up the repo in question, and look at the Commits page. I can see which author committed, and when, and click on each one, to see where the FOLDER was mentioned as missing. I find the commit, and then look at the date and time, and I think to myself, oh snap. Days like this, you need Git to help you out of a mess, that Git got you into. Well, not Git per say, but cleaning up the Git repo, to remove files and folders we don't need, late at night, and you accidentally remove the entire folder, not just the deleted file you intended, and being too tired to notice the difference. Yes, it was me, I removed the whole folder from my repo... and committed the change, eliminating that folder.

This is Git though, and no matter how it happened, we have ways to Clone a repo, switch to a previous commit etc, so that is exactly what I did, and it didn't take long, much faster than restoring from a backup, wherever those are.

To roll back your repo to a given commit, you need to know the commit id. We know the notes on it, by looking at the BitBucket.org commit screen, but the IDs there are not the same as on the machine you made the commit on. So at the command line, in the repo, you can type 

$ git log

 

This will dump the whole log, and it give you something like this.

 

This is a pretty nice format, but the log function is pretty powerful, you can just ask for one liners

$ git log --pretty=oneline
94231de7ceceb89a6fe3aaf1842ca29a5999e85e Fixed Git Ignore
5c87e4758c6aa7116853bf1fd81666ed69c44816 GitIgnore Cleanup on Production
5270d58e60db2eee8b7d50fbf67606555da7b5a3 Updated for Dev Environment Variables
3016eadbdaf12f5be4f0179a1951420baa1ee99c Upload Letter Product ID Fixed
e930333e9556d6ee5dada58c935682078319501a Production Updates - Git Ignores
b5d78bf6c0535da1559e260d30053543c4c50454 First set of files from New Supernova

 

And you can even roll your own style if you want.

$ git log --pretty=format:"%H - %an: %s"
94231de7ceceb89a6fe3aaf1842ca29a5999e85e - Gavin Pickin: Fixed Git Ignore
5c87e4758c6aa7116853bf1fd81666ed69c44816 - Gavin Pickin: GitIgnore Cleanup on Production
5270d58e60db2eee8b7d50fbf67606555da7b5a3 - Gavin: Updated for Dev Environment Variables
3016eadbdaf12f5be4f0179a1951420baa1ee99c - Gavin - Supernova Production: Upload Letter Product ID Fixed
e930333e9556d6ee5dada58c935682078319501a - Gavin - Supernova Production: Production Updates - Git Ignores
b5d78bf6c0535da1559e260d30053543c4c50454 - root: First set of files from New Supernova


You can limit the time limit on the log too by doing something like this

$ git log --since=1.weeks
commit 94231de7ceceb89a6fe3aaf1842ca29a5999e85e
Author: Gavin Pickin <gavin@netxn.com>
Date:   Sat Jan 18 12:34:11 2014 -0800

    Fixed Git Ignore

commit 5c87e4758c6aa7116853bf1fd81666ed69c44816
Author: Gavin Pickin <gavin@netxn.com>
Date:   Thu Jan 16 14:46:10 2014 -0800

    GitIgnore Cleanup on Production

 

You can find a lot of cool info on the Commit History at this link http://git-scm.com/book/en/Git-Basics-Viewing-the-Commit-History
The git-scm.com site has a lot of good information.

Ok, so now we have found the right commit hash (the one before I screwed up royally)... we need to tell Git to roll back our repo to that commit.

$ git reset --hard 5c87e4758c6aa7116853bf1fd81666ed69c44816
HEAD is now at 5c87e47 GitIgnore Cleanup on Production

 

Pretty simple looking, git reset and the hash. What does the --hard do? The --hard tells git we want to roll back the commit history, and the files. Without --hard, it rolls back the commit history, but leaves the file structure in tack. We need the --hard, and you can see the files are back. I look, and ta-daa!!!, the folder is back.

Now the local repo is fixed, what about the remote repo? Lets do a git push.

$ git push
To ssh://git@bitbucket.org/xxxxx/www.xxxxx.com.git
 ! [rejected]        master -> master (non-fast-forward)
error: failed to push some refs to 'ssh://git@bitbucket.org/xxxxxx/www.xxxxx.com.git'
To prevent you from losing history, non-fast-forward updates were rejected
Merge the remote changes before pushing again.  See the 'Note about
fast-forwards' section of 'git push --help' for details.

 

This is a nice feature, making sure someone doesn't roll back the remote repo by mistake if they're playing with rolling back a commit on their local repo. To push and force the remote to roll back, we need to add a -f flag.

$ git push origin master -f
Counting objects: 9, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (5/5), done.
Writing objects: 100% (6/6), 1.14 KiB, done.
Total 6 (delta 2), reused 0 (delta 0)
To ssh://git@bitbucket.org/xxxxxx/www.xxxxxx.com.git
 + 354a3d4...94231de master -> master (forced update)

 

If we login to BitBucket.org again, look at commits, and we'll see the roll back was a success, and now the remote and the local are in sync, with the folder back in play. Saved my bacon, glad I got to play with the commit rollbacks, but of course, I would have preferred more practice without needing it.

As usual, I want to add that you should play, test, and get used to using all of Git's functions, rolling back, locally and remotely, and really get familiar before making a mess of things, like me :) Git's a great tool, but like any great tool, doesn't mean you'll do great things, because the operator is in control (or is supposed to be). So practice, make sure you know what its actually doing. Setup a git101 repo and play with it. See what happens when you do this, and that. It was interesting watching what happens when you use branches... which is probably going to be the next entry in this series.

Thanks for reading,

Gavin

by Jared
01/21/2014 02:38:11 PM

Looks good, I like the clean and concise approach to explaining rolling back in git. Not too many blog posts cover it with out getting overly involved in all the other intricacies of git.

Atlassian the company that created the bitbucket site, has a GUI tool called SourceTree that makes it very easy for a novice to utilize git and all its power. I still prefer using the command line interface for certain actions but source tree is a great utility.

by Gavin
01/21/2014 10:54:37 PM

I use SourceTree personally, but obviously working on Linux boxes, using the command line is necessary. I thought using command line would be best for beginners, since it doesn't complicate matters with the different UIs of the tools out there.

In one of my earlier posts, I mentioned some of the UI tools available, and I would try and write up mini reviews on them at some point. SourceTree is a great tool, and its very cool to see a visual of your project, but at the same time, all those UI elements can easily overwhelm you when you first open it up, especially if you're learning GIT too.

I still plan on trying to write those, but obviously, I jump around a bit in regards to topics... all depends on whats more interesting or relevant at the time.

Thanks for the comment Jared.

Blog Search