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:
- Pro Git by Scott Chacon and Ben Straub
- Github's git tutorial
- Git Immersion
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:
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...