Toon’s git configuration


git config

This file generates my git global config.

User config

Only define my name, and not my email. And instruct git to avoid trying to guess a default for the email. This will enforce me to set the email for each git repo.

[user]
        useConfigOnly = true
        name = Toon Claes

Core config

[core]

Global ignore file

Use a global ignore file.

I’m using the default ~/.config/git/ignore so no need to set this explicitly.

excludesfile = ~/.config/git/ignore

Hooks path

Centralize all hooks instead of configuring them on a per-repository basis.

hooksPath = ~/.config/git/hooks/

Commit comments

I tend to use markdown in my commit messages, and markdown uses the # symbol to define headings. So instead of the default symbol # used to define comments in commit messages, use ;.

commentchar = ";"

CR/LF

Don’t do output conversion on end-of-line.

autocrlf = input

Help

[help]

Auto-correct

Auto-correct mistyped commands after 0.1 seconds.

autoCorrect = 1

Protocol

Use git protocol v2 whenever possible.

[protocol]
        version = 2

Status

[status]

Untracked files

Show also individual files in untracked directories.

showUntrackedFiles = all

Submodule summary

Enable submodule summary showing the summary of commits for modified submodules.

submoduleSummary = true

Fetching

[fetch]

Prune

Prune the local tracking branches when fetching from remote.

prune = true

Aliases

Define a set of aliases.

[alias]

Scrub

This alias scrubs away all local branches that are merged.

scrub = !git branch --merged | egrep -v '(^\\*|master)' | xargs git branch -d

Work-in-progress

I don’t like git stashes. A git stash is where code goes to die. So instead of stashes, create a WIP commit on the current branch. This is much better to keep context of the work-in-progress code, allows me to push the code to a remote and have backup, and maybe also give me some insights on the test results of CI.

I’m also providing an alias that undoes the last commit if it is a WIP commit.

Improved unwip alias by ZJ.

wip = !git add -A && git commit -mWIP
unwip = !git log -1 --format=format:"%H" --invert-grep --grep '^WIP' | xargs git reset --soft

Rebase on remote master

I commonly rebase my working branch on master on the remote. That remote can be origin or upstream. So this alias allows me to fetch master from the <remote> and rebase current branch on <remote>/master.

It expects one argument:

  • the name of the remote
remaster = !sh -c 'git fetch $1 master && git rebase $1/master' -

Resync with remote

When the remote branch was rebased and you want to resynchronize your local branch to the remote state, use this reremote alias.

It expects one argument:

  • the name of the remote
reremote = !sh -c 'git fetch $1 HEAD && git reset --hard FETCH_HEAD' -

Rerere

git-rerere stands for: Reuse recorded resolution of conflicted merges. It is an awesome feature that helps you to resolve the same conflicts over and over again.

[rerere]
        enabled = true

Markdown diffing

Below is an attempt to improve diffing markdown files. But I never got it working and I just left it here.

[diff "markdown"]
        tool = lowdown

[difftool "lowdown"]
        cmd = "lowdown-diff -s -Tman $LOCAL $REMOTE | groff -Tascii -man | less"

Rails database schema merging

[merge "merge_db_schema"]
        name = Merge db/schema.rb
        driver = merge_db_schema %O %A %B
        recursive = text

LFS

These settings involving LFS are generated by git itself.

[filter "lfs"]
        smudge = git-lfs smudge -- %f
        process = git-lfs filter-process
        required = true
        clean = git-lfs clean -- %f

Protocol

Enable git protocol version 2.

Read about it.

[protocol]
        version = 2

Sendmail

Configure git to send mails directly from git.

Instructions came from git-send-email.io.

I have msmtp configured to send mails through Emacs, so I can just use that tool here too.

[sendemail]
    smtpserver = /usr/bin/msmtp

Global Gitignore

Ruby vendoring

Ignore gems installed in the local vendor directory.

/vendor/ruby

GNU Global

For a while I used GNU Global for tagging code, so ignore the TAGS files from being committed.

GPATH
GRTAGS
GTAGS

Dir locals

Most project don’t like Emacs .dir-locals.el.

.dir-locals.el

Byebug

Byebug creates a history file in the current working directory, and that’s not something you want to check in.

.byebug_history

Gitattributes

Markdown

Configure how markdown files are diffed, but not enabled at the moment.

*.md diff=markdown

Rails database schema

Specify the merge tool to be used to merge db/schema.rb in Ruby on Rails projects.

db/schema.rb merge=merge_db_schema
ee/db/geo/schema.rb merge=merge_db_schema

Hooks

User-wide hooks.

Pre-push

When a Gemfile is found, and rubocop is enabled, run Rubocop on the files modified compared to the last merge commit. And since in our codebase everything is applied to master with a merge commit, this can be considered the upstream commit.

We also could have used @{upstream}, but that requires each branch to set it’s upstream branch, and that is not always the case.

if [[ -f Gemfile.lock && -x $(bundle exec which rubocop) ]]; then
  echo "> Running Rubocop.."
  git diff --name-only --diff-filter=d $(git log --merges -1 --pretty=format:%H) | xargs bundle exec rubocop
else
  exit 0
fi

Standalone commands

A section of small, standalone git command scripts

Delouse

I borrowed this command from @nvie’s git-toolbelt.

Say you want to rebuild your last commit, but want to keep the commit message. git delouse empties the last commit on the current branch and places all changes back into the working tree.

#!/bin/sh
set -e
curr_sha=$(git rev-parse HEAD)

git reset HEAD~1
git commit --allow-empty --no-verify -C "$curr_sha"

Abort

A short command to abort any action that is ongoing. That could be:

  • cherry-pick
  • rebase
  • merge
git_status=$(git status)

if [[ $git_status =~ 'currently cherry-picking' ]]; then
  git cherry-pick --abort
  echo "Ongoing cherry-pick aborted."
  exit 0
fi

if [[ $git_status =~ $(echo 'currently (editing a commit while )?rebasing') ]]; then
  git rebase --abort
  echo "Ongoing rebase aborted."
  exit 0
fi

if [[ $git_status =~ 'you are still merging' ]]; then
  git merge --abort
  echo "Ongoing merge aborted."
  exit 0
fi

echo >&2 "Nothing found to abort."
exit 1

Continue

A short command to continue any action that is ongoing. That could be:

  • cherry-pick
  • rebase
  • merge
git_status=$(git status)

if [[ $git_status =~ 'currently cherry-picking' ]]; then
  echo "Continuing ongoing cherry-pick."
  git cherry-pick --continue
  exit 0
fi

if [[ $git_status =~ $(echo 'currently (editing a commit while )?rebasing') ]]; then
  git rebase --continue
  echo "Continuing ongoing rebase."
  exit 0
fi

if [[ $git_status =~ 'you are still merging' ]]; then
  echo "Continuing ongoing merge."
  git commit
  exit 0
fi

echo >&2 "Nothing found to continue."
exit 1

Modified

Get all files that are modified.

There was some discussion on this on team chat.

git diff --name-only --diff-filter=d