Code & Craft by Kasra

Adding a System-Wide Git Logger on macOS

Git is both simple and, at times, complicated. While it’s initially encouraged to use the command line instead of apps like Tower or Fork, which offer a user-friendly interface, these apps can sometimes boost productivity. For instance, they provide a visual representation of branches and convenient ways to perform tasks like cloning, pulling, cherry-picking, and rebasing. However, not all of them offer a log or console to monitor the Git commands being executed behind the scenes.

A couple of years ago, I started using Tower, and it has almost replaced Terminal for me. I say almost because there are still a few things that Tower doesn’t offer, but that’s beyond the scope of this article. After reading and following steps in this article, you’ll have a folder containing a log of all the Git commands executed by any app on your system. Here’s a glimpse of my logs, which shows even what commands oh-my-zsh is running:

2024-09-27-20:32:36 git status -z -uall
2024-09-27-20:32:36 git rev-parse refs/remotes/origin/main
2024-09-27-20:32:36 git for-each-ref --ignore-case refs/heads/master refs/remotes/master
2024-09-27-20:32:36 git for-each-ref --ignore-case refs/heads/main refs/remotes/main
2024-09-27-20:32:36 git config --local branch.main.vscode-merge-base
2024-09-28-18:29:25 git status --porcelain --ignore-submodules=dirty
2024-09-28-18:29:29 git commit -m Adding a System-Wide Git Logger on macOS
2024-09-28-18:29:29 git rev-parse --verify --quiet HEAD
2024-09-28-18:29:29 git rev-parse --git-dir
2024-09-28-18:29:29 git config --get oh-my-zsh.hide-status

Locate the path of the git executable

macOS doesn’t come with a built-in version of Git; however, if you’re reading this article, chances are you’ve already installed it. If you installed it some time ago and are unsure of the path to the Git executable on your system, simply run:

which git

In many cases, the path will be either /usr/bin/git or a different location, such as the path for Homebrew (likely /opt/homebrew/bin/git). Note that apps like Tower also install their own Git executable, which can be found in:

/Applications/Tower.app/Contents/Resources/git/bin

It is important to ensure that Tower is configured to use the executable specified in your PATH.

Create a Git Logger

I have many scripts, personally prefer to place all of them in ~/.scripts/. The directory you prefer to keep your scripts is up to you; however, the following steps assume it is the same as mine. We will create the following script:

#!/bin/bash

set -e

# Get the directory where the script is located
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"

# Create a folder.
LOG_FOLDER="git-logs"
mkdir -p "$DIR/$LOG_FOLDER"

# Date is used as a prefix for the log file.
DATE="$(TZ=America/Edmonton date '+%Y-%m-%d')"

# Set the log file path
LOG_FILE="$DIR/$LOG_FOLDER/$DATE.log"

# Create a `$DATE.log` file if it doesn't exists.
if [ ! -f "$LOG_FILE" ]; then
    touch "$LOG_FILE"
fi

# Notice that the timezone is set to MT. But you can adjust it.
TIMESSTAMP="$(TZ=America/Edmonton date '+%Y-%m-%d-%H:%M:%S')"
echo "$TIMESSTAMP git $*" >> "$LOG_FILE"

# The path needs to match the output of `which git`
/opt/homebrew/bin/git "${@}"

This script will create a folder called git-logs, with a new log file for each day. It will intercept each Git command, log it, and then pass it on to the actual Git binary.

Save this file as git (yes, without an extension) and ensure it is executable:

chmod +x git

Update the PATH

The final step is to update your PATH. This part can vary depending on which shell you’re using. I use ZSH, but if you’re using Bash or another shell, there shouldn’t be much difference.

The important thing to note is that we want the path to our script to precede any other path that contains an executable file named git. So, in your .zshrc file, add the following line at the bottom of the file:

export PATH="$HOME/.scripts:$PATH"

This ensures that the path to our git file precedes /opt/homebrew/bin, /usr/bin/git, and so on. You could also place it at the top, but then there’s a chance that something else could precede it by doing something like:

export PATH="/opt/homebrew/bin:$PATH" ❌❌❌

That’s it! Simply re-run the terminal (or run source ~/.zshrc) to ensure your PATH is updated, and then try:

which git

It should output ~/.scripts/git.