Aliases

From Git SCM Wiki
Jump to: navigation, search

OBSOLETE CONTENT

This wiki has been archived and the content is no longer updated. Please visit git-scm.com/doc for up-to-date documentation.

Aliases

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:

Contents



Introduction

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

Simple

A shortcut for seeing the fetched commits

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

Undo the last commit

[alias]
        undo=reset --soft HEAD^

Aliases with arguments

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.

'ci'

That's right. The simplest alias on this page takes arguments, so you can call:

$ git ci -m message file1 file2 dir1

Shortcut for displaying dates in your local timezone

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

Simple diff wrappers

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

Use of quotes inside an alias

In more complex aliases, the quoting rules can also appear complex. One issue isn't with Git's alias mechanism, but a quirk of how "sh -c" works, taking the first non-option argument as $0, not $1.

Some of the key points are discussed in the thread https://lore.kernel.org/git/CAHMHMxVajKxjBweG=mps0gLwE1o8M69DvPb1iUQYgLXx0VO5AA@mail.gmail.com/

Advanced

Since version 1.5.0, Git supports aliases executing non-git commands, by prefixing the value with "!":

Calling "gitk"

Since gitk does not follow the common form git-<name>, 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

What's new?

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

Poor man's "stash"

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

Serve repo on the spot

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 git://127.0.0.1/ etc.

Prune all your stale remote branches

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

Advanced aliases with arguments

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.

Spelunking of the project's history

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.

A 'debug' alias to help debugging builtins

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.

Calling "interdiff" between commits

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.

Collection of aliases by Git users

Here is a collection of some Git users' aliases. If you know a simpler way to achieve the same, please add some notes.

Getting the diff of only one function

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 <old-rev> <new-rev> <path> <function>.

simple diff ignoring line number changes

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

Editing/adding conflicted files

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

Use graphviz for display

[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.

Cherrypick Style Recording

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.

Shortcuts

[alias]
    st = status
    ci = commit
    br = branch
    co = checkout
    df = diff
    dc = diff --cached
    lg = log -p
    who = shortlog -s --

git k

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

alias

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 <new alias> <original command>\" >&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/[ ]/ = /'

Sending multiple messages from a single file

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.

SVN-like aliases

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

Getting pretty logs

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.

Finding the right commit

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' -"

Listing the tips of branches in pu that are not in next

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.

Obtaining the Empty Tree SHA1

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)

Getting the diff of a branch since it forked from another branch, or since the last merge

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.

Usage

git forkdiff <forked from branch> <forked branch> [git-diff-options]

Example

  git forkdiff origin/master my_forked_branch --stat

Untrack a file

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 --

Checkout recursive submodules

Checking out a repo and it's submodules is not part of the regular 'git checkout' command. Normally you need a two command sequence

git checkout *oldcommit*
git submodule update --recursive

These can be combined using the tricks above, and using '&&' for command chaining to prevent losing work when you mistype the submodule name, into a simple alias

[alias]
        co-recurse = !sh -c 'git checkout $1 && git submodule update --recursive' -



Personal tools