I have been using Git extensively since 2011. Over the years, I have configured it to make myself more productive. In this post, I would like to share and explain my Git configuration with you. Hopefully, you will find some nice tweaks in there that will help you to speed up your workflow.
In the present post, I assume that you are using Git from a shell. If you are using it from your IDE, most of the tips will not be useful for you. That being said, let us start with shell configuration.
git is one of my most used commands. Therefore, it has earned its place in my list of one-letter shell aliases:
This alias should be put into your shell configuration file. For Bash, it is
~/.bashrc. With this alias, every Git command is shorter by two characters because instead of
git, you can write just
It is very useful to enable Git completion in your shell. This will make TAB complete Git commands, parameters, branch names etc. For example, to check out the
my-branch-with-long-name branch, you can write just
g checkout my and then press TAB. When there is more than one branch starting with
my, a menu will be shown to you.
To enable this completion in your shell, you can either install a package from your distribution that does this for you (provided that your distribution has such a package), or do it manually. For example, for Bash, you can download the completion file:
wget https://raw.githubusercontent.com/git/git/master/contrib/completion/git-completion.bash -O ~/.git-completion.bash
and add the following piece of code into your
if [[ -f ~/.git-completion.bash ]]; then source ~/.git-completion.bash fi
If you have setup the one-letter
g shell alias (highly recommended), make completion also work for it by adding the following line into your
complete -o default -o nospace -F _git g
Of course, the above way is Bash-specific, so for other shells, you have to do this differently.
I use the following two third-party extensions that are not part of the standard Git.
git up is a great addition to
git pull. It has the following advantages:
git upupdates all branches, not just the branch you are currently on.
git upshows you a list of new commits on each locally tracked branch after it finishes.
git upautomatically stashes local changes before pulling new commits.
git uprebases upstream changes instead of merging them, which makes the commit graph clearer. No more pesky
"Merge branch 'master' of ssh://login@server/git/repo"commits (merge of a branch into itself)!
git edit-index allows you to stage or unstage files from the index in an editor, just like when you perform an interactive rebase. It thus represents a faster alternative to
git add -i or
git gui. See my blog post for more details about it.
All the aliases below belong to the
[alias] section in your
~/.gitconfig. They allow you to write just e.g.
git s instead of
git status -bs. And, if you are using the
g alias, you can write just
g s, which is even faster.
a = add aa = add --update aaa = add --all ap = add --patch
Staging of files.
a stages the given file(s),
aa stages all modified files, and
aaa stages all files (even files that are not tracked by git). Finally,
ap allows you to stage just parts of files (this is useful when you want to commit only some of the changes in the files).
authors = "!git log --pretty=format:%aN | sort | uniq -c | sort -rn"
Lists all commit authors in the repository, ordered by the number of commits.
br = branch -vv bra = branch --all -vv
Lists branches in the repository with more information (
bra also includes remote branches.
This is how the output of
g bra looks like:
c = commit --verbose ca = commit --verbose --all
--verbose parameter includes the diff into the editor, so you can see what you are committing. It also enables you to perform completion when writing the commit message (e.g.
Ctrl-p/n in Vim).
ca commits all tracked files, which is faster than staging them manually.
amend = commit --verbose --amend --reset-author
Amend of the latest commit. This is handy when you realize that you forgot to do something in the last commit (e.g. made a typo or forgot to commit a file).
clear = reset --hard undo = reset --soft HEAD^
clear throws away all changes in the working tree.
undo removes the last commit but leaves the changed files in the index. This is useful when you want to remove the last commit but would like to keep the changes so you can make a different commit.
conflicts = diff --name-only --diff-filter=U --relative
Lists all files with conflicts, relative to the current working directory.
co = checkout cob = checkout -b cot = checkout -t
cob creates a new local branch and checkouts it.
cot checkouts and starts tracking the given remote branch.
d = diff da = diff HEAD ds = diff --staged
da shows all changes since the last commit (both staged and unstaged).
ds shows what changes are staged to be commited.
ignored = ls-files --exclude-standard --ignored --others
Lists files in the current directory (and subdirectories) that are ignored by Git.
l = "!git --no-pager log -20 --pretty='format:%C(yellow)%h %C(green)%ai %C(bold blue)%an %C(red)%d%C(reset) %s'; echo" ll = log --pretty='format:%C(yellow)%h %C(green)%ai %C(bold blue)%an %C(red)%d%C(reset) %s' lf = log --name-status --pretty='format:%C(yellow)%h %C(green)%ai %C(bold blue)%an %C(red)%d%C(reset) %s' lg = log --graph --pretty='format:%C(yellow)%h %C(green)%ai %C(bold blue)%an %C(red)%d%C(reset) %s' lga = log --graph --branches --remotes --tags --pretty='format:%C(yellow)%h %C(green)%ai %C(bold blue)%an %C(red)%d%C(reset) %s'
Display of commits in a pretty format.
l lists the topmost 20 commits without a pager.
ll lists all commits (linearized).
lf lists files that were changed in the commits.
lg displays a commit graph.
lga displays also a commit graph but includes info about all branches.
This is how the output of
g l looks like:
m = merge --no-ff
--no-ff parameter ensures that a merge commit is created. This is useful when merging topic branches because the branch will be shown in a graph log (otherwise, if it has merged
master in the last commit, no commit will be created because Git will do a fast-forward).
p = push pb = "!git push --set-upstream origin `git rev-parse --abbrev-ref HEAD`"
pb pushes the current branch to the remote server and makes it tracking your local branch. Useful after creating a local branch.
rb = rebase --preserve-merges rba = rebase --abort rbc = rebase --continue rbi = rebase --interactive rbs = rebase --skip
Rebasing. The parameter names are mostly self-explaining. The
--preserve-merges parameter ensures that local merges are preserved during a rebase. Otherwise, Git would perform a rebase instead of each merge, so you would loose the merges.
s = status --short --branch
Shows the status.
--short makes the status more readable.
--branch shows also the name of the current branch.
This is how the output of
g s looks like:
sh = stash sha = stash apply shd = stash drop shl = stash list shp = stash pop shs = stash show -p
shs shows the topmost stash as a diff.
sw = show --format=fuller
Shows the given commit and displays more information.
tags = tag --list -n1
Lists all tags.
bl = blame cp = cherry-pick ei = edit-index u = up
Just to save some typing.
The following settings also go to your
[color] ui = true
Enable colors in the output of Git commands. This makes the output more readable.
[color "grep"] filename = magenta match = yellow bold separator = cyan
git grep colors match the colors I use for
grep in Bash (see my
[core] whitespace = trailing-space,space-before-tab pager = less -iFRXS -x4 editor = vim
git notice whitespace-related problems (e.g. in diffs). The used
less parameters are explained here. Use
vim as the editor for e.g.
git commit and
git rebase -i.
[merge] tool = vimdiff
As I use Vim as my editor,
vimdiff is the natural merge tool to use.
[advice] pushNonFastForward = false statusHints = false commitBeforeMerge = false resolveConflict = false detachedHead = false
Make Git a little less verbose. See this post for a description and illustrations of the effect of these settings.
[include] path = .gitconfig.local
This allows me to have a
~/.gitconfig.local file that may override the settings in my
~/.gitconfig. For example, at work, I use a different
[git-up "rebase"] arguments = --preserve-merges log-hook = "echo \"* changes on $1:\"; git log --pretty='format:%C(yellow)%h %C(green)%ai %C(bold blue)%an %C(red)%d%C(reset) %s' $1..$2"
git up. The first one causes
git-up to preserve local merges during rebasing (see the description of the
--preserve-merges parameter to
git rebase above). The second one makes
git up use the same log format that I use in my log-related aliases.