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"