Configure Git

Git can be configured to improve a developer's workflow. I use git from the command line, so I rely on aliases and hooks.

Aliases

Git aliases allow one to decrease the amount of typing and the need to memorize exact commands.They are defined in .gitconfig file, under the alias section.

[alias]
	c=commit
	lg="git log -1"

In the example above, the aliases c and lg allow one to run git c and git log instead of git commit or git log -1 .

The alias section in my .gitconfig is as follows

[alias]
  a=add
  b=branch
	c=commit
  p=push
  s=status
  # Add a patch
	ap="!git add ${@} -p; git status"
  # Simple Checkout
	co="!git checkout ${@}; git status"
  # Display last commit (HEAD)
	lst="!git log -1 | cat"
  # Search for a branch
	sr="!git branch -a | grep $2"
  # Discard changes
	unco="!git checkout -- ${@}; git status"
  # Unstage changes
	unst="!git reset HEAD -- ${@}; git status"

The ! tells to git to run the command as if in a terminal.

Hooks

Git hooks allow one to tap into the the git lifecycle events.This gives one the ability to automate routine tasks. I use the following hooks

  1. pre-commit
  2. commit-msg
  3. pre-push

Pre-commit

This hook is run before any of the commit related git lifecycle events are fired. I use it to do the linting and type checking.

#!/bin/sh
set -e

changed_files="$(git diff --staged --name-only *.{ts,tsx})"

## Linter on changed files
echo "Running ESLint on changed files"
echo $changed_files | xargs npx eslint

## Typechecker on changed files
echo "Running typechecker on changed files"
echo $changed_files | xargs npx tsc --noEmit

Commit-msg

This hook is run after a commit message has been written and before the commit has been applied.I use it to ensure that the commit message header is prefixed with the issue/ticket id.

#!/bin/sh
set -e

# Read first line from EDIT_COMMITMSG file
read -r msg<$1

# Get current branch name
branch=$(git symbolic-ref --short -q HEAD)

# If branch name is properly named, then extract XXX-1234 prefix.
# It will used to prefix the commit message.
if [[ $branch =~ ^[a-zA-Z]{3}-[0-9]+ ]]; then
  prefix="${BASH_REMATCH[0]}"
else 
  echo "Branch name is not prefixed with XXX-1234."
  exit 1
fi

if [[ $msg =~ ^[a-zA-Z]{3}-[0-9]+ ]]; then
  echo "The commit message properly formatted."
else
  msg="$prefix $msg"
  # Replace the commit message header with the prefixed one
  gsed -i "1s/.*/$msg/" $1
  echo "Prefixed the commit message with $prefix"
fi

Pre-push

This hook is run before one pushes to a remote branch. I use it to run tests, this is specially helpful when pushing to an open PR.

#!/bin/bash

npm test -- --all --watchAll=false --silent