Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save aont/71650f71f29b75e0723ae38b13e3a95d to your computer and use it in GitHub Desktop.

Select an option

Save aont/71650f71f29b75e0723ae38b13e3a95d to your computer and use it in GitHub Desktop.

Prevent Accidental Cross-Account Pushes with a Git Hook

If you work with multiple Git identities (e.g., company and personal), it’s easy to commit with one account and accidentally push from another. The simple pre-push hook below helps catch that mistake by checking your recent commits against a list of “my accounts.” If it finds overlaps, it blocks the push and shows you the matches.

What the Hook Does

  • Reads a list of your own identities (name + email) from ~/.config/git/hooks/my-accounts.
  • Scans recent commits in the current repository for author lines (%an <%ae>).
  • Normalizes and deduplicates both lists, then computes the intersection.
  • If two or more identities overlap, it fails the push (helps catch cross-account mixing).
  • If one overlaps, it lets the push proceed but shows the match (useful visibility).
  • If none overlap, it prints OK and proceeds.

Why “two or more”? One match may be the normal, intended identity; multiple matches suggest mixed identities in recent commits.

Set Up the Hooks Directory

# Create a directory to hold your hooks
mkdir -p ~/.config/git/hooks

# Tell Git to use this directory for all repositories
git config --global core.hooksPath ~/.config/git/hooks

Install the Hook

Save the script below as:

~/.config/git/hooks/pre-push

Make it executable:

chmod +x ~/.config/git/hooks/pre-push

Note: Be sure the filename and the chmod target both refer to pre-push.

Create Your Accounts List

Create the file ~/.config/git/hooks/my-accounts with one identity per line, using the format:

Your Name <you@example.com>
Work Name <you@company.com>

How to Use It

  1. Add/commit as usual.

  2. When you push, Git will run pre-push:

    • If it detects multiple overlapping identities, the push stops with an error and shows the offending lines.
    • Otherwise, the push proceeds.

Troubleshooting

  • Hook didn’t run? Confirm git config --global core.hooksPath shows ~/.git-hooks and the script is executable.
  • Wrong file made executable? Ensure you ran chmod +x ~/.git-hooks/pre-push (not pre-commit).
  • No accounts file? Create ~/.git-hooks/my-accounts with your identities as shown above.

That’s it! This lightweight guard helps keep your commits aligned with the right identity before they leave your machine.

#!/usr/bin/env bash
set -euo pipefail
MY_ACCOUNTS_FILE="$(git config --global core.hooksPath)/my-accounts"
err_exit() {
echo "$1" >&2
exit "${2:-2}"
}
if [ ! -f "$MY_ACCOUNTS_FILE" ]; then
err_exit "Error: my accounts file not found: $MY_ACCOUNTS_FILE" 2
fi
if ! git rev-parse --git-dir >/dev/null 2>&1; then
err_exit "Error: not a git repository" 2
fi
# normalize_line: trims, collapses internal whitespace to a single space, removes CR
normalize_line() {
# reads from stdin, writes normalized lines to stdout
sed 's/\r$//' \
| sed -E 's/^[[:space:]]+//; s/[[:space:]]+$//' \
| sed -E 's/[[:space:]]+/ /g'
}
# 1) Read, normalize, and deduplicate the allowed accounts list
my_accounts_lines=$(normalize_line <"$MY_ACCOUNTS_FILE")
# 2) Get the author lines from the last N commits (%an %ae)
commit_lines=$(git shortlog -sne 2>/dev/null | sed -e 's/^[[:space:]]*[0-9]\+[[:space:]]\+//g' | normalize_line)
# 3) Intersection (lines present in both lists)
# Use process substitution for comm
matches=$(comm -12 <(echo "$my_accounts_lines") <(echo "$commit_lines") || true)
# Count non-empty lines
match_count=0
if [ -n "${matches}" ]; then
# remove blank lines and count
match_count=$(printf "%s\n" "$matches" | sed '/^\s*$/d' | wc -l | tr -d ' ')
fi
# 4) Evaluate results
if [ "$match_count" -ge 2 ]; then
echo "ERROR: found ${match_count} overlapping account(s) (same \"%an %ae\" lines present in both my accounts file and commits):"
printf "%s\n" "$matches"
exit 1
else
echo "OK: overlapping accounts count = ${match_count}"
if [ "$match_count" -eq 1 ]; then
echo "Match:"
printf "%s\n" "$matches"
fi
exit 0
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment