Instantly share code, notes, and snippets.

What would you like to do?
The Ultimate Git Alias Setup

The Ultimate Git Alias Setup

If you use git on the command-line, you'll eventually find yourself wanting aliases for your most commonly-used commands. It's incredibly useful to be able to explore your repos with only a few keystrokes that eventually get hardcoded into muscle memory.

Some people don't add aliases because they don't want to have to adjust to not having them on a remote server. Personally, I find that having aliases doesn't mean I that forget the underlying commands, and aliases provide such a massive improvement to my workflow that it would be crazy not to have them.

The simplest way to add an alias for a specific git command is to use a standard bash alias.

# .bashrc

alias s="git status -s"

The disadvantage of this is that it isn't integrated with git's own alias system, which lets you define git commands or external shell commands that you call with git <alias>. This has some nice advantages:

  • integration with git's default bash completion for subcommand arguments
  • ability to store your git aliases separately from your bash aliases
  • ability to see all your aliases and their corresponding commands using git config

If you add the following code to your .bashrc on a system with the default git bash completion scripts installed, it will automatically create completion-aware g<alias> bash aliases for each of your git aliases.

if [ -f /etc/bash_completion ] && ! shopt -oq posix; then
    . /etc/bash_completion                                                                                                                                                                

function_exists() {
    declare -f -F $1 > /dev/null
    return $?

for al in `__git_aliases`; do
    alias g$al="git $al"
    complete_func=_git_$(__git_aliased_command $al)
    function_exists $complete_fnc && __git_complete g$al $complete_func

The main downside to this approach is that it will make your terminal take a little longer to load.

My aliases

Here are the aliases I use constantly in my workflow. I'm lazy about remembering many other aliases that I've decided I should be using, which this setup is great for because I can always list them all using gla.

    # one-line log
    l = log --pretty=format:"%C(yellow)%h\\ %ad%Cred%d\\ %Creset%s%Cblue\\ [%cn]" --decorate --date=short

    a = add
    ap = add -p
    c = commit --verbose
    ca = commit -a --verbose
    cm = commit -m
    cam = commit -a -m
    m = commit --amend --verbose
    d = diff
    ds = diff --stat
    dc = diff --cached

    s = status -s
    co = checkout
    cob = checkout -b
    # list branches sorted by last modified
    b = "!git for-each-ref --sort='-authordate' --format='%(authordate)%09%(objectname:short)%09%(refname)' refs/heads | sed -e 's-refs/heads/--'"

    # list aliases
    la = "!git config -l | grep alias | cut -c 7-"

See Must Have Git Aliases for more.


This comment has been minimized.

VinnyFonseca commented Aug 26, 2014

I have 3 aliases which are pretty helpful, maybe you'd like to include them?

rao = remote add origin
ac = !git add . && git commit -am
pushitgood = push -u origin --all


git init
git rao https://url-here.git
git ac "Message"
git pushitgood

and you have a working repo with set upstream. git ac is still very useful throughout development while the others are for fist time setup only.


This comment has been minimized.

cottsak commented Jan 28, 2015

That ac one is gold


This comment has been minimized.

adarshk7 commented May 20, 2015

These are quite useful to me, so I'll share them!

undo-commit = reset --soft HEAD~1

This one removes all the branches that have been merged to the current branch that you are in.
If you use this from master then all branches merged to master are deleted. This reading git branch easier.
clean-merged = !git branch --merged | grep -v \"\\*\" | xargs -n 1 git branch -d


This comment has been minimized.

zsoobhan commented Aug 21, 2015

A variation on pushitgood
po=!echo 'Ah push it' && git push origin && echo 'PUSH IT REAL GOOD'


This comment has been minimized.

DavidWiesner commented Nov 25, 2015

I´ve git an issue when add this to the .bashrc. I got
bash: __git_aliases: command not found
the problem is the __git_aliases command will be loaded after first use of git auto-completion - after first git <TAB><TAB>. So you will need to force include this command. On my system this will be in /usr/share/bash-completion/completions/git
Just add include this file to the .bashrc like this:

if [ -f /etc/bash_completion ] && ! shopt -oq posix; then
    . /etc/bash_completion
    . /usr/share/bash-completion/completions/git

This comment has been minimized.

embix commented Sep 1, 2016

If you want your gitk ordered and possibly include orphan commits, e.g when you deleted the wrong branch pointer and want it back:

ka = !gitk --all --date-order &
orphank = !gitk --all --date-order `git reflog | cut -c1-7`&

And a bonus for those having to work with submodule infected repositories:

sobmodules = submodule update --init --recursive

This comment has been minimized.

k3n commented Sep 1, 2016

In case anyone else stumbles over it like I did, you place the aliases (e.g. the snippet above that begins with [alias]) into your .gitconfig file.


This comment has been minimized.

shreyasbharath commented Sep 6, 2016

This is a useful one for me, it allows me to rebase with the tracking branch even if I have uncommitted changes. Credit goes to @cmsolomon.

rb = "!f() { \
            echo fetching...; \
            git fetch; \
            if [ $? -eq 0 ]; then \
                last_status=$(git status --untracked-files=no --porcelain); \
                if [ \"$last_status\" != \"\" ]; then \
                    echo stashing local changes...; \
                    git stash; \
                else \
                    echo nothing to stash...; \
                if [ $? -eq 0 ]; then \
                    echo rebasing...;\
                    git rebase;\
                    if [ $? -eq 0 ]; then \
                        if [ \"$last_status\" != \"\" ]; then\
                            echo applying stashed changes...;\
                            git stash pop;\
                            if [ $? -ne 0 ]; then \
                                echo STASH POP FAIL - you will need to resolve merge conflicts with git mergetool; \
                            fi; \
                        fi; \
                    else \
                        echo REBASE FAILED - you will need to manually run stash pop; \
            fi; \
            if [ $? -ne 0 ]; then \
                echo ERROR: Operation failed; \
            fi; \
        }; f"

This comment has been minimized.

shhac commented Sep 9, 2016

When I'm working in my own branches (never do this on someone else's branch) I occasionally will want to rewrite my history, so I use the following git alias

