Tracking AI Assistant Contributions Using Git Trailers and Git Hooks

January 23, 2025 • Written by Jakob Serlier

Tags: Git, AI, Development, Productivity, Automation
---

It can be challenging to pinpoint the 'concrete' impact AI assistants have on daily development work.

For example, during a workshop I was part of hosting for a customer, they literally asked in what number we can express the impact of AI tools on our (engineering).

One approach: Git Trailers for AI Attribution

Following some suggestions from our internal community, we can track AI Assistant contributions by attributing their impact using git trailers. This approach makes AI usage visible and concrete in our version control history. This metadata becomes part of your version history, making it possible to generate reports on AI/models usage (frequency), contribution levels, or even the prompts using custom scripts or Git analytics tools.

Here's a git hook that automatically prompts developers to add AI contribution metadata to their commits:

#!/bin/bash
# Usage: add to .git/hooks/commit-msg
# Make the script executable: chmod +x .git/hooks/commit-msg
# To track in repository: add to .githooks folder and set hookspath
# using `git config core.hooksPath .githooks`

set -euo pipefail

COMMIT_MSG_FILE="$1"

# Validate input argument
if [[ -z "${COMMIT_MSG_FILE:-}" ]] || [[ ! -f "$COMMIT_MSG_FILE" ]]; then
    echo "Error: Invalid or missing commit message file" >&2
    exit 1
fi

# Skip for automated commits (merge, rebase, cherry-pick, etc.)
git_dir=$(git rev-parse --git-dir 2>/dev/null || echo "")
if [[ -n "$git_dir" ]]; then
    if [[ -f "$git_dir/MERGE_HEAD" ]]; then
        exit 0
    fi
    if [[ -d "$git_dir/rebase-merge" ]] || [[ -d "$git_dir/rebase-apply" ]]; then
        exit 0
    fi
    if [[ -f "$git_dir/CHERRY_PICK_HEAD" ]]; then
        exit 0
    fi
    if [[ -f "$git_dir/REVERT_HEAD" ]]; then
        exit 0
    fi
fi

# Check for TTY availability
if [[ ! -t 0 ]] && [[ ! -c /dev/tty ]]; then
    echo "No interactive terminal available, skipping AI metadata collection" >&2
    exit 0
fi

echo "AI Commit Metadata Assistant"

prompt() {
    local message="$1"
    local default="$2"
    local response
    
    if read -p "$message" response < /dev/tty; then
        echo "${response:-$default}"
    else
        echo "$default"
    fi
}

# Check if user wants to add AI metadata
echo -n "Did you use an AI Assistant for this commit? [y/N] "
if read -t 10 -r used_ai < /dev/tty; then
    if [[ ! "$used_ai" =~ ^[Yy] ]]; then
        exit 0
    fi
else
    exit 0
fi

model=$(prompt "Assistant model [GPT-4.1]: " "GPT-4.1")
contrib=$(prompt "LLM Contribution [50%]: " "50%")
prompt_summary=$(prompt "Prompt summary (optional): " "")

if [[ "$contrib" =~ ^[0-9]+$ ]]; then
    contrib="${contrib}%"
fi

# Use git interpret-trailers to add proper Git trailers
temp_file=$(mktemp)
cp "$COMMIT_MSG_FILE" "$temp_file" || {
    echo "Error: Failed to create temporary file" >&2
    exit 1
}

trailer_args=(
    --trailer "Assistant-model: $model"
    --trailer "LLM-Contrib: $contrib"
)

if [[ -n "$prompt_summary" ]]; then
    trailer_args+=(--trailer "Prompt: $prompt_summary")
fi

git interpret-trailers "${trailer_args[@]}" "$temp_file" > "$COMMIT_MSG_FILE" || {
    echo "Error: Failed to add trailers to commit message" >&2
    rm -f "$temp_file"
    exit 1
}

rm -f "$temp_file"
echo "AI metadata added to commit message"
exit 0