Pages

Friday, July 15, 2011

5 Cool Things in Git

Thing #1: Pretty coloured output
Command: git config --global color.ui auto
This will make all output colour-coded. So now git diff and git status will show up in red-green awesomeness (not that that's a great help to me, but it will be to you, undoubtedly).

Thing #2: Aliases
Command: git config --global alias.shortcut command
The beloved time-savers. Here are some of my aliases:
git config --global alias.l log
git config --global alias.s status
git config --global alias.co checkout

Thing #3: Awesome-looking git log
Command: git log --pretty=oneline --graph
Combine that with Thing #1, and you've got an ASCII-art style, rainbow-coloured, git log. And, if you have a lot of free time, or if you're just way too interested in git, you can read man git-log. There's ton of options in there.

Thing #4: A bucket-load of ways to refer to commits
Ok, first of all, branches are not branches. Yes, you read that right. A "branch" is actually just a reference to the latest commit in it. A commit's lineage defines its history, and so arises the idea of a "branch".

You can refer to commits in many ways. Let's agree on some common notations before I explain that. Every commit can be referred to by a commit pointer. The commit pointer may be followed by any number of modifiers, which will together constitute another commit pointer. A commit pointer without any modifiers can have any one of the following forms:
    a. the SHA key of the commit (the first 6-7 characters should suffice)
    b. HEAD (refers to the latest commit in the current branch)
    c. branch_name (refers to the latest commit in the branch specifed by branch_name)
    d. tag_name (refers to the commit pointed to by the tag called tag_name)

A modifier, on the other hand, can be either one of the following:
    a. ~n (refers to the nth ancestor of the commit pointed to by the commit pointer preceding it)
    b. ^ (refers to the parent of the commit pointed to by the commit pointer preceding it. If a commit has multiple parents, you can use ^n to refer to the nth one)

We all learn by example, so let's consider a possible scenario. Say we have a git repository with 2 branches, master and testing. Say the master branch has 2 commits with SHA keys 0af4780... (=HEAD) and 326399d..., and say the testing branch has 3 commits. Say the current branch is testing. Here are some examples in the context of that scenario:
    a. 0af4780... = HEAD = self explanatory
    b. HEAD~1 = commit 326399d...
    c. testing^^ = the oldest commit in the testing branch

Thing #5: Alternate usages
In commands like git diff, which make sense for both commits and files, the commit pointers passed to them can be followed by :file_path, if you wish to compare 2 past versions of a file instead of 2 whole commits. For example, say we have a file called blah.c in the lib/ directory in our repository (which happens to be huge), and we want to see what changes were made to it between the second last and fourth last commits. We could do something like:

git diff HEAD~1:lib/blah.c HEAD~3:lib/blah.c

Another interesting thing is commit ranges, which you can pass to commands like git log to see what has changed in that range of commits. They have the form commit_pointer1..commit_pointer2.

If this got you interested, you really should read this amazing PDF on the internals of git.

----
If you liked this article, why not extend your appreciation by following me or Rajat on Twitter?

3 comments:

  1. It is a pretty good topic of discussion, and like all your articles, very well written.

    Through some bitter experiences, I have learnt that knowing Git well enough is crucial ;-); this could be a good starter for me.

    ReplyDelete
  2. I just came across this
    http://thread.gmane.org/gmane.comp.version-control.git/57643/focus=57918

    In this post, Linus defends why C was a better option for Git than C++ (and in the way tells us all why not to use C++ ;-) )

    Intrigued by this, I ended up reading on Wikipedia that git was developed by LINUS TORVALDS. That was news to me; what about you ?

    ReplyDelete
  3. I've already seen that link. And I also knew Git was developed by Torvalds. He's a genius, that guy. He's well known for Linux and Git, but few others recognize his third contribution: his strategy of software development incorporating ideas from the users and the public. http://linux.slashdot.org/story/11/06/16/1322220/Linus-Other-Gift-to-the-World

    ReplyDelete