git config --global alias.ria '!git rebase -i `git merge-base HEAD master`'

Interactive rebase onto the branch point between the current branch and master, no worries about conflicts for a merge onto a future master, you can clean up your branch history and then decide what to do with it after.

A few other really useful aliases,

Check out the last branch you were on

git config --global alias.col 'checkout @{-1}'

Some submodule related aliases

git config --global alias.sup 'submodule update --init --recursive'
git config --global alias.coz '!f(){ git checkout "$@" && git submodule update --init --recursive; }; f'
git config --global alias.colz '!git checkout @{-1} && git submodule update --init --recursive'
git config --global alias.comz '!git checkout master && git submodule update --init --recursive'
git config --global alias.plz '!git pull && git submodule update --init --recursive'
git config --global alias.clz 'clone --recursive'

If you're not sure how any of there work I would not recommend adding them as an alias


This comment has been minimized.

shreyasbharath commented Sep 12, 2016

This one's a really useful alias for me. It allows you to diff the last commit for a given file.

Usage (no matter where you are in the repo) -

git diff-file-last-commit File.cpp

This opens your configured difftool with the changes to File.cpp in the last commit it was touched.

diff-file-last-commit = "!f() { \
            project_root_dir=$(git rev-parse --show-toplevel); \
            echo finding full file path of $1 in $project_root_dir; \
            filepath=$(find $project_root_dir -type f -name $1); \
            echo full file path $filepath; \
            last_modified_commit_hash=$(git rev-list -1 HEAD $filepath); \
            echo last commit file modified $last_modified_commit_hash; \
            git difftool $last_modified_commit_hash^ $filepath; \
       }; f"

I'd love to enhance this so it does auto-completion of files etc., will do when I get the time.


This comment has been minimized.

HaleTom commented Sep 24, 2016

@cmsolomon do you have a script to quote multi-line strings like the code that you were mentioned in above?

I've got one for single line strings (just paste in anything that you would type at the sh prompt)

quote-string = "!read -r l; printf \\\"!; printf %s \"$l\" | sed 's/\\([\\\"]\\)/\\\\\\1/g'; printf \" #\\\"\\n\" #"

To undo the quoting, use the la alias above, or my better one which allows grep-ing:

la = !git config --list | grep ^alias\\. | cut -c 7- | grep -Ei --color \"$1\" "#" # List aliases


This comment has been minimized.

janephilipps commented Dec 6, 2016

