Useful Git aliases
Posted on
In what’s apparently turning into a series of posts about how I use Git, I thought I might post a few of the aliases I use. Adding aliases to Git effectively allows you to define your own simple sub-commands, which invoke one of the built in sub-commands, another alias, or some external command.
I’ll start with a quick run down of how to create aliases, but if you’re already familiar with that then you should skip ahead to my aliases.
Creating aliases
As with all Git configuration, you can create aliases from the command line
with the
git config
command or modify the configuration files directly.
To create an alias from the command line you use:
git config --global alias.foo 'status --short'
This will create a global alias foo
such that
git foo
is now the equivalent of
git status --short
.
If the --global
flag is omitted then the alias is only created
for the current repository.
If you want the alias to run an external shell command, instead of a
Git sub-command, then you prefix the alias with a !
:
git conifg --global alias.bar !echo
You’ll also need this prefix if you want an alias that starts with a Git sub-command, but then pipes the output into some other program (there are some examples of this later).
To create the same aliases by editing the configuration files you would add the following lines:
[alias]
foo = status --short
bar = !echo
For a global alias this goes in ~/.gitconfig
, and for a
repository specific alias it goes in .git/config
. I’ll use
this format for the examples that follow.
When you use your aliases, any command line arguments you
provide will be passed on to the aliased command. For example, with the
aliases configured above git foo --branch
is the same as
git status --short --branch
.
A few of my favourite aliases
Pretty graphs
[alias]
graph = log --all --graph --decorate --oneline -n30
This alias shows the last 30 commits from all branches laid out in a graph,
and decorated with branch and tag names. If
git log
gets more
than one -n
parameter it will use the last one, which means
you can easily change the number of commits shown in the graph when you
want more or less context (e.g. git graph -n5
).
I used to use GitX to visualise
the commit graph, but I was usually trying to quickly get my
bearings before I issued another command, so having the graph in my terminal
to refer back to is more useful than switching away to another app to see
it (I have my
Correction: As
Matthew Somerville
pointed out in the comments, the default pager is core.pager
set to cat
, so Git doesn’t pipe everything into
less
and the output stays visible when I start typing the next
commandless -FRSX
,
which means the output is still visible after quitting less).
Seeing where I’m up to
[alias]
cb = !git branch | grep ^* | cut -d' ' -f2
sb = !ls .git/refs/remotes/*/$(git cb) | cut -d/ -f4,5 | \
xargs git show-branch $(git cb)
These two commands work together to show the differences between my
currently checked out branch (found by git cb
), and the branches
with the same name on all remotes. For example, if I have the
master branch checked out in a repository with remotes called
heroku and github, git sb
is the (much shorter) equivalent of
git show-branch master heroku/master github/master
.
Rather than using
git pull
I prefer to use
git fetch
and then manually
merge
or
rebase
my changes. I find
the time between fetching and merging very useful: I
can see what other developers have been working on, spot potential conflicts,
and generally keep up with what’s changing in the codebase. My
git sb
alias gives me a quick overview of the changes with a
single command.
Incidentally, if you’ve not used
git show-branch
I’d definitely recommend trying it out. It’s become one of the Git
sub-commands I use most often.
GitHub
I’m cheating a little here, this one started life as an alias but it got
so complex that I re-wrote it as a Bash script. A handy feature of
Git’s architecture is that any executable on your path with a name that
starts with git-
can be executed as a Git sub-command. In this
case my file is called git-hub
, so I can execute it by running
git hub
:
#!/bin/bash
github_remote=$(git remote -v | grep -Eo 'github.com[:/][^.]+' | head -1)
if [ -z $github_remote ]
then
echo "No GitHub remote"
exit
fi
github_url="https://${github_remote/://}/"
if [ ! -z $1 ]
then
sha=$(git rev-parse $1)
github_url="${github_url}commit/$sha"
fi
open $github_url
You can use this in two ways. Without any arguments (git hub
) it
will just open the GitHub page for the repository. When an argument is given
it will attempt to convert that argument into a commit ID (using
git rev-parse
)
and then open the GitHub page for that specific
commit, for example git hub origin/master~3
.
I find this very useful when combined with my git sb
alias;
when I’m reviewing new commits before I merge in my own changes I can
easily open up a specific commit’s GitHub page to leave a comment or read
in more detail later.
Finding things
[alias]
rgrep = !git grep
This alias runs
git grep
from the root directory of the repository, so you can search the whole tree
for something even if you’re currently in a subdirectory.
I wrote this one recently as an answer to a
Stack Overflow question,
so it’s not exactly one of my everyday tools, but it does demonstrate a
useful property of aliases: Any alias to an external command (i.e. any
alias that starts with !
) is executed from the repository’s
root directory regardless of the current working directory.
That’s all folks
I find these aliases make Git much more useful and enjoyable to use, hopefully you will too. You can find all of the examples in a Gist on GitHub for reference, easy copying and pasting, or suggested additions and improvements.
4 Comments
Matthew Somerville commented on :
"(I have my core.pager set to cat, so Git doesn’t pipe everything into less and the output stays visible when I start typing the next command)" - I thought git by default called less with -FRSX; certainly, I don't get anything disappearing when I hit q in default git, no special pager set.
You might want to investigate git symbolic-ref HEAD rather than parsing the output of git branch - something like "git symbolic-ref HEAD 2>/dev/null" and then strip off refs/heads/ or set to "detached HEAD" if no output.
And I'm sure you've seen this - http://www.jukie.net/bart/blog/pimping-out-git-log is what I use by default for my pretty graphs.
George Brocklehurst responded on :
Thanks Matthew.
I wasn't very clear about my pager settings; I was referring to the output disappearing after I'd hit q in less. Most of the time that isn't what I want, I'd still like to be able to glance up and see the output later.
Using symbolic-ref sounds simpler than parsing the branch output, I'll look into it.
Matthew Somerville commented on :
Obviously I haven't been clear either, as that's what I meant :-) No output disappears for me when I hit q with default git behaviour; it all stays there so I can see the output. This is because git calls less with -X which stops any page clearing your terminal might do with the te termcap. (You can set the LESS environment variable to the options you want less to use by default, too, so that it never happens with less.)
Philip Möjbro commented on :
Now I'm `cb`ing and `sb`ing like never before.