Blog

git notoriously has a steep learning curve, so I wanted to share some of my git configuration options that have mildly improved my workflow. You can view your global configuration by typing git config --global --list or by viewing your ~/.gitconfig file.

Default Commit Author

First up is user.email and user.name, which almost everyone sets as global settings in their ~/.gitconfig file like this:

git config --global user.name "Your Name"
git config --global user.email "your-email@your-domain.com"

This ensures that your name and email address appear on the commits that you author. Your global git configuration file ~/.gitignore is updated as follows:

[user]
	name = Your Name
	email = your-email@your-domain.com

Line Endings

If you develop on various operating systems (i.e. Windows and Linux), you may run into line feed issues. My opinion is to ensure whatever is committed to a repository uses LF only, never CR and never CRLF. To ensure this happens, I recommend setting the core.autocrlf option to input. In my opinion, you should do this even on Windows where CRLF is often used. You can always override this for each repository with a .gitattributes file.

git config --global core.autocrlf input

Diff Options

I have found it sometimes useful to show a colored diff at the word level like this: git wdiff. Under the hood, you can configure git to invoke diff --color-words.

git config --global alias.wdiff="diff --color-words"

Now you can run git wdiff instead of git diff where appropriate. You can even perform diffs on more complex files such as Word documents. Hrishi Olickel has a great blog post discussing how to do this.

Push Options

Many times I just want git push to push my branch with the same name as the remote and automatically set up upstream tracking. As of Git 2.37 this is possible with two settings:

git config --global push.default current
git config --global --bool push.autoSetupRemote true

push.default has many options now. If you find yourself looking back and forth between the descriptions to see the differences, try using this chart (courtesy of this StackOverflow answer):

Behavior simple1 upstream2 current matching nothing3
Push checked-out branch
Push other branches
Upstream branch
must be configured
Upstream branch
name must match

1 simple is the default setting value since Git v2.0, released in 2014.
2 upstream has a deprecated alias, tracking.
3 nothing requires all options to be specified on the CLI.

push.autoSetupRemote enables a feature where pushing a new branch to a remote repository automatically sets up that branch to track the remote branch with the same name.

Now, if we create a new branch from master:

git checkout master
git checkout -b feat/my-new-feature

We can simply make commits on it and push to origin with git push. So instead of this:

git push -u origin feat/my-new-feature

We can do this:

git push

…and your new branch is automatically pushed to origin with the same branch name.

Pull Options

git pull is an alias for:

git fetch
git merge

Since git merge can sometimes result in merge conflicts, I'd prefer that it's only run with --ff-only, so that merging only occurs if a fast-forward is possible. You can make this the default for git pull with this configuration:

git config --global pull.ff only

Similarly, I really like git fetch to be run with the git fetch --prune option set. This ensures that deleted remote reference branches are also deleted on the local machine, which I believe is a nice way to clean up old branch references. Note: this does not clean up local branches, just the references to the deleted remote branches.

git config --global fetch.prune true

Log Decoration

git log --decorate is a bit nicer than git log in my opinion. We can set this behavior by default:

git config --global log.decorate auto

Conclusion

That's it! Here's my entire git configuration file with all of these settings applied:

[user]
	name = Blake Miner
	email = miner.blake@gmail.com
[core]
	autocrlf = input
[alias]
	wdiff = diff --color-words
[push]
	default = current
	autoSetupRemote = true
[log]
	decorate = auto
[pull]
	ff = only
[fetch]
	prune = true

Now go git 'em!


Blog Post Index