Git is very configurable. If you're ever bored, you could spend some time reading git-config(1). You never know what you might find.
I'm an opinionated person. So I've tried to break the Git configuration I use into varying levels of opinion.
There's no excuse for not setting your user.name
and user.email
,
especially in a professional environment. Git defaults to using your computer username, which
probably isn't appropriate to use.
I don't want to see 4-5 different spellings of your name, your username, and your email in the Git log. I don't want to see a random ID number in the Git log that I can't map to a person.
</rant>[user]
name = First Last
email = email@example.com
My workplace prefers a linear history. That means we rebase and merge without a merge commit. This
results in a much cleaner commit history that's easier to interrogate. My personal opinion, is
that feature branches should be rebased, but then merged with an empty merge commit. They should
not be squashed, as that makes using git-log
and git-blame
to
interrogate the commit history impossible to glean useful information from.
In both cases, pull.rebase=true
should be set. This means any local commits will be rebased
on top of the remote branch instead of creating a merge commit. This one change would eliminate much of
the frustration coworkers have experienced with "tricky" rebases.
[pull]
rebase = true
In my preferred workflow, there's a branch per feature, and then those branches get deleted after
they're merged (so you don't end up with thousands of remote branches!) So you should set
fetch.prune=true
[fetch]
prune = true
TODO: I have not learned a nice way to automatically delete local branches when the remote tracking branch has been deleted. From https://stackoverflow.com/questions/13064613/how-to-prune-local-tracking-branches-that-do-not-exist-on-remote-anymore it looks like
git switch master
git branch -vv | grep ': gone]' | awk '{print $1}' | xargs -r git branch -d
Note you must checkout the master branch before running, or else use
git branch -D
.
I was really tempted to put this in the section above. Complaints about how much work it is to write good commit messages that meet the stylistic concerns of the esteemed How to Write a Git Commit Message blog post by Chris Beams. Vim does syntax highlighting of the subject line, blank line, and can reflow paragraphs to meet the 72 character line length limit.
[core]
editor = vim
The importance of using Linux newlines depends on the team and technologies being developed. For what I work on, CRLF has no place.
[core]
eol = lf
Seeing the diff you're committing right in your commit editor (and syntax highlighted if you have a
sufficient core.editor
) is invaluable for crafting informative commit messages, and
providing a guard against committing changes you never intended.
[commit]
verbose = true
It's also helpful to have a global .gitignore
to avoid committing common temp files.
[core]
excludesFile = ~/.gitignore
in which I have
# Vim swap files
*.sw?
# GDB history logs
.gdb_history
I like using delta as my Git pager. It
does better word-diffing and highlighting than the contrib
diff-highlight
, and it additionally provides syntax highlighting and line numbers. The package in the Ubuntu
repository was a bit out of date, so I installed delta
from the latest GitHub release with
USERNAME="dandavison"
REPO="delta"
curl --silent "https://api.github.com/repos/$USERNAME/$REPO/releases/latest" | # Get latest release from GitHub api
grep --only-matching --perl-regexp '"tag_name": "\K(.*)(?=")' | # Get the latest tag
xargs -I {} curl --location --output /tmp/delta.deb --remote-name "https://github.com/$USERNAME/$REPO/releases/download/{}/git-delta_{}_amd64.deb"
sudo apt install /tmp/delta.deb
Then add the following config
[core]
pager = delta
[interactive]
diffFilter = delta --color-only
[delta]
line-numbers = true
syntax-theme = base16
# side-by-side diffs are nice, but are too wide to be helpful in fzf --preview windows
# TODO: Perhaps git-gl should be rewritten to pass git -c delta.side-by-side=false for the preview
# but not to the pager view?
# TODO: There's also something weird about the terminal width when switching from the preview
# to the pager.
# side-by-side = true
I have a number of aliases that are so-ingrained in my muscle memory that I almost can't use Git on a colleague's computer.
[alias]
lg = log --color --graph --pretty=format:'%C(auto)%h%d %s %C(black)%C(bold)%an, %ar' --abbrev-commit --decorate
ll = log --pretty=format:'%C(red)%h%C(reset) -%C(yellow)%d%C(reset) %s %C(bold blue) <%an>' --decorate --numstat --abbrev-commit
rf = reflog --pretty=format:'%C(auto)%h %gd %gs%C(black)%C(bold), %cr'
co = checkout
sw = switch
amend = commit --amend --no-edit
st = status
b = branch -vv
rb = rebase
chp = cherry-pick
Lastly, I can't live without git-gl
, which is an interactive commit browser powered by FZF. Briefly, it's a pager for
git-log
that supports searching commit messages, previewing the diffs, performing
interactive rebases, copying hashes to the system clipboard, and cherry-picking selected commits.