Tracking AI Assistant Contributions Using Git Trailers and Git Hooks

July 28, 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

Git trailers add metadata in the form of:

Assistant-model: GPT-4.1
LLM-Contrib: 50%
Prompt: Refactored authentication logic for clarity

Using Git Trailers, we can attribute the impact of AI on a commit-level. 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. Using it would look like:

usage_hook

#!/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