This is great! I have a couple of others that I use:

com="checkout master"
stl="stash list"
rl="ref log"

This comment has been minimized.

tbass134 commented Dec 13, 2016

i use this when zipping the current branch with the name of the zip file as the current tag. Its been useful for uploading to Elasticbeanstalk

currentTag = tag --points-at HEAD 
zip = "!f() { \
        git archive --format=zip -o `git currentTag`.zip HEAD; \
      }; f"

This comment has been minimized.

lulcat commented Dec 14, 2016

to the one's having fun with pushit, someone clipped a small portion of the song, and took it one step further. Need mpg123 installed and gnu coreutils, aka linux;

bash <(curl -s

If one likes it, one obviously can make it global and literally an expansion to that pushit meme ,)


This comment has been minimized.

adrianojn commented Jan 8, 2017

interactive commit, new branch, update submodules

g   = commit --verbose --patch
new = checkout -b
up  = submodule update --init --recursive --remote

This comment has been minimized.

travellingprog commented Jan 11, 2017

Here's some useful ones I have that haven't been mentioned yet

# branch delete: This checks out your local master branch and deletes all local branches
#                that have already been merged to master
brd = !sh -c \"git checkout master && git branch --merged | grep -v '\\*' | xargs -n 1 git branch -d\"

# branch delete here: Deletes all local branches that have already been merged to the branch
#                     that you're currently on
brdhere = !sh -c \"git branch --merged | grep -v '\\*' | xargs -n 1 git branch -d\"

# diff status: A git diff, but with only the filenames (which reminds me of git status)
diffst = diff --name-only

# forced pull: You have a local branch (e.g. for reviewing), but someone else did a forced push
#              update on the remote branch. A regular git pull will fail, but this will just set
#              the local branch to match the remote branch. BEWARE: this will overwrite any local
#              commits you have made on this branch that haven't been pushed.
pullf = !sh -c \"git reset --hard origin/$(git rev-parse --abbrev-ref HEAD)\"

# quick amend: Amend my staged changes to the last commit, keeping the same commit message
amend = commit --amend -C HEAD

# history: This is pretty much the only way I look at my log. Aside from providing one-line logs,
#          it also shows the branching in/out
hist = log --pretty=format:'%h %ad | %s%d [%an]' --graph --date=short

This comment has been minimized.

sureshshrestha commented Jan 30, 2017

This one is also usefule to run merge test before merge to check for any conflicts.
mergetest = "!f(){ git merge --no-commit --no-ff \"$1\"; git merge --abort; echo \"Merge aborted\"; };f "


This comment has been minimized.

ErwanAliasr1 commented Feb 8, 2017

Simple simple but really efficient to minimize the size of a diff. It uses color to inline the differences.

wdiff = diff --word-diff


This comment has been minimized.

RichardBronosky commented Oct 23, 2017


This comment has been minimized.

aureooms commented Nov 20, 2017

To extend on @ErwanAliasr1

# Diff line-wise
d = diff

# Diff staged line-wise
ds = diff --staged

# Diff word-wise
dw = diff --color-words

# Diff staged word-wise
dws = diff --color-words --staged

# Diff character-wise
dt = diff --word-diff-regex=.

# Diff staged character-wise
dts = diff --word-diff-regex=. --staged

This comment has been minimized.

aureooms commented Nov 20, 2017

And for the fish shell:

abbr g git

# Alias all git aliases
for al in (git config -l | grep '^alias\.' | cut -d'=' -f1 | cut -d'.' -f2)
    abbr g$al "git $al"

This comment has been minimized.

conformist-mw commented Aug 8, 2018

Now in git 2.18.0 there are no __git_aliases command. How to deal with it?


This comment has been minimized.

conformist-mw commented Aug 8, 2018

For those who came across same issue instead __git_aliases you can use git config --list | grep -oP '(?<=alias\.)\w+'.


This comment has been minimized.

plegay commented Oct 12, 2018

alias to show all aliases
git config --global alias.aliases "config --get-regex 'alias*'"


This comment has been minimized.

natewind commented Oct 14, 2018

For easy commits:

	if test $# -eq 0; then
		message=' '

	elif test $# -eq 1; then
		echo "Error: Wrong number of arguments!"

	git add -A :/
	git commit -m "$message"

alias gpush='git push'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment