Git tips

I've been using git for a few years now. Initially I was a little reluctant to pick it up, however in retrospect I'm glad I did.

This post is going to go over a few tips I wish I knew when I was starting out, if you're new to git you might want to look at some of the following resources instead:

Checking for trailing whitespace

It's very easy to accidently leave trailing whitespace in your files. Thankfully git makes it easy to check for this before you commit anything. To do this you just need to run git diff --check:

$ git diff --check
example.md:1: trailing whitespace.
+Hello world 
example.md:3: new blank line at EOF.

You can also set git up to automatically run this check by creating a pre-commit hook. To do this create a script called .git/hooks/pre-commit with the following contents:

#!/bin/sh
git diff --check --cached

Note: You need to used the --cached option if you want to compare changes which have already been staged.

Verbose commits

By default when you make a commit you will have a message like this in your favourite editor:

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# Explicit paths specified without -i or -o; assuming --only paths...
# On branch example
# Changes to be committed:
#       modified:   example.md

That's great if you remember what you changed, however it's very easy to forget exactly what you changed. One way around this is to use the verbose option (-v). This will insert a unified diff at the bottom of your commit message for reference.

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch example
# Changes to be committed:
#       modified:   example.md
#
# ------------------------ >8 ------------------------
# Do not touch the line above.
# Everything below will be removed.
diff --git a/example.md b/example.md
index 61408ec..88fbc46 100644
--- a/example.md
+++ b/example.md
@@ -1,2 +1,2 @@
-hello world
+Hello world
...

Pretty git graphs

Once you start regularly branching, merging and rebasing it gets very easy to lose track of where you are. A little while ago I stumbled across a stack overflow question asking about tools to make printable images of git history. The top answer suggests setting up a few aliases to call git log in a few different ways. The main command I use is:

git log --graph --abbrev-commit --decorate --date=relative --format=format:'%C(bold blue)%h%C(reset) - %C(bold green)(%ar)%C(reset) %C(white)%s%C(reset) %C(dim white)- %an%C(reset)%C(bold yellow)%d%C(reset)' --all

This is obviously a little long to type over and over so I have it aliased to git lg. You can do this by running:

git config --global alias.lg "log --graph --abbrev-commit --decorate --date=relative --format=format:'%C(bold blue)%h%C(reset) - %C(bold green)(%ar)%C(reset) %C(white)%s%C(reset) %C(dim white)- %an%C(reset)%C(bold yellow)%d%C(reset)' --all"

Once you've got an alias set up you can run git lg and you should get output that looks something like this:

pretty git graph example output

The git log command has quite a few options, it's well worth spending some time going through the documentation and experimenting with a few of the available options.

Squashing commits

Unlike some version control systems commits are not automatically pushed upstream. This is nice because you can commit small changes often and easily see what you've done.

The only problem with this approach is you soon end up with a commit history that looks something like this:

* b4b0acf - (2 seconds ago) Correct spelling mistake - Floatingoctothorpe (HEAD -> example)
* 86d323e - (9 minutes ago) Fix another typo... - Floatingoctothorpe
* 0a3a74d - (13 minutes ago) Correct syntax error - Floatingoctothorpe
* 46740c6 - (25 minutes ago) Fix typo - Floatingoctothorpe
* 0eefcb6 - (84 minutes ago) Add really awesome feature - Floatingoctothorpe
* 94694d1 - (2 hours ago) First commit - Floatingoctothorpe (master)

Thankfully it's pretty straightforward to squash unwanted commit messages together. For example to combine the commits made since master you can run git rebase -i master. This will drop you into an editor where you can change unwanted commits to f. Git will then discard the commit message for each commit and merge the change into the previous commit.

pick 0eefcb6 Add really awesome feature
f 46740c6 Fix typo
f 0a3a74d Correct syntax error
f 86d323e Fix another typo...
f b4b0acf Correct spelling mistake

Once your done the change log should be a little shorter:

* 050fce8 - (1 hours ago) Add really awesome feature - Floatingoctothorpe (HEAD -> example)
* 94694d1 - (2 hours ago) First commit - Floatingoctothorpe (master)

Note: A word of warning, when you squash commits you are effectively discarding the previous commits. This is fine on your local topic branch, however doing this on the master branch of a group project is a good way to make enemies...