| name | Git |
| description | Git version control best practices and workflows. USE WHEN working with git commands, commits, branches, pull requests, rebasing, or version control operations. |
Git Best Practices
Purpose
Guide git usage following best practices, conventional commits, and project-specific workflows.
Context Detection
This skill activates when:
- Current directory is a git repository (contains
.git/) or in a git repository - User asks about git commands, commits, branches, or version control
- User mentions workflows like rebasing, merging, cherry-picking
- Commands like
git commit,git rebase,git mergeare mentioned - User asks about commit messages or git best practices
Workflow Routing
When the user's request matches specific Git operations, route to the appropriate workflow:
| Workflow | Trigger | File |
|---|---|---|
| Commit | "create commit", "commit changes", "write commit message", "amend commit" | workflows/Commit.md |
| Branch | "create branch", "switch branches", "delete branch", "branch management" | workflows/Branch.md |
| Rebase | "rebase branch", "interactive rebase", "clean up commits", "squash commits" | workflows/Rebase.md |
| Merge | "merge branch", "merge conflicts", "resolve conflicts", "merge strategies" | workflows/Merge.md |
| Stash | "stash changes", "save work in progress", "temporarily save", "switch branches" | workflows/Stash.md |
| Bisect | "find bad commit", "when did this break", "regression debugging", "binary search" | workflows/Bisect.md |
| Worktree | "multiple branches", "parallel development", "work on multiple branches" | workflows/Worktree.md |
| Cherry-Pick | "cherry pick", "apply specific commit", "copy commit", "backport fix" | workflows/Cherry.md |
| Reset | "undo commit", "reset branch", "discard changes", "move branch pointer" | workflows/Reset.md |
When to use workflows:
- Route when the user explicitly asks about one of these operations
- Workflows provide comprehensive, focused guidance for specific Git tasks
- For general git advice or commit creation, continue with this main skill
Commit Message Philosophy
Focus on WHY, not WHAT
The code diff shows WHAT changed. Your commit message should explain WHY it changed and WHAT IMPACT it has.
Good Example
feat: Add user authentication system
- Enable secure user sessions for multi-user support
- Prevent unauthorized API access with JWT validation
- Establish foundation for role-based permissions
Bad Example
feat: Add auth
- Added login.ts file
- Added middleware
- Added tests
Commit Message Format
Structure
<type>: <short description (max 80 chars)>
- <bullet point describing impact/reason>
- <bullet point describing impact/reason>
- <bullet point describing impact/reason>
Signed-off-by: Vincent Demeester <vincent@sbr.pm>
Co-Authored-By: Claude <noreply@anthropic.com>
Commit Types
- feat: New feature or capability
- fix: Bug fix
- chore: Maintenance, dependencies, tooling
- docs: Documentation only
- refactor: Code restructuring without behavior change
- test: Adding or updating tests
- perf: Performance improvement
- style: Code style/formatting (not visual style)
- ci: CI/CD pipeline changes
Guidelines
First Line:
- Clear, concise summary under 80 characters
- Use imperative mood ("Add", "Fix", "Update", not "Added", "Fixed")
- Start with commit type
Bullet Points:
- 2-3 bullets maximum (not more)
- Each bullet under 80 characters
- Focus on WHY and IMPACT, not WHAT
- Explain the reasoning and consequences
- Think: "What problem does this solve?"
Mandatory Commit Requirements
Always Include
--signoff: ALWAYS use the
--signoffflaggit commit --signoff -m "message"This adds:
Signed-off-by: Vincent Demeester <vincent@sbr.pm>Co-Authored-By: When working with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
Never Include
❌ NO EMOJIS: Never use 🚀, ✨, 🎉, or any emojis in commit messages
- Keep commits professional
- Emojis don't add value and can cause encoding issues
- Focus on clear, descriptive text
Commit Best Practices
1. Atomic Commits
- One logical change per commit
- Commits should be self-contained and reversible
- If you can't describe it in one sentence, it's too big
2. Review Before Committing
# Always review what's staged
git diff --staged
# Check each file individually
git diff --staged src/auth/login.ts
# Verify no secrets
grep -r "API_KEY\|SECRET\|PASSWORD" .
3. One Concern Per Commit
❌ Bad: Multiple unrelated changes
git add src/auth/ src/ui/ docs/
git commit -m "Updates"
✅ Good: Focused, logical commits
git add src/auth/
git commit --signoff -m "feat: Add JWT authentication"
git add src/ui/
git commit --signoff -m "feat: Add login form component"
git add docs/
git commit --signoff -m "docs: Document authentication flow"
Commit Message Examples
Feature
feat: Implement user authentication
- Enable secure multi-user sessions with JWT
- Prevent unauthorized access to protected routes
- Lay groundwork for role-based access control
Signed-off-by: Vincent Demeester <vincent@sbr.pm>
Co-Authored-By: Claude <noreply@anthropic.com>
Bug Fix
fix: Prevent null pointer in user validation
- Resolve crashes when user object is undefined
- Ensure defensive checks at API boundaries
Signed-off-by: Vincent Demeester <vincent@sbr.pm>
Co-Authored-By: Claude <noreply@anthropic.com>
Refactoring
refactor: Simplify error handling in API layer
- Reduce code duplication across endpoints
- Improve error message clarity for debugging
- Make error handling more maintainable
Signed-off-by: Vincent Demeester <vincent@sbr.pm>
Co-Authored-By: Claude <noreply@anthropic.com>
Chore
chore: Update dependencies and resolve warnings
- Address security vulnerabilities in npm packages
- Fix ESLint warnings for cleaner codebase
Signed-off-by: Vincent Demeester <vincent@sbr.pm>
Co-Authored-By: Claude <noreply@anthropic.com>
Creating Commits with HEREDOC
To ensure proper formatting with multi-line messages:
git commit --signoff --message "$(cat <<'EOF'
feat: Add user authentication system
- Enable secure user sessions for multi-user support
- Prevent unauthorized API access with JWT validation
- Establish foundation for role-based permissions
Co-Authored-By: Claude <noreply@anthropic.com>
EOF
)"
Why HEREDOC?
- Ensures proper multi-line formatting
- Prevents shell escaping issues
- Preserves formatting exactly as written
Branch Management
Naming Conventions
feature/<description> # New features
fix/<description> # Bug fixes
chore/<description> # Maintenance
docs/<description> # Documentation
refactor/<description> # Refactoring
Examples:
feature/user-authenticationfix/null-pointer-validationchore/update-dependencies
Branch Workflow
Prefer Worktrees for Significant Work
For substantial changes (new features, bug fixes, refactoring), use Git worktrees instead of branch switching:
# Instead of switching branches
git checkout -b feature/user-auth # ❌ Old approach
# Create worktree for new work
git worktree add ../myproject-user-auth -b feature/user-auth # ✅ Better
# Now you have:
# ~/projects/myproject/ (main branch - continue current work)
# ~/projects/myproject-user-auth/ (feature branch - new work)
Why worktrees?
- No context switching - keep current work untouched
- No stashing needed - both codebases available simultaneously
- Run tests on both versions in parallel
- Easier to compare implementations side-by-side
- Faster than switching branches (no index/working directory updates)
When to use worktrees:
- ✅ Starting new feature development
- ✅ Fixing bugs that need testing
- ✅ Code review (checkout PR in separate worktree)
- ✅ Comparing implementations
- ✅ Long-running work that might be interrupted
When branch switching is fine:
- Small, quick changes
- Documentation updates
- Trivial fixes
See workflows/Worktree.md for comprehensive worktree guidance.
Traditional Branch Workflow (for quick changes)
# Create feature branch
git checkout -b feature/user-auth
# Make changes and commit
git add src/auth/
git commit --signoff -m "feat: Add JWT authentication"
# Keep updated with main (rebase, don't merge)
git fetch origin
git rebase origin/main
# Push to remote
git push -u origin feature/user-auth
Amending Commits
When to Amend
✅ Safe to amend:
- Last commit
- Not yet pushed
- You are the author
❌ Never amend:
- Commits already pushed to shared branches
- Commits authored by someone else
- Commits on main/master
How to Amend
# Check authorship first
git log -1 --format='%an %ae'
# Verify not pushed
git status # Should show "Your branch is ahead"
# Amend if both conditions true
git add forgotten-file.ts
git commit --amend --no-edit
# Or change message
git commit --amend
Rebasing
Interactive Rebase
# Clean up last 3 commits
git rebase -i HEAD~3
# In editor:
# pick - keep commit as-is
# reword - change commit message
# squash - merge into previous commit (keep message)
# fixup - merge into previous commit (discard message)
# drop - remove commit
Rebase on Main
# Update feature branch with latest main
git fetch origin
git rebase origin/main
# If conflicts occur
git status # See conflicting files
# Edit files to resolve
git add <resolved-files>
git rebase --continue
# Or abort if needed
git rebase --abort
Stashing
# Save work in progress
git stash push -m "WIP: refactoring auth"
# List stashes
git stash list
# Apply and remove
git stash pop
# Apply without removing
git stash apply stash@{0}
# Drop a stash
git stash drop stash@{0}
Pull Requests
Creating PRs
# Ensure branch is up to date
git fetch origin
git rebase origin/main
# Push to remote
git push -u origin feature/my-feature
# Create PR (using gh CLI)
gh pr create --title "feat: Add user authentication" --body "$(cat <<'EOF'
## Summary
- Enable secure user sessions for multi-user support
- Prevent unauthorized API access with JWT validation
- Establish foundation for role-based permissions
## Test plan
- [ ] Test user login flow
- [ ] Test token validation
- [ ] Test unauthorized access prevention
EOF
)"
PR Best Practices
- One PR = One Feature: Keep PRs focused
- Small PRs: Easier to review, faster to merge
- Clean commits: Squash fixup commits before merging
- Update regularly: Rebase on main frequently
- Respond to reviews: Address feedback promptly
Pre-commit Hooks
The home repository uses pre-commit hooks for:
- nixfmt-rfc-style: Nix formatting
- deadnix: Remove dead Nix code
- gofmt: Go formatting
- shellcheck: Shell script linting
- flake8, ruff: Python linting
If Hooks Fail
# Format files
make fmt
# Re-add specific formatted files and commit
git add path/to/formatted/file.nix
git commit --signoff -m "your message"
Common Workflows
Feature Development (Recommended: Use Worktree)
# 1. Create worktree for new feature
git worktree add ../myproject-new-feature -b feature/new-feature
cd ../myproject-new-feature
# 2. Make changes and commit atomically
git add src/module1/
git commit --signoff -m "feat: Add module1 functionality"
git add src/module2/
git commit --signoff -m "feat: Add module2 integration"
# 3. Keep updated
git fetch origin
git rebase origin/main
# 4. Push
git push -u origin feature/new-feature
# 5. Create PR
gh pr create
# 6. When done, remove worktree
cd ~/projects/myproject
git worktree remove ../myproject-new-feature
Fixing a Bug (Recommended: Use Worktree)
# 1. Create worktree for bug fix
git worktree add ../myproject-bugfix -b fix/null-pointer-crash
cd ../myproject-bugfix
# 2. Commit the fix
git add src/validation.ts
git commit --signoff -m "fix: Prevent null pointer in user validation
- Resolve crashes when user object is undefined
- Ensure defensive checks at API boundaries
"
# 3. Push and create PR
git push -u origin fix/null-pointer-crash
gh pr create
# 4. When done, remove worktree
cd ~/projects/myproject
git worktree remove ../myproject-bugfix
Troubleshooting
Undo Last Commit (Keep Changes)
git reset --soft HEAD~1
Undo Last Commit (Discard Changes)
git reset --hard HEAD~1
Fix Wrong Branch
# Committed to main instead of feature branch
git branch feature/new-work
git reset --hard origin/main
git checkout feature/new-work
Recover Deleted Commit
# Find lost commit
git reflog
# Restore it
git checkout <commit-hash>
git checkout -b recovered-branch
Remove File from Staging
git reset HEAD file.txt
Git Configuration
Required Settings
# User identity (required for --signoff)
git config --global user.name "Vincent Demeester"
git config --global user.email "vincent@sbr.pm"
Recommended Settings
# Default branch name
git config --global init.defaultBranch main
# Rebase by default when pulling
git config --global pull.rebase true
# Prune on fetch
git config --global fetch.prune true
# Better diff output
git config --global diff.algorithm histogram
# Show original in merge conflicts
git config --global merge.conflictstyle diff3
Preferred Method: Use /git-commit:commit Command
IMPORTANT: When creating commits, ALWAYS prefer using the /git-commit:commit slash command instead of running git commit directly.
The /git-commit:commit slash command provides a guided workflow:
- Parallel information gathering - Fast git status, diff, log
- File-by-file review - Understand each change
- Commit message creation - Focus on WHY and impact
- User approval - Explicit confirmation before committing
- Smart push offer - Automatic push handling
- Explicit file staging - Never uses
git add -Aorgit add .
The command follows all the best practices in this skill and ensures:
- Proper
--signoffusage Co-Authored-By: Claudeattribution- No emojis
- Focus on WHY over WHAT
- Atomic, well-structured commits
- Explicit file staging (never adds all files blindly)
When to use it:
- Creating any new commit
- Committing staged or unstaged changes
- Need to review changes before committing
When you can use git directly:
- Amending the last commit (
git commit --amend) - Specific git operations like rebase, cherry-pick, etc.
Anti-Patterns to Avoid
❌ Vague Messages
git commit -m "Update code"
git commit -m "Fix stuff"
git commit -m "WIP"
❌ Including Emojis
git commit -m "✨ Add new feature" # NO!
git commit -m "🚀 Deploy changes" # NO!
❌ Describing WHAT Instead of WHY
git commit -m "feat: Add login function
- Created login.ts
- Added handleLogin method
- Imported jwt library
"
❌ Force Pushing to Shared Branches
git push --force origin main # NEVER!
❌ Using git add -A or git add .
git add -A # NEVER! Too broad, adds everything
git add . # NEVER! Too broad, adds everything
Why to avoid:
- Adds ALL changes including unintended files
- Can include generated files (build outputs, dependencies)
- Can include sensitive files (.env, credentials)
- Bypasses intentional staging control
- Makes commits less atomic and focused
✅ Instead, explicitly add files or directories:
git add src/auth/
git add docs/authentication.md
git add tests/auth.test.ts
❌ Committing Secrets
git add .env # Check for secrets first!
git add config/credentials.json # NO!
Summary
Key Takeaways:
- ✅ ALWAYS use
--signoff - ✅ Include
Co-Authored-By: Claudewhen working with AI - ❌ NEVER use emojis in commit messages
- ❌ NEVER use
git add -Aorgit add .- always add files explicitly - ✅ Focus on WHY and IMPACT, not WHAT
- ✅ Keep commits atomic - one logical change per commit
- ✅ Use HEREDOC for multi-line commit messages
- ✅ Rebase, don't merge when updating feature branches
- ✅ Review before committing - check diffs and verify no secrets
- ✅ 2-3 bullet points maximum, each under 80 chars
- ✅ Test before committing - run pre-commit checks
Remember: Future you will thank present you for clear, descriptive commit messages that explain WHY changes were made!
Examples
Example 1: Making a clean commit
User: "Commit the authentication changes"
→ Reviews git diff to understand changes
→ Adds files explicitly: git add src/auth/ tests/auth.test.ts
→ Creates commit with HEREDOC format
→ Includes --signoff and Co-Authored-By: Claude
→ Uses 2-3 bullet points explaining WHY changes were made
→ Result: Clean, well-documented commit ready to push
Example 2: Rebasing a feature branch
User: "Update my feature branch with latest main"
→ Checks current branch status
→ Fetches latest changes: git fetch origin main
→ Rebases instead of merging: git rebase origin/main
→ Resolves any conflicts interactively
→ Force-pushes with lease: git push --force-with-lease
→ Result: Clean linear history without merge commits
Example 3: Avoiding common mistakes
User: "Add all changes and commit"
→ STOPS user from using git add -A or git add .
→ Reviews git status to see what changed
→ Adds files explicitly by directory/path
→ Warns if .env or credentials files are staged
→ Creates proper commit message without emojis
→ Result: Safe, intentional commit with no secrets