Friday, September 17, 2010

Notes on Git and the difference between the git revert and the git reset commands

It was love at first sight with git. After having been using git as the source control management tool (SCM) on a few projects, my appreciation of its architecture and ease of use grew stronger.

Git's Main Features:
I don't imagine working on a serious project without git. It's my secret weapon (not anymore after this article). What I love about git are the following main features:

1- Distributed and peer-to-peer SCM vs. the traditional central repository style

2- Extremley powerful and flexible branching that's built into its bones

3- Works great as a compliment to central repository SCM. In my opinion, git was the missing piece in the overall source control management discipline. Of course, Git can also act as the central repository as one of the nodes

4- Intuitive command line usage

5- Small foot print and simplicity

6- Introduces the concept of a third staging state (index) vs. just working set and committed states

Git's Benefits to the Development Team
1- Increases innovation. Git encourages experimentation which is the corner stone of innovation. Let's face it, a lot of developers shy away from experimenting with new ideas because they don't want to check in their experimental code into the main tree and have everyone look at it or the check in policies are strict. Having a local distributed SCM encourages the developer to play for as long as he or she wants locally with multiple versions and branches and only check in once they found their EUREKA.

2- Developers have their own local versions and branches seperated from the central repository. How many times as a developer you were asked to drop everything you're doing and work on some other code or do a quick build?

More often than not, you wouldn't want to check in your work-in-progress into the main tree. With git, you can simply switch to any build or version (commit) or branch, do a build or what have you, then easily go back to what you were doing without touching the main central repository, under the radar while your manager is wondering how could you pull this off so quickly and without waiting for the official build date when the stars are all aligned.

Implemenation Scenario of Git
I don't recommend that companies replace their central repository approach with a distributed one, to the contrary, the git approach and the central repository approach compliment one another.

What I do recommend is that each developer should have a copy of git locally to unleash their creativity, provide agility and only check in the "good" code into the company's central repository for safe keeping. The best of both worlds.

Difference Between Git Revert and Git Reset
A quick google search will introduce you to the basics of git, however, what you will not find (rarely with git), is a clear explanation of the confusing usage of the reset and the revert commands. So, I will attempt to clarify for those of you who are still struggling with them, like I was, to know when to use each.

Think of git reset [commit], especially with the --hard argument as the command that moves the HEAD "pointer" and working set to any version or "commit/checkin", disregarding all subsequent ones. It is like random access to any commit with the addition that it "resets" the HEAD pointer at that location. It is simply your HEAD mover.

On the other hand, git revert [commit] only reverts the [commit] and your current working set to the previous commit. It simply "reverts" the commit you point to the previous one. This last statement is very important to get and is mostly the source of confusion.

You can conclude from this that git revert only works on work that you have committed and not if you have code that is "not checked in" yet.

Usage Scenarios of Git Reset and Revert
For git revert, a typical usage scenario is when you get a new idea or you think you are going to refactor some code, and after you commit your supposedly "better" code, you discover that oops, it broke other areas and the refactoring was more involved that you had thought.

In that case, the proper git command to use is git revert HEAD which simply tells git to move the HEAD and index and working state to the previous state and record this revert as a new commit for records keeping.

For git reset --hard, a typical usage is the same as the above scenario but this time, you haven't commited your supposed improvements yet. Also, you just want to trash your changes. As I explained, this command will move the implied HEAD pointer (you don't have to type it at the command line) to the last commit. The --hard option will align your working directory and index with it too. So you will lose your changes and bring back the last commited one.

Another scenario is when you want to move the pointer HEAD to some old commit in the past where you want to start fresh. This is not a likely scenario as you should've used the powerful git branch features, never the less, this demonstrates the "random" access to your commits of the reset command.