With aliases, you can avoid typing the same commands over and over again. Aliases were added in Git version 1.4.0.
Table of contents:
To show how to use aliases, suppose you wish you could write git ci instead of git commit. You can achieve this by adding the following section to ~/.gitconfig:
[alias]
ci = commit
Some people are uncomfortable editing the config file themselves. They can edit the config by calling git config alias.ci commit instead.
If you want to have the alias available everywhere on your local machine, you can either
- edit ~/.gitconfig, or
- use the --global flag:
git config --global alias.ci commit
If you want to be able to say git lc to list all new commits after you fetched, with stats, but excluding merges, add this alias:
[alias]
lc = log ORIG_HEAD.. --stat --no-merges
Note that this is dangerous!
[alias]
undo=reset --hard
Right from the start, aliases were meant as an easy way to avoid really simple, really short scripts. Therefore, they can take arguments, which are appended to the command.
That’s right. The simplest alias on this page takes arguments, so you can call:
$ git ci -m message file1 file2 dir1
Here’s how to create an alias git llog that will behave just like git log, but will display dates in your local timezone.
[alias]
llog = log --date=local
These two aliases wrap commonly used options to git diff, and accept the full range of arguments that diff accepts:
[alias]
changes=diff --name-status -r
diffstat=diff --stat -r
Since version 1.5.0, Git supports aliases executing non-git commands, by prefixing the value with “!”:
Since gitk does not follow the common form git-, and is no builtin either, you have to use the prefix “!” to call gitk from an alias:
[alias]
gitkconflict = !gitk --left-right HEAD...MERGE_HEAD
To see what new commits have been created by the last command (typically after a “git pull”) :
[alias]
new = !sh -c 'git log $1@{1}..$1@{0} "$@"'
Use like
git pull
git new
git new origin/master
A concatenation of git programs can also be achieved by the prefix “!”:
[alias]
stsh = !CURRENT=$(git symbolic-ref HEAD) && git symbolic-ref HEAD refs/heads/stash && git commit -a -m stashed && git checkout $CURRENT
This fires up a git daemon for the repo you are currently in:
[alias]
serve = !git daemon --reuseaddr --verbose --base-path=. --export-all ./.git
It makes use of the fact that (currently, as of git 1.5.6.1) non-git alias are executed from the top-level dir of a repo. The simpler version
[alias]
serve = daemon --reuseaddr --verbose --base-path=. --export-all ./.git
works only when called from the top-level dir. In any case, you can connect simply by _git ls-remote _ etc.
There’s no way to tell git remote update
to prune stale branches, and git remote prune
does not understand \--all
. So here is an alias to do the job:
[alias]
prune-all = !git remote | xargs -n 1 git remote prune
Starting with version 1.5.3, git supports appending the arguments to commands prefixed with “!”, too. If you need to perform a reordering, or to use an argument twice, you can use this trick:
[alias]
example = !sh -c 'ls $2 $1' -
The final dash is so that arguments start with $1, not with $0.
NOTE: later on the page presents a nice trick using a shell function instead of _sh -c. Most aliases could be converted to use that style._
Here are two aliases suggested on the mailing list by Junio Hamano:
[alias]
whois = "!sh -c 'git log -i -1 --pretty="format:%an <%ae>n" --author="$1"' -"
whatis = show -s --pretty='tformat:%h (%s, %ad)' --date=short
Try then by yourself! The first takes the name of a person or their email address. The second takes a commit name.
When debugging builtins, you often use gdb to analyze the runtime state. However, you have to disable the pager, and often you have to call the program with arguments. If the program to debug is a builtin, you can use this alias:
[alias]
debug = !GIT_PAGER= gdb --args git
Suppose you want to debug git log HEAD..next, you can call gdb by git debug log HEAD..next now.
If upstream applied a slightly modified patch, and you want to see the modifications, you should use the program interdiff of the patchutils package. Then you can add the alias intercommit:
[alias]
intercommit = !sh -c 'interdiff <(git show $1) <(git show $2) | less -FRS' -
This accept two commits, typically the first coming from upstream (e.g. origin/master) and the second coming from your own topic branch.
Here is a collection of some Git users’ aliases. If you know a simpler way to achieve the same, please add some notes.
When you want to see just the differences of one function in one file in two different commits, you can do this:
$ git config alias.funcdiff '!sh -c "git show "$0:$2" | sed -n "/^[^ t].*$3[ t]*(/,/^}/p" > .tmp1 &&
git show "$1:$2" | sed -n "/^[^ t].*$3[ t]*(/,/^}/p" > .tmp2 &&
git diff --no-index .tmp1 .tmp2"' -
The idea is to create two temporary files which contain only the function, and call git diff on them. Use this alias this way: _git funcdiff _.
If anyone knows of a way to do this that gives prettier output, please do share :-)
If you’ve eg. moved around a bunch of lines in data files, and want a diff of what else happened, you can use the following alias
[alias]
sortdiff = !sh -c 'git diff "$@" | grep "^[+-]" | sort --key=1.2 | uniq -u -s1'
(sort –key=1.2 ignores the leading + or -, as does -s to uniq, while -u removes any consequtive lines; I would grep -v '^(+++ b|--- a)'
but that gave me “bad config file” for some reason)
You could probably include line numbers here too, by using the field features of sort/uniq
You get a lot of merge conflicts and want to quickly solve them using an editor and then add the conflicted files. Try this:
[alias]
edit-unmerged = "!f() { git diff --name-status --diff-filter=U | cut -f2 ; }; vim `f`"
add-unmerged = "!f() { git diff --name-status --diff-filter=U | cut -f2 ; }; git add `f`"
You should replace “vim” by your favorite editor.
Then just use
$ git edit-unmerged
... edit ...
$ ... test ...
$ git add-unmerged
$ git commit # or git rebase --continue or whatever
[alias]
graphviz = "!f() { echo 'digraph git {' ; git log --pretty='format: %h -> { %p }' "$@" | sed 's/[0-9a-f][0-9a-f]*/"&"/g' ; echo '}'; }; f"
This produces output that can be displayed using dotty, for example:
$ git graphviz HEAD~100..HEAD~60 | dotty /dev/stdin
$ git graphviz --first-parent master | dotty /dev/stdin
Note how defining a function eliminates the need to use sh -c.
This approximates what happens with hg/darcs record (i.e. ask interactively which patch hunk to commit, and then do the commit) :
[alias]
record = ! sh -c '(git add -p -- $@ && git commit) || git reset' --
It will not only do ‘git add -p’ (with an optional file list), but it will also immediately do the commit. Upon abandonment of either the add or the commit it will reset the index.
[alias]
st = status
ci = commit
br = branch
co = checkout
df = diff
dc = diff --cached
lg = log -p
who = shortlog -s --
If you use gitk in your git sessions quite frequently, you have perhaps misused your history and done:
$ gitk foo..bar
$ gitk checkout baz
Using git k
instead of gitk
may solve your problem:
[alias]
k = !gitk
Now that you know all about aliases, it might be handy to define some, using an alias:
[alias]
alias = "!sh -c '[ $# = 2 ] && git config --global alias."$1" "$2" && exit 0 || echo "usage: git alias " >&2 && exit 1' -"
then define new aliases with:
$ git alias new_alias original_command
Note that you must enclose the entire original_command in single or double quotes, so that the shell interprets it as a single expression.
Going further, to get a list of your defined aliases:
[alias]
aliases = !git config --get-regexp 'alias.*' | colrm 1 6 | sed 's/[ ]/ = /'
This can be useful to use send-email on the output of git format-patch –stdout
[alias]
send-mbox = "!bash -c 'eval f=\$$#; eval set -- `seq -f"\$%.0f" 1 $(($#-1))`; mkdir .mboxsplit || exit; trap "st=\$?; rm -rf .mboxsplit; exit \$?" 0 INT TERM; if last=`git mailsplit -d4 -o.mboxsplit -b -- "$f"`; then echo Found $last messages in "$f"; git send-email "$@" .mboxsplit; fi' -"
Most of the complication is because the last argument must be passed to git mailsplit, while the others must be passed to git send-email.
Here are some aliases to help git-svn users migrate away from SVN. Be careful though - trying to completely recreate an SVN environment with aliases will cause problems when commands don’t quite do what you expect.
[alias]
st = status
# SVN-compatible versions of commands
# "foo-svn" is used here instead of "svn-foo" so that it's suggested when people tab-complete "git fo..."
cherry-pick-svn = !GIT_EDITOR='sed -i /^git-svn-id:/d' git cherry-pick -e
branch-svn = svn branch
merge-svn = merge --squash
push-svn = svn dcommit
# The next two lines are recommended, as their strengths outweigh their weaknesses.
# Strength: they make transitioning from SVN easier
# Weakness: they make teaching `git pull` harder when you move to git on the server
# Weakness: they encourage people to think that rebasing is a safe default
up = svn rebase
update = svn rebase
# The next line *is not* recommended, as its weaknesses outweigh its strengths.
# Strength: it makes transitioning from SVN easier
# Weakness: it makes teaching `git add`, `git commit -a`, the index, etc. harder
# Weakness: it encourages people to think that a git commit is analogous to an SVN commit
#ci = commit
There is my git lg alias:
[alias]
lg = log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit --date=relative
Full details are in my “pimping out git log“ blog entry.
If you use shortened hashes, sometimes you may encounter a collision. The following alias prints out all commits whose hash start with given string.
[alias]
abbr = "!sh -c 'git rev-list --all | grep ^$1 | while read commit; do git --no-pager log -n1 --pretty=format:"%H %ci %an %s%n" $commit; done' -"
Suppose you have two aliases defined like so:
[alias]
oneline ="!_() { $(test $# -eq 0 && echo xargs -L1) git log --no-walk --decorate --oneline "$@"; }; _"
tips = "!_() { t=$(git rev-list --no-merges --max-count=1 "$@"); if test -n "$t"; then echo $t; _ "$@" ^$t; fi; }; _"
Then:
git tips origin/pu ^origin/next | git oneline
might show something like this:
9dcca58 filter-branch.sh: de-dent usage string
704c335 On Cygwin support both UNIX and DOS style path-names
1c460f9 t3030: fix accidental success in symlink rename
9e81372 test-path-utils: Add subcommand "prefix_path"
ad733bd revert: Propagate errors upwards from do_pick_commit
76cf946 fixup! xdiff/xhistogram: rework handling of recursed results
df6a9c7 fixup! describe: Refresh the index when run with --dirty
c9f57a0 squash! ls-files: fix pathspec display on error
a1288bc add--interactive: add option to autosplit hunks
365b78a t5800: point out that deleting branches does not work
c997182 limit "contains" traversals based on commit generation
914b6fb doc/fast-import: document feature import-marks-if-exists
b792c06 branch -v: honor core.abbrev
b166408 mergetool: Don't assume paths are unmerged
b29d76f merge: mark the final "Merge made by..." message for l10n
942cf39 receive-pack: Allow server to refuse pushes with too many objects
which is a list of the tips of linear sequences of commits that are in pu, but not in next.
While the empty tree sha1 4b825dc642cb6eb9a060e54bf8d69288fbee4904 is known to git, you may need to generate it.
[alias]
empty-tree-sha1 = hash-object -t tree /dev/null
Diffing against the empty tree can be useful for things like generating a patch which represents the creation of an entire slice of your working tree (squashing the effect of all commits so far into a single patch):
$ git diff -p $(git empty-tree-sha1) some-interesting-subdir/
You can even get a complete listing of any whitespace violations in the current working tree:
$ git diff --check $(git empty-tree-sha1)
Update: This alias is unnecessary.
git diff A...B
does the same thing.
To see the changes in a branch since it was forked from another branch, or since the last merge with the origin branch, you can add this ‘forkdiff’ alias to $HOME/.gitconfig:
[alias]
forkdiff = !bash -c 'git diff $(git merge-base "$1" "$2") "$2" "${@: 3}" ' -
It uses git-merge-base to determine the fork-point (the commit that is common to both the branches) and does a git-diff between that commit and the second branch.
git forkdiff [git-diff-options]
git forkdiff origin/master my_forked_branch --stat
In some scenarios it’s necessary to untrack a particular file in say a production branch to avoid developer content spilling into it. As a rare activity it can be difficult to locate in the manuals. The git rm man page ‘Discussion’ section gives additional details regarding the blobbing of filenames.
[alias]
untrack = rm --cache --