Last Updated: 2025-10-31
Purpose: Production-grade git configuration optimized for software engineering workflows
This repository contains a production-ready git configuration designed for modern software development workflows. It provides an opinionated setup that emphasizes:
- 🔐 Security: SSH commit signing, protocol hardening, and credential protection
- ⚡ Performance: Optimized for large repositories with fsmonitor, commit graphs, and incremental maintenance
- 🎨 Developer Experience: 25+ useful aliases, better diffs/merges, and smart defaults
- 📦 Modern Standards: XDG Base Directory compliance, conventional commits, and Git 2.32+ features
- 🔄 Best Practices: Signed commits, linear history, automatic pruning, and integrity checks
This configuration provides:
- Complete SSH Signing Setup - Simpler than GPG, works with GitHub/GitLab
- Performance Optimizations - 10x faster
git statuson large repos - Smart Aliases - Shortcuts for common workflows (undo, amend, sync, gone, etc.)
- Enhanced Diff/Merge - Histogram algorithm, move detection, zdiff3 conflicts
- Security Hardening - Block insecure protocols, verify objects, protect secrets
- Global Ignore Patterns - Never commit secrets, build artifacts, or OS files
- Conventional Commits - Template enforcing semantic commit messages
- Cross-Platform Support - Line ending normalization, proper file attributes
- Individual developers wanting a battle-tested git setup
- Teams establishing consistent git workflows
- Open source maintainers requiring signed commits and verified contributions
- Anyone tired of configuring git from scratch on new machines
Step 1: Clone this repository
# Clone to a location of your choice (e.g., ~/dev or ~/projects)
git clone https://github.com/orue/git-configuration.git
cd git-configurationNote: Remember the location where you cloned this repo - you'll need to reference these files during installation.
Step 2: Follow the Installation Guide
After cloning, follow the complete installation process below:
- Generate SSH keys (if you don't have one)
- Configure GitHub
- Configure GitLab (optional)
- Install config files - Copy files from this cloned repo to
~/.config/git/ - Update personal information - Add your name, email, and SSH key
- Test the setup - Verify everything works
- User Identity & Signing
- Commit Configuration
- GPG/SSH Signing
- Aliases
- Colors & UI
- Branch & Tag Management
- Diff Configuration
- Merge Configuration
- Push & Fetch
- Performance Optimization
- Workflow Enhancements
- Security
- Advanced Features
- Global Ignore Patterns
- Git Attributes
- File Structure
This configuration uses the XDG Base Directory Specification for organizing git configuration files.
- Better Organization: All git files in one directory instead of scattered in home directory
- Modern Standard: XDG Base Directory is the modern Linux/Unix standard (adopted by git 2.32+)
- Cleaner Home Directory: Reduces clutter in ~/
- Easier Backup: Single directory to backup all git configuration
- Version Control: Easier to track in dotfiles repositories
Old approach (traditional):
~/
├── .gitconfig # Main config
├── .gitignore_global # Global ignore
├── .gitmessage # Commit template
└── .git-templates/ # Templates
New approach (XDG):
~/.config/git/
├── config # Main config (was ~/.gitconfig)
├── ignore # Global ignore (was ~/.gitignore_global)
├── commit-template.txt # Commit template
├── allowed_signers # SSH signing verification
└── attributes # Global attributes
If you have an existing ~/.gitconfig file, here's how to migrate:
# 1. Backup existing configuration
cp ~/.gitconfig ~/.gitconfig.backup
# 2. Create XDG directory
mkdir -p ~/.config/git
# 3. Move existing config (if you want to keep your current settings)
mv ~/.gitconfig ~/.config/git/config
# 4. Or start fresh with this configuration
cp config ~/.config/git/config
# 5. Verify git finds the config
git config --list --show-originGit will automatically check both locations in this order:
~/.config/git/config(XDG, preferred)~/.gitconfig(traditional, fallback)
Important: If both files exist, git will read from both, with ~/.gitconfig taking precedence. To avoid conflicts, choose one location.
SSH keys are used for both authentication (pushing/pulling) and signing commits.
# Generate a new ED25519 SSH key
ssh-keygen -t ed25519 -C "your.email@example.com"
# When prompted:
# - File location: Press Enter for default (~/.ssh/id_ed25519)
# - Passphrase: Enter a strong passphrase (recommended for security)Why ED25519?
- ✅ More secure than RSA
- ✅ Smaller key size (faster)
- ✅ Better performance
- ✅ Recommended by GitHub, GitLab, and security experts
# Generate 4096-bit RSA key (if ED25519 not available)
ssh-keygen -t rsa -b 4096 -C "your.email@example.com"# Start ssh-agent (if not running)
eval "$(ssh-agent -s)"
# Add your SSH key to the agent
ssh-add ~/.ssh/id_ed25519
# Verify key is loaded
ssh-add -L
# Make it persist across reboots (macOS)
# Add to ~/.ssh/config:
cat >> ~/.ssh/config <<'EOF'
Host *
AddKeysToAgent yes
UseKeychain yes
IdentityFile ~/.ssh/id_ed25519
EOFSSH keys serve two purposes on GitHub:
- Authentication - Push/pull repositories
- Signing - Sign commits and tags
You'll add the same public key for both purposes.
# Copy your public key to clipboard
# macOS:
pbcopy < ~/.ssh/id_ed25519.pub
# Linux (requires xclip):
xclip -selection clipboard < ~/.ssh/id_ed25519.pub
# Or just display it:
cat ~/.ssh/id_ed25519.pubOn GitHub:
- Go to Settings → SSH and GPG keys → New SSH key
- Title:
Work Laptop - Authentication(descriptive name) - Key type:
Authentication Key - Key: Paste your public key
- Click Add SSH key
Test SSH connection:
ssh -T git@github.com
# Should see: "Hi username! You've successfully authenticated..."On GitHub:
- Go to Settings → SSH and GPG keys → New SSH key
- Title:
Work Laptop - Signing(descriptive name) - Key type:
Signing Key⚠️ Important: Select "Signing Key" not "Authentication Key" - Key: Paste the same public key again
- Click Add SSH key
Why add the same key twice?
- GitHub separates authentication keys from signing keys
- You can use the same key for both purposes
- Or use different keys if you prefer separation
On GitHub:
- Go to Settings → SSH and GPG keys
- Scroll down to Vigilant mode
- Check Flag unsigned commits as unverified
Benefits:
- All unsigned commits will be marked as "Unverified"
- Makes it obvious when commits aren't signed
- Improves security awareness
Similar to GitHub, GitLab uses SSH keys for authentication and signing.
# Copy your public key (same commands as above)
cat ~/.ssh/id_ed25519.pubOn GitLab:
- Go to Preferences → SSH Keys
- Key: Paste your public key
- Title:
Work Laptop - Authentication(descriptive name) - Usage type:
AuthenticationorAuthentication & Signing - Expiration date: Optional (recommended for security)
- Click Add key
Test SSH connection:
ssh -T git@gitlab.com
# Should see: "Welcome to GitLab, @username!"On GitLab:
- Go to Preferences → GPG Keys (yes, even for SSH signing!)
- GitLab supports SSH signing via the same SSH key
- Alternatively, if you want separate signing keys, add another SSH key
Note: GitLab's SSH signing support may vary by version. For best compatibility:
- GitLab 14.0+: Native SSH signing support
- Earlier versions: May require GPG signing instead
# 1. Create config directory
mkdir -p ~/.config/git
# 2. Copy all configuration files
cp config ~/.config/git/config
cp commit-template.txt ~/.config/git/commit-template.txt
cp allowed_signers ~/.config/git/allowed_signers
cp attributes ~/.config/git/attributes
cp ignore ~/.config/git/ignore
# 3. Make sure old ~/.gitconfig doesn't conflict
# Option A: Remove it (if you're using this config)
mv ~/.gitconfig ~/.gitconfig.old
# Option B: Keep both (not recommended - can cause conflicts)
# Git will read both, with ~/.gitconfig taking precedenceEdit ~/.config/git/config:
# Open in your editor
nvim ~/.config/git/config # or nano, vim, code, etc.Replace these values:
[user]
name = Your Name → Your actual name
email = your.email@example.com → Your actual email
signingkey = ~/.ssh/id_ed25519.pub → Path to your SSH PUBLIC keyImportant:
- Use your public key (.pub file), not private key
- Must match the email you used with GitHub/GitLab
- Path can be absolute or relative to home (~/)
The allowed_signers file tells git which SSH keys are authorized to sign commits.
# Edit the allowed_signers file
nvim ~/.config/git/allowed_signersFormat:
your.email@example.com namespaces="git" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... your.email@example.com
Generate your entry:
# Get your public key content
cat ~/.ssh/id_ed25519.pub
# Format it correctly (replace with your actual email and key)
echo "your.email@example.com namespaces=\"git\" $(cat ~/.ssh/id_ed25519.pub)" > ~/.config/git/allowed_signersExplanation of format:
your.email@example.com- Email (must match git config)namespaces="git"- Limits key to git signingssh-ed25519 AAAA...- Your actual public key contentyour.email@example.com- Comment (usually same email)
# Verify public key exists and is readable
cat ~/.ssh/id_ed25519.pub
# Verify private key exists (don't display it!)
ls -la ~/.ssh/id_ed25519
# Check file permissions (private key should be 600)
chmod 600 ~/.ssh/id_ed25519
chmod 644 ~/.ssh/id_ed25519.pubYour configuration already has SSH signing enabled, but let's verify:
# Check signing configuration
git config --global gpg.format
# Should output: ssh
git config --global user.signingkey
# Should output: ~/.ssh/id_ed25519.pub (or your key path)
git config --global commit.gpgsign
# Should output: true
git config --global gpg.ssh.allowedSignersFile
# Should output: ~/.config/git/allowed_signersIf any are missing, set them:
git config --global gpg.format ssh
git config --global user.signingkey ~/.ssh/id_ed25519.pub
git config --global commit.gpgsign true
git config --global gpg.ssh.allowedSignersFile ~/.config/git/allowed_signers# See where git is reading config from
git config --list --show-origin | grep "user.name"
# Should show: file:/home/you/.config/git/config
# Check all important settings
git config user.name
git config user.email
git config user.signingkey
git config commit.gpgsign# Create a test repository
mkdir /tmp/git-signing-test
cd /tmp/git-signing-test
git init
# Make a test commit
git commit --allow-empty -m "test: verify SSH signing works"
# Verify the commit is signed
git log --show-signature -1
# Should see:
# Good "git" signature for your.email@example.com with ED25519 key SHA256:...If signing fails, troubleshoot:
# Check ssh-agent has your key
ssh-add -L
# If empty, add your key
ssh-add ~/.ssh/id_ed25519
# Try signing again
GIT_TRACE=1 git commit --allow-empty -m "test" -S# Clone a repository via SSH
git clone git@github.com:yourusername/your-repo.git
cd your-repo
# Make a signed commit
echo "test" >> README.md
git add README.md
git commit -m "test: verify signed commit on GitHub"
# Push to GitHub
git push
# Check on GitHub:
# - Go to the commit on GitHub's web interface
# - Should see "Verified" badge next to your commitgit sb # Short status
git recent # Recent branches
git lol # Visual log
git branches # Branch list with tracking# Already set to nvim in config, but you can change it:
git config --global core.editor "code --wait" # VS Code
git config --global core.editor "vim" # Vim
git config --global core.editor "nano" # Nano# VS Code as difftool
git config --global diff.tool vscode
git config --global difftool.vscode.cmd 'code --wait --diff $LOCAL $REMOTE'
# VS Code as mergetool
git config --global merge.tool vscode
git config --global mergetool.vscode.cmd 'code --wait --merge $REMOTE $LOCAL $BASE $MERGED'# Enable automatic background maintenance
git maintenance start
# This will optimize your repositories automatically:
# - Garbage collection
# - Commit-graph updates
# - Incremental repack[user]
name = Your Name
email = your.email@example.com
signingkey = ~/.ssh/id_ed25519.pubPurpose:
- name/email: Identity for all commits you make
- signingkey: Path to your SSH public key for signing commits
Why:
- Ensures proper attribution in git history
- SSH key signing is simpler than GPG (no key management complexity)
- Verified commits provide authenticity and non-repudiation
[commit]
gpgsign = true
verbose = true
template = ~/.config/git/commit-template.txt
cleanup = scissorsPurpose:
- gpgsign: Automatically sign all commits
- verbose: Show diff while writing commit message
- template: Pre-populate commit messages with template
- cleanup: Use scissors mode for cleaning commit messages
Why:
- Signed commits prove authorship and prevent impersonation
- Verbose mode helps write better commit messages by showing what changed
- Template enforces consistent commit message format (conventional commits)
- Scissors cleanup preserves content above scissors line, removes below
Template Format:
<type>(<scope>): <subject>
- Types: feat, fix, docs, style, refactor, perf, test, chore, build, ci
- Enforces conventional commits standard
- Improves changelog generation and semantic versioning
[gpg]
program = gpg
format = ssh
[gpg "ssh"]
allowedSignersFile = ~/.config/git/allowed_signers
defaultKeyCommand = ssh-add -LPurpose:
- format = ssh: Use SSH keys instead of GPG keys for signing
- allowedSignersFile: Verification of SSH signatures
- defaultKeyCommand: Automatically use SSH agent keys
Why:
- SSH signing is simpler than GPG (no separate keyring)
- Most developers already have SSH keys
- GitHub/GitLab support SSH signature verification
- SSH agent integration makes signing seamless
allowed_signers format:
your.email@example.com namespaces="git" ssh-ed25519 AAAAC3... your.email@example.com
This file allows git to verify your own signatures locally.
sb = status -sb # Short branch status
lol = log --oneline --graph --all # Visual commit graphWhy:
- sb: Cleaner, more readable status output
- lol: Visualize branch topology quickly
undo = reset HEAD~1 --mixed # Undo last commit, keep changes
amend = commit --amend --no-edit # Quick amend without changing message
fixup = commit --fixup # Create fixup commit for interactive rebaseWhy:
- undo: Safe way to uncommit (preserves working directory)
- amend: Quick fixes to last commit
- fixup: Part of interactive rebase workflow for clean history
gone = ! git fetch -p && git for-each-ref --format '%(refname:short) %(upstream:track)' | awk '$2 == "[gone]" {print $1}' | xargs -r git branch -D
branches = branch -vv
recent = branch --sort=-committerdate --format='%(committerdate:relative)%09%(refname:short)'Why:
- gone: Delete local branches whose remote has been deleted (cleanup after merged PRs)
- branches: See all branches with tracking info
- recent: Find branches you worked on recently (sorted by commit date)
staged = diff --cached # Show staged changes
last = log -1 HEAD --stat # Show last commit with stats
diffw = diff --word-diff # Word-level diff (better for prose)Why:
- staged: Preview what will be committed
- last: Quick review of what you just committed
- diffw: Better for reviewing documentation/text changes
unstage = restore --staged # Remove from staging area
discard = restore # Discard working directory changesWhy:
- Modern git commands (replace
reset HEADandcheckout --) - More intuitive naming
- Safer operations (less destructive defaults)
pushu = push -u origin HEAD # Push current branch and set upstream
sync = !git fetch --all --prune && git pull --rebase # Sync with remote
wip = commit -am "WIP" --no-verify # Quick work-in-progress commitWhy:
- pushu: Create remote branch automatically on first push
- sync: Update local repo with all remotes in one command
- wip: Quick save point (bypasses hooks for temporary commits)
grep = grep -Ii # Case-insensitive grep
find = log --all --full-history -- # Find file in history
contributors = shortlog -sn # Show commit counts by authorWhy:
- grep: Search codebase efficiently (case-insensitive)
- find: Locate deleted files or changes across all branches
- contributors: See team contribution metrics
[color]
ui = auto
[color "diff"]
meta = yellow bold
commit = green bold
frag = magenta bold
old = red bold
new = green bold
whitespace = red reverse
[color "branch"]
current = yellow reverse
local = yellow
remote = green
[color "status"]
added = green
changed = yellow
untracked = redPurpose:
- Enable automatic color in terminal output
- Customize colors for better readability
Why:
- Visual clarity: Quickly distinguish added/removed/modified
- Consistency: Same color scheme across all git commands
- Accessibility: Bold colors easier to see in various terminal themes
- Whitespace highlighting: Catch trailing spaces (red reverse)
[branch]
sort = -committerdate
[tag]
sort = version:refname
gpgsign = truePurpose:
- branch.sort: Show most recently committed branches first
- tag.sort: Sort tags by semantic version
- tag.gpgsign: Sign all tags automatically
Why:
- Recent branches are usually more relevant
- Version sorting shows v1.9.0 before v1.10.0 (not alphabetically)
- Signed tags provide release authenticity
[diff]
algorithm = histogram
colorMoved = plain
mnemonicPrefix = true
renames = true
tool = vimdiff
indentHeuristic = true
colorMovedWS = allow-indentation-change
submodule = log
[difftool]
prompt = false
trustExitCode = true
[diff "lockfile"]
textconv = cat
binary = truePurpose:
- algorithm = histogram: More accurate diff algorithm
- colorMoved: Highlight moved code blocks
- mnemonicPrefix: Use meaningful prefixes (i/, w/, c/ instead of a/, b/)
- renames: Detect renamed files
- indentHeuristic: Better diff chunk boundaries
- colorMovedWS: Ignore whitespace when detecting moves
- submodule = log: Show submodule changes as log entries
Why:
- Histogram algorithm: Better than Myers for most code (faster, more intuitive)
- Move detection: Refactoring shows as moves, not delete+add
- Mnemonic prefixes: i/ = index, w/ = working tree, c/ = commit (clearer context)
- Indent heuristic: Diffs break at logical boundaries (functions, classes)
- Lockfile handling: Treat as binary (they're generated, not meaningful to diff)
Tool Configuration:
- vimdiff: Powerful side-by-side diff viewer
- prompt = false: Don't ask before launching difftool
- trustExitCode: Honor tool's exit code for success/failure
[merge]
conflictstyle = zdiff3
tool = vimdiff
ff = only
[mergetool]
prompt = false
keepBackup = false
trustExitCode = truePurpose:
- conflictstyle = zdiff3: Show 3-way merge conflicts with common ancestor
- ff = only: Only allow fast-forward merges (prevent merge commits)
- keepBackup = false: Don't keep .orig files after merge
Why:
- zdiff3: Shows original code + both changes = easier conflict resolution
<<<<<<< HEAD your changes ||||||| base original code (this is the extra context!) ======= their changes >>>>>>> branch - ff = only: Enforces linear history (fails if fast-forward not possible)
- No backups: .orig files clutter working directory
- No prompt: Faster merge resolution workflow
[push]
autoSetupRemote = true
followTags = true
default = current
[fetch]
prune = true
pruneTags = true
fsckObjects = true
parallel = 0
writeCommitGraph = truePurpose:
- autoSetupRemote: Create remote branch on first push
- followTags: Push annotated tags with commits
- default = current: Push current branch to same name
- prune: Delete local references to deleted remote branches
- pruneTags: Delete local tags deleted on remote
- fsckObjects: Verify objects during fetch (detect corruption)
- parallel = 0: Auto-detect optimal parallel fetch count
- writeCommitGraph: Update commit graph on fetch
Why:
- autoSetupRemote: No need for
-u origin branchon first push - followTags: Releases (tags) are pushed with commits automatically
- Pruning: Keep local repo clean (no stale references)
- Integrity checks: Catch repository corruption early
- Parallel fetching: Faster fetches on multi-remote repos
- Commit graph: Faster log/blame operations after fetch
[core]
editor = nvim
excludesfile = ~/.gitignore_global
fsmonitor = true
untrackedCache = true
preloadIndex = true
commitGraph = true
multiPackIndex = true
[gc]
auto = 256
writeCommitGraph = true
[maintenance]
auto = true
strategy = incremental
[pack]
useSparse = true
writeReverseIndex = true
[index]
version = 4
[protocol]
version = 2Purpose:
- fsmonitor: Use filesystem events to track changes (faster status)
- untrackedCache: Cache untracked files (faster status)
- preloadIndex: Load index in parallel (faster operations)
- commitGraph: Accelerate commit traversal
- multiPackIndex: Faster object lookups in repos with many packfiles
- gc.auto = 256: Run garbage collection after 256 loose objects
- maintenance: Automatic background optimization
- pack optimizations: Faster clones and fetches
- index v4: Compressed index format
- protocol v2: Faster wire protocol
Why:
- Large repos: These settings make big repositories faster
- Background optimization: Maintenance runs automatically
- Modern git: Uses latest performance features
- Minimal overhead: All settings are backwards compatible
Performance Impact:
git statusup to 10x faster on large reposgit logandgit blamesignificantly faster- Reduced disk space usage
- Better clone/fetch performance
[help]
autocorrect = prompt
[rerere]
enabled = true
autoupdate = true
[rebase]
autoSquash = true
autoStash = true
updateRefs = true
[pull]
rebase = true
[status]
showUntrackedFiles = all
submoduleSummary = true
[log]
abbrevCommit = true
follow = true
decorate = auto
date = relative
[submodule]
recurse = true
[blame]
ignoreRevsFile = .git-blame-ignore-revs
markIgnoredLines = true
markUnblamableLines = truePurpose & Why:
- Suggests corrections for typos:
git comit→ prompt to rungit commit - Safer than
autocorrect = 1(auto-runs after 1 second)
- enabled: Records how you resolved merge conflicts
- autoupdate: Automatically applies previously learned resolutions
- Why: If you rebase and get the same conflict twice, it auto-resolves the second time
- autoSquash: Automatically arrange
fixup!commits during interactive rebase - autoStash: Stash changes before rebase, apply after
- updateRefs: Update all branches pointing to rebased commits
- Why: Cleaner rebase workflow, less manual work
- Always rebase instead of merge when pulling
- Why: Linear history, no merge commits from
git pull
- showUntrackedFiles = all: Show all files in untracked directories
- submoduleSummary: Show submodule changes in status
- Why: Better visibility of repository state
- abbrevCommit: Show short commit hashes (7 chars)
- follow: Track file renames in log
- decorate: Show branch/tag names in log
- date = relative: "2 hours ago" instead of timestamps
- Why: More readable, informative output
- Automatically recurse into submodules for all commands
- Why: Submodules stay in sync with parent repo
- ignoreRevsFile: Ignore bulk formatting commits in blame
- markIgnoredLines: Mark lines from ignored commits
- Why:
git blameshows who actually wrote the code, not who ran Prettier
[transfer]
fsckObjects = true
[receive]
fsckObjects = true
[url "https://github.com/"]
insteadOf = git://github.com/
[url "https://"]
insteadOf = git://
[url "ssh://git@github.com/"]
pushInsteadOf = https://github.com/Purpose:
- fsckObjects: Verify object integrity during transfer
- URL rewrites: Force HTTPS/SSH, block insecure git:// protocol
Why:
- Corruption detection: Catch corrupted objects during push/pull
- Security: git:// protocol is unencrypted and unauthenticated
- Best practice: Always use HTTPS for fetching, SSH for pushing
- GitHub optimization: Uses SSH for push (faster, more reliable)
Attack prevention:
- Man-in-the-middle attacks (git:// protocol)
- Repository corruption
- Malicious object injection
[init]
defaultBranch = main
[feature]
manyFiles = true
[filter "lfs"]
process = git-lfs filter-process
required = true
clean = git-lfs clean -- %f
smudge = git-lfs smudge -- %f
[column]
ui = autoPurpose:
- defaultBranch = main: Use "main" instead of "master" for new repos
- manyFiles: Optimize for repositories with many files
- lfs: Git Large File Storage support
- column.ui: Use columns in output when space permits
Why:
- main: Industry standard, inclusive naming
- manyFiles: Better performance for monorepos
- LFS: Required for binary assets, datasets, media files
- Columns: More compact output in wide terminals
File: ~/.config/git/ignore
- OS files: .DS_Store, Thumbs.db, desktop.ini
- IDEs: .vscode/, .idea/, *.swp
- Dependencies: node_modules/, vendor/, .venv/
- Secrets: .env, _.key, _.pem, credentials.json
- Build artifacts: dist/, build/, target/, *.egg-info/
- DevOps: .terraform/, *.tfstate, docker-compose.override.yml
- Languages: pycache/, _.pyc, _.class, *.o
Why:
- Never commit secrets: Prevent credential leaks
- Clean repos: Don't commit generated files
- Universal: Applies to all your repositories
- Team safety: Even if .gitignore is incomplete
File: ~/.config/git/attributes
* text=auto # Auto-detect text files
*.js text eol=lf # Force LF line endings
*.png binary # Mark as binary
package-lock.json binary # Don't diff lockfilesPurpose:
- Line ending normalization: Consistent LF across platforms
- Binary file detection: Don't diff images/binaries
- Merge strategies: Special handling for lockfiles
Why:
- Cross-platform: Windows/Mac/Linux consistency
- Clean diffs: No "entire file changed" due to line endings
- Lockfile handling: Merge lockfiles correctly (union strategy)
- Performance: Don't waste time diffing binary files
- Share
allowed_signersfile (add team keys) - Agree on
.git-blame-ignore-revsfor formatting commits - Use same
commit-template.txtfor consistency - Document custom aliases in team wiki
- Enable
core.fsmonitor(requires watchman or built-in) - Use
git maintenance startfor background optimization - Consider partial clone:
git clone --filter=blob:none - Use sparse checkout for monorepos
- ✅ All commits signed
- ✅ git:// protocol blocked
- ✅ Secrets in global ignore
- ✅ fsckObjects enabled
- ✅ SSH key in ssh-agent
# Verify SSH key is loaded
ssh-add -L
# Test signing
git commit --allow-empty -m "test" -S
# Check allowed_signers format
cat ~/.config/git/allowed_signers# Run maintenance
git maintenance run --task=gc
# Check repository health
git fsck
# Rebuild commit graph
git commit-graph write --reachable# Verify vimdiff is available
which vimdiff
# Or use vscode
git config --global merge.tool vscode
git config --global mergetool.vscode.cmd 'code --wait --merge $REMOTE $LOCAL $BASE $MERGED'This configuration is free to use and modify. Attribution appreciated but not required.
