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.
Shell Alias
git
is one of my most used commands. Therefore, it has earned its place in my list of one-letter shell aliases:
alias g='git'
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 g
.
Shell Completion
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 ~/.bashrc
:
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 ~/.bashrc
:
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.
Git Extensions
I use the following two third-party extensions that are not part of the standard Git.
git up
git up
is a great addition to git pull
. It has the following advantages:
git up
updates all branches, not just the branch you are currently on.git up
shows you a list of new commits on each locally tracked branch after it finishes.git up
automatically stashes local changes before pulling new commits.git up
rebases 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
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.
Git Aliases
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 (-vv
). bra
also includes remote branches.
This is how the output of g bra
looks like:
c = commit --verbose ca = commit --verbose --all
Committing. The --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^
Reset. 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
Checkout. 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
Diffing. 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
Merging. The --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`"
Pushing. 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
Stashing. 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.
Git Settings
The following settings also go to your ~/.gitconfig
.
[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
Make the git grep
colors match the colors I use for grep
in Bash (see my .bashrc
).
[core] whitespace = trailing-space,space-before-tab pager = less -iFRXS -x4 editor = vim
Make 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 user.name
and user.email
.
[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"
Settings for 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.
My Configuration Files
My configuration files are available on Github. More specifically, configuration files for Git and Bash are here and here, respectively.
Great Post’
I did it, thanks.