Random learnings and other thoughts from an unashamed geek

My Favourite Git Commands II: Viewing Changes/History

| Comments

This is part 2 in my Favourite Git Commands series.

Viewing Changes/History

A distributed version control system is very useful at helping you to track down bugs, revert to previously working versions, and especially for collaborating with other (remote) users. But you can lose many of these benefits if you don’t keep your revision history tidy.

I find the best way to do this is to keep each commit small and focussed on just one feature. Unrelated changes and fixes should go in their own commits, even if this means that you’re committing just one line: “fix typo in random number generator.”

Keeping a tidy revision history is especially useful if you ever need git bisect to help you track down a bug a number of commits ago - when you find the commit that introduces the bug it should be easy to see what line caused it because there won’t be any unrelated lines in that commit.

To help you keep a tidy revision history you should always be aware exactly what you’re committing. When you pull changes from another user you should always look through what they’ve done (which you can do with git show) so put yourself in their shoes: when they look at your code they want to be able to scan through the changes as fast as possible, and not have to try and understand how unrelated changes fit in to implementing a specific feature. They especially don’t want to see you adding debugging lines in one commit, then removing them in a later commit, then adding them again - this is noise that will get in the way of their timely understanding of your changes.

git diff

You should be typing this many times a day, it shows you at a glance what lines you have changed in your working copy. A great way of reviewing just those lines for typos or bugs - be your own pair programming partner!

git diff --ignore-space-change

Or git diff -b for short - this is particularly useful if you’ve changed a lot of whitespace (e.g. you’ve decided to switch tabs for 2 spaces throughout) but want to make sure you didn’t accidentally edit any lines of code.

It’s also useful if you’re using a whitespace sensitive language (e.g. Python or CoffeeScript) and you know you indented a bunch of old code, but just want to see your new modifications.

Also of use git diff --ignore-all-space / git diff -w which ignores the difference between a line with whitespace and a line without.

Either way, if you use this then I’d still advise you use vanilla git diff before committing, as this is what your collaborators will see when they review your code.

git diff --staged

This command shows you the changes you have staged for the next commit. I do this before almost every commit to check I’m only committing exactly what I want to commit, and when I forget to do this, I generally regret it.

git show HEAD~3

When you pull down someone elses changes, or before modifying history, it’s generally a good idea to know what happened in each commit. I use git show HEAD to review the last commit, this is very useful and sometimes reveals that I added more than I meant to (or less). You can use git show HEAD^^^ or git show HEAD~3 to view the 4th commit ago if you want to go back further. (Note: each ^ means “this commit’s first parent” so more ^s means further back. If your history is non-linear you need to be more careful that you’re reviewing all the relevant commits.)

git blame

Very useful for figuring out which commit a particular bug or typo came from (so you can edit that bug out of history and no-one will ever know: see part 3…). Try it now: git blame [filename] - pretty neat, isn’t it? Also useful for debunking “it couldn’t possibly have been me that wrote that messy code, it must have been you!”

git log

Of course, it’s generally a good idea to keep an eye on your git log too, and this is why you want your commit messages to be short and to the point. git log is a great command, and very flexible, but it has so many options many people simply use git log and miss out on it’s power!

Here’s a couple of my favourite git log aliases and how to add them to your own configuration.

git lg

This is my preferred way of viewing history. It inherits from a number of other peoples’, sorry I can’t remember their names right now.

To add it:

git config --global alias.lg "log --graph --pretty=format:'%Cgreen%h%Creset -%Creset %s%C(yellow)%d %Cblue(%aN, %cr)%Creset' --abbrev-commit --date=relative"

git heir

Tells you the hierarchy of your various git branches.

To add it:

git config --global alias.heir "log --all --graph --decorate --oneline --simplify-by-decoration"