git-master
Git Mastery - Complete Git Expertise
šØ CRITICAL GUIDELINES
Windows File Path Requirements
MANDATORY: Always Use Backslashes on Windows for File Paths
When using Edit or Write tools on Windows, you MUST use backslashes (\) in file paths, NOT forward slashes (/).
Examples:
- ā WRONG:
D:/repos/project/file.tsx - ā
CORRECT:
D:\repos\project\file.tsx
This applies to:
- Edit tool file_path parameter
- Write tool file_path parameter
- All file operations on Windows systems
Documentation Guidelines
NEVER create new documentation files unless explicitly requested by the user.
- Priority: Update existing README.md files rather than creating new documentation
- Repository cleanliness: Keep repository root clean - only README.md unless user requests otherwise
- Style: Documentation should be concise, direct, and professional - avoid AI-generated tone
- User preference: Only create additional .md files when user specifically asks for documentation
Comprehensive guide for ALL Git operations from basic to advanced, including dangerous operations with safety guardrails.
TL;DR QUICK REFERENCE
Safety First - Before ANY Destructive Operation:
# ALWAYS check status first
git status
git log --oneline -10
# For risky operations, create a safety branch
git branch backup-$(date +%Y%m%d-%H%M%S)
# Remember: git reflog is your safety net (90 days default)
git reflog
User Preference Check:
- ALWAYS ASK: "Would you like me to create commits automatically, or would you prefer to handle commits manually?"
- Respect user's choice throughout the session
Overview
This skill provides COMPLETE Git expertise for ANY Git operation, no matter how advanced, niche, or risky. It covers:
MUST use this skill for:
- ā ANY Git command or operation
- ā Repository initialization, cloning, configuration
- ā Branch management and strategies
- ā Commit workflows and best practices
- ā Merge strategies and conflict resolution
- ā Rebase operations (interactive and non-interactive)
- ā History rewriting (filter-repo, reset, revert)
- ā Recovery operations (reflog, fsck)
- ā Dangerous operations (force push, hard reset)
- ā Platform-specific workflows (GitHub, Azure DevOps, Bitbucket)
- ā Advanced features (submodules, worktrees, hooks)
- ā Performance optimization
- ā Cross-platform compatibility (Windows/Linux/macOS)
Core Principles
1. Safety Guardrails for Destructive Operations
CRITICAL: Before ANY destructive operation (reset --hard, force push, filter-repo, etc.):
- Always warn the user explicitly
- Explain the risks clearly
- Ask for confirmation
- Suggest creating a backup branch first
- Provide recovery instructions
# Example safety pattern for dangerous operations
echo "ā ļø WARNING: This operation is DESTRUCTIVE and will:"
echo " - Permanently delete uncommitted changes"
echo " - Rewrite Git history"
echo " - [specific risks for the operation]"
echo ""
echo "Safety recommendation: Creating backup branch first..."
git branch backup-before-reset-$(date +%Y%m%d-%H%M%S)
echo ""
echo "To recover if needed: git reset --hard backup-before-reset-XXXXXXXX"
echo ""
read -p "Are you SURE you want to proceed? (yes/NO): " confirm
if [[ "$confirm" != "yes" ]]; then
echo "Operation cancelled."
exit 1
fi
2. Commit Creation Policy
ALWAYS ASK at the start of ANY Git task: "Would you like me to:
- Create commits automatically with appropriate messages
- Stage changes only (you handle commits manually)
- Just provide guidance (no automatic operations)"
Respect this choice throughout the session.
3. Platform Awareness
Git behavior and workflows differ across platforms and hosting providers:
Windows (Git Bash/PowerShell):
- Line ending handling (core.autocrlf)
- Path separators and case sensitivity
- Credential management (Windows Credential Manager)
Linux/macOS:
- Case-sensitive filesystems
- SSH key management
- Permission handling
Hosting Platforms:
- GitHub: Pull requests, GitHub Actions, GitHub CLI
- Azure DevOps: Pull requests, Azure Pipelines, policies
- Bitbucket: Pull requests, Bitbucket Pipelines, Jira integration
- GitLab: Merge requests, GitLab CI/CD
Basic Git Operations
Repository Initialization and Cloning
# Initialize new repository
git init
git init --initial-branch=main # Specify default branch name
# Clone repository
git clone <url>
git clone <url> <directory>
git clone --depth 1 <url> # Shallow clone (faster, less history)
git clone --branch <branch> <url> # Clone specific branch
git clone --recurse-submodules <url> # Include submodules
Configuration
# User identity (required for commits)
git config --global user.name "Your Name"
git config --global user.email "your.email@example.com"
# Default branch name
git config --global init.defaultBranch main
# Line ending handling (Windows)
git config --global core.autocrlf true # Windows
git config --global core.autocrlf input # macOS/Linux
# Editor
git config --global core.editor "code --wait" # VS Code
git config --global core.editor "vim"
# Diff tool
git config --global diff.tool vscode
git config --global difftool.vscode.cmd 'code --wait --diff $LOCAL $REMOTE'
# Merge tool
git config --global merge.tool vscode
git config --global mergetool.vscode.cmd 'code --wait $MERGED'
# Aliases
git config --global alias.st status
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.ci commit
git config --global alias.unstage 'reset HEAD --'
git config --global alias.last 'log -1 HEAD'
git config --global alias.visual '!gitk'
# View configuration
git config --list
git config --global --list
git config --local --list
git config user.name # Get specific value
Basic Workflow
# Check status
git status
git status -s # Short format
git status -sb # Short with branch info
# Add files
git add <file>
git add . # Add all changes in current directory
git add -A # Add all changes in repository
git add -p # Interactive staging (patch mode)
# Remove files
git rm <file>
git rm --cached <file> # Remove from index, keep in working directory
git rm -r <directory>
# Move/rename files
git mv <old> <new>
# Commit
git commit -m "message"
git commit -am "message" # Add and commit tracked files
git commit --amend # Amend last commit
git commit --amend --no-edit # Amend without changing message
git commit --allow-empty -m "message" # Empty commit (useful for triggers)
# View history
git log
git log --oneline
git log --graph --oneline --all --decorate
git log --stat # Show file statistics
git log --patch # Show diffs
git log -p -2 # Show last 2 commits with diffs
git log --since="2 weeks ago"
git log --until="2025-01-01"
git log --author="Name"
git log --grep="pattern"
git log -- <file> # History of specific file
git log --follow <file> # Follow renames
# Show changes
git diff # Unstaged changes
git diff --staged # Staged changes
git diff HEAD # All changes since last commit
git diff <branch> # Compare with another branch
git diff <commit1> <commit2>
git diff <commit> # Changes since specific commit
git diff <branch1>...<branch2> # Changes between branches
# Show commit details
git show <commit>
git show <commit>:<file> # Show file at specific commit
Branch Management
Creating and Switching Branches
# List branches
git branch # Local branches
git branch -r # Remote branches
git branch -a # All branches
git branch -v # With last commit info
git branch -vv # With tracking info
# Create branch
git branch <branch-name>
git branch <branch-name> <start-point> # From specific commit/tag
# Switch branch
git switch <branch-name>
git checkout <branch-name> # Old syntax, still works
# Create and switch
git switch -c <branch-name>
git checkout -b <branch-name>
git switch -c <branch-name> <start-point>
# Delete branch
git branch -d <branch-name> # Safe delete (only if merged)
git branch -D <branch-name> # Force delete (even if not merged)
# Rename branch
git branch -m <old-name> <new-name>
git branch -m <new-name> # Rename current branch
# Set upstream tracking
git branch --set-upstream-to=origin/<branch>
git branch -u origin/<branch>
Branch Strategies
Git Flow:
main/master: Production-ready codedevelop: Integration branch for featuresfeature/*: New featuresrelease/*: Release preparationhotfix/*: Production fixes
GitHub Flow:
main: Always deployablefeature/*: Short-lived feature branches- Create PR, review, merge
Trunk-Based Development:
main: Single branch- Short-lived feature branches (< 1 day)
- Feature flags for incomplete features
GitLab Flow:
- Environment branches:
production,staging,main - Feature branches merge to
main - Deploy from environment branches
Merging and Rebasing
Merge Strategies
# Fast-forward merge (default if possible)
git merge <branch>
# Force merge commit (even if fast-forward possible)
git merge --no-ff <branch>
# Squash merge (combine all commits into one)
git merge --squash <branch>
# Then commit manually: git commit -m "Merged feature X"
# Merge with specific strategy
git merge -s recursive <branch> # Default strategy
git merge -s ours <branch> # Always use "our" version
git merge -s theirs <branch> # Always use "their" version (requires merge-theirs)
git merge -s octopus <branch1> <branch2> <branch3> # Merge multiple branches
# Merge with strategy options
git merge -X ours <branch> # Prefer "our" changes in conflicts
git merge -X theirs <branch> # Prefer "their" changes in conflicts
git merge -X ignore-all-space <branch>
git merge -X ignore-space-change <branch>
# Abort merge
git merge --abort
# Continue after resolving conflicts
git merge --continue
Conflict Resolution
# When merge conflicts occur
git status # See conflicted files
# Conflict markers in files:
# <<<<<<< HEAD
# Your changes
# =======
# Their changes
# >>>>>>> branch-name
# Resolve conflicts manually, then:
git add <resolved-file>
git commit # Complete the merge
# Use mergetool
git mergetool
# Accept one side completely
git checkout --ours <file> # Keep our version
git checkout --theirs <file> # Keep their version
git add <file>
# View conflict diff
git diff # Show conflicts
git diff --ours # Compare with our version
git diff --theirs # Compare with their version
git diff --base # Compare with base version
# List conflicts
git diff --name-only --diff-filter=U
Rebase Operations
ā ļø WARNING: Rebase rewrites history. Never rebase commits that have been pushed to shared branches!
# Basic rebase
git rebase <base-branch>
git rebase origin/main
# Interactive rebase (POWERFUL)
git rebase -i <base-commit>
git rebase -i HEAD~5 # Last 5 commits
# Interactive rebase commands:
# p, pick = use commit
# r, reword = use commit, but edit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like squash, but discard commit message
# x, exec = run command (rest of line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop = remove commit
# l, label = label current HEAD with a name
# t, reset = reset HEAD to a label
# Rebase onto different base
git rebase --onto <new-base> <old-base> <branch>
# Continue after resolving conflicts
git rebase --continue
# Skip current commit
git rebase --skip
# Abort rebase
git rebase --abort
# Preserve merge commits
git rebase --preserve-merges <base> # Deprecated
git rebase --rebase-merges <base> # Modern approach
# Autosquash (with fixup commits)
git commit --fixup <commit>
git rebase -i --autosquash <base>
Cherry-Pick
# Apply specific commit to current branch
git cherry-pick <commit>
# Cherry-pick multiple commits
git cherry-pick <commit1> <commit2>
git cherry-pick <commit1>..<commit5>
# Cherry-pick without committing
git cherry-pick -n <commit>
git cherry-pick --no-commit <commit>
# Continue after resolving conflicts
git cherry-pick --continue
# Abort cherry-pick
git cherry-pick --abort
Remote Operations
Remote Management
# List remotes
git remote
git remote -v # With URLs
# Add remote
git remote add <name> <url>
git remote add origin https://github.com/user/repo.git
# Change remote URL
git remote set-url <name> <new-url>
# Remove remote
git remote remove <name>
git remote rm <name>
# Rename remote
git remote rename <old> <new>
# Show remote info
git remote show <name>
git remote show origin
# Prune stale remote branches
git remote prune origin
git fetch --prune
Fetch and Pull
# Fetch from remote (doesn't merge)
git fetch
git fetch origin
git fetch --all # All remotes
git fetch --prune # Remove stale remote-tracking branches
# Pull (fetch + merge)
git pull
git pull origin <branch>
git pull --rebase # Fetch + rebase instead of merge
git pull --no-ff # Always create merge commit
git pull --ff-only # Only if fast-forward possible
# Set default pull behavior
git config --global pull.rebase true # Always rebase
git config --global pull.ff only # Only fast-forward
Push
# Push to remote
git push
git push origin <branch>
git push origin <local-branch>:<remote-branch>
# Push new branch and set upstream
git push -u origin <branch>
git push --set-upstream origin <branch>
# Push all branches
git push --all
# Push tags
git push --tags
git push origin <tag-name>
# Delete remote branch
git push origin --delete <branch>
git push origin :<branch> # Old syntax
# Delete remote tag
git push origin --delete <tag>
git push origin :refs/tags/<tag>
# ā ļø DANGEROUS: Force push (overwrites remote history)
# ALWAYS ASK USER FOR CONFIRMATION FIRST
git push --force
git push -f
# ā ļø SAFER: Force push with lease (fails if remote updated)
git push --force-with-lease
git push --force-with-lease=<ref>:<expected-value>
Force Push Safety Protocol:
Before ANY force push, execute this safety check:
echo "ā ļø DANGER: Force push will overwrite remote history!"
echo ""
echo "Remote branch status:"
git fetch origin
git log --oneline origin/<branch> ^<branch> --decorate
if [ -z "$(git log --oneline origin/<branch> ^<branch>)" ]; then
echo "ā No commits will be lost (remote is behind local)"
else
echo "ā WARNING: Remote has commits that will be LOST:"
git log --oneline --decorate origin/<branch> ^<branch>
echo ""
echo "These commits from other developers will be destroyed!"
fi
echo ""
echo "Consider using --force-with-lease instead of --force"
echo ""
read -p "Type 'force push' to confirm: " confirm
if [[ "$confirm" != "force push" ]]; then
echo "Cancelled."
exit 1
fi
Advanced Commands
Stash
# Stash changes
git stash
git stash save "message"
git stash push -m "message"
# Stash including untracked files
git stash -u
git stash --include-untracked
# Stash including ignored files
git stash -a
git stash --all
# List stashes
git stash list
# Show stash contents
git stash show
git stash show -p # With diff
git stash show stash@{2}
# Apply stash (keep in stash list)
git stash apply
git stash apply stash@{2}
# Pop stash (apply and remove)
git stash pop
git stash pop stash@{2}
# Drop stash
git stash drop
git stash drop stash@{2}
# Clear all stashes
git stash clear
# Create branch from stash
git stash branch <branch-name>
git stash branch <branch-name> stash@{1}
# Git 2.51+ : Import/Export stashes (share stashes between machines)
# Export stash to a file
git stash store --file=stash.patch stash@{0}
# Import stash from a file
git stash import --file=stash.patch
# Share stashes like branches/tags
git stash export > my-stash.patch
git stash import < my-stash.patch
Reset
ā ļø WARNING: reset can permanently delete changes!
# Soft reset (keep changes staged)
git reset --soft <commit>
git reset --soft HEAD~1 # Undo last commit, keep changes staged
# Mixed reset (default - keep changes unstaged)
git reset <commit>
git reset HEAD~1 # Undo last commit, keep changes unstaged
# ā ļø HARD reset (DELETE all changes - DANGEROUS!)
# ALWAYS create backup branch first!
git branch backup-$(date +%Y%m%d-%H%M%S)
git reset --hard <commit>
git reset --hard HEAD~1 # Undo last commit and DELETE all changes
git reset --hard origin/<branch> # Reset to remote state
# Unstage files
git reset HEAD <file>
git reset -- <file>
# Reset specific file to commit
git checkout <commit> -- <file>
Revert
# Revert commit (creates new commit that undoes changes)
# Safer than reset for shared branches
git revert <commit>
# Revert without creating commit
git revert -n <commit>
git revert --no-commit <commit>
# Revert merge commit
git revert -m 1 <merge-commit> # Keep first parent
git revert -m 2 <merge-commit> # Keep second parent
# Revert multiple commits
git revert <commit1> <commit2>
git revert <commit1>..<commit5>
# Continue after resolving conflicts
git revert --continue
# Abort revert
git revert --abort
Reflog (Recovery)
reflog is your safety net - it tracks all HEAD movements for 90 days (default)
# View reflog
git reflog
git reflog show
git reflog show <branch>
# More detailed reflog
git log -g # Reflog as log
git log -g --all
# Find lost commits
git reflog --all
git fsck --lost-found
# Recover deleted branch
git reflog # Find commit where branch existed
git branch <branch-name> <commit-hash>
# Recover from hard reset
git reflog # Find commit before reset
git reset --hard <commit-hash>
# Recover deleted commits
git cherry-pick <commit-hash>
# Reflog expiration (change retention)
git config gc.reflogExpire "90 days"
git config gc.reflogExpireUnreachable "30 days"
Bisect (Find Bad Commits)
# Start bisect
git bisect start
# Mark current commit as bad
git bisect bad
# Mark known good commit
git bisect good <commit>
# Test each commit, then mark as good or bad
git bisect good # Current commit is good
git bisect bad # Current commit is bad
# Automate with test script
git bisect run <test-script>
# Bisect shows the first bad commit
# Finish bisect
git bisect reset
# Skip commit if unable to test
git bisect skip
Clean
ā ļø WARNING: clean permanently deletes untracked files!
# Show what would be deleted (dry run - ALWAYS do this first!)
git clean -n
git clean --dry-run
# Delete untracked files
git clean -f
# Delete untracked files and directories
git clean -fd
# Delete untracked and ignored files
git clean -fdx
# Interactive clean
git clean -i
Worktrees
# List worktrees
git worktree list
# Add new worktree
git worktree add <path> <branch>
git worktree add ../project-feature feature-branch
# Add worktree for new branch
git worktree add -b <new-branch> <path>
# Remove worktree
git worktree remove <path>
# Prune stale worktrees
git worktree prune
Submodules
# Add submodule
git submodule add <url> <path>
# Initialize submodules (after clone)
git submodule init
git submodule update
# Clone with submodules
git clone --recurse-submodules <url>
# Update submodules
git submodule update --remote
git submodule update --init --recursive
# Execute command in all submodules
git submodule foreach <command>
git submodule foreach git pull origin main
# Remove submodule
git submodule deinit <path>
git rm <path>
rm -rf .git/modules/<path>
Dangerous Operations (High Risk)
Filter-Repo (History Rewriting)
ā ļø EXTREMELY DANGEROUS: Rewrites entire repository history!
# Install git-filter-repo (not built-in)
# pip install git-filter-repo
# Remove file from all history
git filter-repo --path <file> --invert-paths
# Remove directory from all history
git filter-repo --path <directory> --invert-paths
# Change author info
git filter-repo --name-callback 'return name.replace(b"Old Name", b"New Name")'
git filter-repo --email-callback 'return email.replace(b"old@email.com", b"new@email.com")'
# Remove large files
git filter-repo --strip-blobs-bigger-than 10M
# ā ļø After filter-repo, force push required
git push --force --all
git push --force --tags
Safety protocol for filter-repo:
echo "ā ļøā ļøā ļø EXTREME DANGER ā ļøā ļøā ļø"
echo "This operation will:"
echo " - Rewrite ENTIRE repository history"
echo " - Change ALL commit hashes"
echo " - Break all existing clones"
echo " - Require all team members to re-clone"
echo " - Cannot be undone after force push"
echo ""
echo "MANDATORY: Create full backup:"
git clone --mirror <repo-url> backup-$(date +%Y%m%d-%H%M%S)
echo ""
echo "Notify ALL team members before proceeding!"
echo ""
read -p "Type 'I UNDERSTAND THE RISKS' to continue: " confirm
if [[ "$confirm" != "I UNDERSTAND THE RISKS" ]]; then
echo "Cancelled."
exit 1
fi
Amend Pushed Commits
ā ļø DANGER: Changing pushed commits requires force push!
# Amend last commit
git commit --amend
# Amend without changing message
git commit --amend --no-edit
# Change author of last commit
git commit --amend --author="Name <email>"
# ā ļø Force push required if already pushed
git push --force-with-lease
Rewrite Multiple Commits
ā ļø DANGER: Interactive rebase on pushed commits!
# Interactive rebase
git rebase -i HEAD~5
# Change author of older commits
git rebase -i <commit>^
# Mark commit as "edit"
# When stopped:
git commit --amend --author="Name <email>" --no-edit
git rebase --continue
# ā ļø Force push required
git push --force-with-lease
Platform-Specific Workflows
GitHub
Pull Requests:
# Install GitHub CLI
# https://cli.github.com/
# Create PR
gh pr create
gh pr create --title "Title" --body "Description"
gh pr create --base main --head feature-branch
# List PRs
gh pr list
# View PR
gh pr view
gh pr view <number>
# Check out PR locally
gh pr checkout <number>
# Review PR
gh pr review
gh pr review --approve
gh pr review --request-changes
gh pr review --comment
# Merge PR
gh pr merge
gh pr merge --squash
gh pr merge --rebase
gh pr merge --merge
# Close PR
gh pr close <number>
GitHub Actions:
# .github/workflows/ci.yml
name: CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run tests
run: npm test
Azure DevOps
Pull Requests:
# Install Azure DevOps CLI
# https://docs.microsoft.com/en-us/cli/azure/install-azure-cli
# Create PR
az repos pr create --title "Title" --description "Description"
az repos pr create --source-branch feature --target-branch main
# List PRs
az repos pr list
# View PR
az repos pr show --id <id>
# Complete PR
az repos pr update --id <id> --status completed
# Branch policies
az repos policy list
az repos policy create --config policy.json
Azure Pipelines:
# azure-pipelines.yml
trigger:
- main
pool:
vmImage: 'ubuntu-latest'
steps:
- script: npm test
displayName: 'Run tests'
Bitbucket
Pull Requests:
# Create PR (via web or Bitbucket CLI)
bb pr create
# Review PR
bb pr list
bb pr view <id>
# Merge PR
bb pr merge <id>
Bitbucket Pipelines:
# bitbucket-pipelines.yml
pipelines:
default:
- step:
script:
- npm test
GitLab
Merge Requests:
# Install GitLab CLI (glab)
# https://gitlab.com/gitlab-org/cli
# Create MR
glab mr create
glab mr create --title "Title" --description "Description"
# List MRs
glab mr list
# View MR
glab mr view <id>
# Merge MR
glab mr merge <id>
# Close MR
glab mr close <id>
GitLab CI:
# .gitlab-ci.yml
stages:
- test
test:
stage: test
script:
- npm test
Performance Optimization
Repository Maintenance
# Garbage collection
git gc
git gc --aggressive # More thorough, slower
# Prune unreachable objects
git prune
# Verify repository
git fsck
git fsck --full
# Optimize repository
git repack -a -d --depth=250 --window=250
# Git 2.51+: Path-walk repacking (generates smaller packs)
# More efficient delta compression by walking paths
git repack --path-walk -a -d
# Count objects
git count-objects -v
# Repository size
du -sh .git
Large Files
# Find large files in history
git rev-list --objects --all |
git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' |
sed -n 's/^blob //p' |
sort --numeric-sort --key=2 |
tail -n 10
# Git LFS (Large File Storage)
git lfs install
git lfs track "*.psd"
git lfs track "*.zip"
git add .gitattributes
git add file.psd
git commit -m "Add large file"
# List LFS files
git lfs ls-files
# Fetch LFS files
git lfs fetch
git lfs pull
Shallow Clones
# Shallow clone (faster, less disk space)
git clone --depth 1 <url>
# Unshallow (convert to full clone)
git fetch --unshallow
# Fetch more history
git fetch --depth=100
Tags and Releases
Creating Tags
# Lightweight tag
git tag <tag-name>
git tag v1.0.0
# Annotated tag (recommended - includes metadata)
git tag -a <tag-name> -m "message"
git tag -a v1.0.0 -m "Release version 1.0.0"
# Tag specific commit
git tag -a <tag-name> <commit>
# Signed tag (GPG signature)
git tag -s <tag-name> -m "message"
Managing Tags
# List tags
git tag
git tag -l "v1.*" # Pattern matching
# Show tag info
git show <tag-name>
# Delete local tag
git tag -d <tag-name>
# Delete remote tag
git push origin --delete <tag-name>
git push origin :refs/tags/<tag-name>
# Push tags
git push origin <tag-name>
git push --tags # All tags
git push --follow-tags # Only annotated tags
Git Hooks
Client-Side Hooks
# Hooks location: .git/hooks/
# pre-commit: Run before commit
# Example: .git/hooks/pre-commit
#!/bin/bash
npm run lint || exit 1
# prepare-commit-msg: Edit commit message before editor opens
# commit-msg: Validate commit message
#!/bin/bash
msg=$(cat "$1")
if ! echo "$msg" | grep -qE "^(feat|fix|docs|style|refactor|test|chore):"; then
echo "Error: Commit message must start with type (feat|fix|docs|...):"
exit 1
fi
# post-commit: Run after commit
# pre-push: Run before push
# post-checkout: Run after checkout
# post-merge: Run after merge
# Make hook executable
chmod +x .git/hooks/pre-commit
Server-Side Hooks
# pre-receive: Run before refs are updated
# update: Run for each branch being updated
# post-receive: Run after refs are updated
# Example: Reject force pushes
#!/bin/bash
while read oldrev newrev refname; do
if [ "$oldrev" != "0000000000000000000000000000000000000000" ]; then
if ! git merge-base --is-ancestor "$oldrev" "$newrev"; then
echo "Error: Force push rejected"
exit 1
fi
fi
done
Troubleshooting and Recovery
Common Problems
Detached HEAD:
# You're in detached HEAD state
git branch temp # Create branch at current commit
git switch main
git merge temp
git branch -d temp
Merge conflicts:
# During merge/rebase
git status # See conflicted files
# Edit files to resolve conflicts
git add <resolved-files>
git merge --continue # or git rebase --continue
# Abort and start over
git merge --abort
git rebase --abort
Accidentally deleted branch:
# Find branch in reflog
git reflog
# Create branch at commit
git branch <branch-name> <commit-hash>
Committed to wrong branch:
# Move commit to correct branch
git switch correct-branch
git cherry-pick <commit>
git switch wrong-branch
git reset --hard HEAD~1 # Remove from wrong branch
Pushed sensitive data:
# ā ļø URGENT: Remove from history immediately
git filter-repo --path <sensitive-file> --invert-paths
git push --force --all
# Then: Rotate compromised credentials immediately!
Large commit by mistake:
# Before pushing
git reset --soft HEAD~1
git reset HEAD <large-file>
git commit -m "message"
# After pushing - use filter-repo or BFG
Recovery Scenarios
Recover after hard reset:
git reflog
git reset --hard <commit-before-reset>
Recover deleted file:
git log --all --full-history -- <file>
git checkout <commit>^ -- <file>
Recover deleted commits:
git reflog # Find commit hash
git cherry-pick <commit>
# or
git merge <commit>
# or
git reset --hard <commit>
Recover from corrupted repository:
# Verify corruption
git fsck --full
# Attempt repair
git gc --aggressive
# Last resort: clone from remote
Best Practices
Commit Messages
Conventional Commits format:
<type>(<scope>): <subject>
<body>
<footer>
Types:
feat: New featurefix: Bug fixdocs: Documentationstyle: Formatting (no code change)refactor: Code restructuringtest: Adding testschore: Maintenance
Example:
feat(auth): add OAuth2 authentication
Implement OAuth2 flow for Google and GitHub providers.
Includes token refresh and revocation.
Closes #123
Branching Best Practices
- Keep branches short-lived (< 2 days ideal)
- Use descriptive names:
feature/user-auth,fix/header-crash - One purpose per branch
- Rebase before merge to keep history clean
- Delete merged branches
Workflow Best Practices
- Commit often (small, logical chunks)
- Pull before push (stay up to date)
- Review before commit (
git diff --staged) - Write meaningful messages
- Test before commit
- Never commit secrets (use
.gitignore, environment variables)
.gitignore Best Practices
# Environment files
.env
.env.local
*.env
# Dependencies
node_modules/
vendor/
venv/
# Build outputs
dist/
build/
*.exe
*.dll
*.so
# IDE
.vscode/
.idea/
*.swp
*.swo
# OS files
.DS_Store
Thumbs.db
# Logs
*.log
logs/
# Temporary files
tmp/
temp/
*.tmp
Security Best Practices
Credential Management
# Store credentials (cache for 1 hour)
git config --global credential.helper cache
git config --global credential.helper 'cache --timeout=3600'
# Store credentials (permanent - use with caution)
git config --global credential.helper store
# Windows: Use Credential Manager
git config --global credential.helper wincred
# macOS: Use Keychain
git config --global credential.helper osxkeychain
# Linux: Use libsecret
git config --global credential.helper /usr/share/doc/git/contrib/credential/libsecret/git-credential-libsecret
SSH Keys
# Generate SSH key
ssh-keygen -t ed25519 -C "your_email@example.com"
ssh-keygen -t rsa -b 4096 -C "your_email@example.com" # If ed25519 not supported
# Start ssh-agent
eval "$(ssh-agent -s)"
# Add key to ssh-agent
ssh-add ~/.ssh/id_ed25519
# Test connection
ssh -T git@github.com
ssh -T git@ssh.dev.azure.com
GPG Signing
# Generate GPG key
gpg --full-generate-key
# List keys
gpg --list-secret-keys --keyid-format LONG
# Configure Git to sign commits
git config --global user.signingkey <key-id>
git config --global commit.gpgsign true
# Sign commits
git commit -S -m "message"
# Verify signatures
git log --show-signature
Preventing Secrets
# Git-secrets (AWS tool)
git secrets --install
git secrets --register-aws
# Gitleaks
gitleaks detect
# Pre-commit hook
#!/bin/bash
if git diff --cached | grep -E "(password|secret|api_key)" ; then
echo "Potential secret detected!"
exit 1
fi
Cross-Platform Considerations
Line Endings
# Windows (CRLF in working directory, LF in repository)
git config --global core.autocrlf true
# macOS/Linux (LF everywhere)
git config --global core.autocrlf input
# No conversion (not recommended)
git config --global core.autocrlf false
# Use .gitattributes for consistency
# .gitattributes:
* text=auto
*.sh text eol=lf
*.bat text eol=crlf
Case Sensitivity
# macOS/Windows: Case-insensitive filesystems
# Linux: Case-sensitive filesystem
# Enable case sensitivity in Git
git config --global core.ignorecase false
# Rename file (case-only change)
git mv --force myfile.txt MyFile.txt
Path Handling
# Git always uses forward slashes internally
# Works on all platforms:
git add src/components/Header.jsx
# Windows-specific tools may need backslashes in some contexts
Git Bash / MINGW Path Conversion (Windows)
CRITICAL: Git Bash is the primary Git environment on Windows!
Git Bash (MINGW/MSYS2) automatically converts Unix-style paths to Windows paths for native executables, which can cause issues with Git operations.
Path Conversion Behavior:
# Automatic conversions that occur:
/foo ā C:/Program Files/Git/usr/foo
/foo:/bar ā C:\msys64\foo;C:\msys64\bar
--dir=/foo ā --dir=C:/msys64/foo
# What triggers conversion:
# ā Leading forward slash (/) in arguments
# ā Colon-separated path lists
# ā Arguments after - or , with path components
# What's exempt from conversion:
# ā Arguments containing = (variable assignments)
# ā Drive specifiers (C:)
# ā Arguments with ; (already Windows format)
# ā Arguments starting with // (Windows switches)
Controlling Path Conversion:
# Method 1: MSYS_NO_PATHCONV (Git for Windows only)
# Disable ALL path conversion for a command
MSYS_NO_PATHCONV=1 git command --option=/path
# Permanently disable (use with caution - can break scripts)
export MSYS_NO_PATHCONV=1
# Method 2: MSYS2_ARG_CONV_EXCL (MSYS2)
# Exclude specific argument patterns
export MSYS2_ARG_CONV_EXCL="*" # Exclude everything
export MSYS2_ARG_CONV_EXCL="--dir=;/test" # Specific prefixes
# Method 3: Manual conversion with cygpath
cygpath -u "C:\path" # ā Unix format: /c/path
cygpath -w "/c/path" # ā Windows format: C:\path
cygpath -m "/c/path" # ā Mixed format: C:/path
# Method 4: Workarounds
# Use double slashes: //e //s instead of /e /s
# Use dash notation: -e -s instead of /e /s
# Quote paths with spaces: "/c/Program Files/file.txt"
Shell Detection in Git Workflows:
# Method 1: $MSYSTEM (Most Reliable for Git Bash)
case "$MSYSTEM" in
MINGW64) echo "Git Bash 64-bit" ;;
MINGW32) echo "Git Bash 32-bit" ;;
MSYS) echo "MSYS environment" ;;
esac
# Method 2: uname -s (Portable)
case "$(uname -s)" in
MINGW64_NT*) echo "Git Bash 64-bit" ;;
MINGW32_NT*) echo "Git Bash 32-bit" ;;
MSYS_NT*) echo "MSYS" ;;
CYGWIN*) echo "Cygwin" ;;
Darwin*) echo "macOS" ;;
Linux*) echo "Linux" ;;
esac
# Method 3: $OSTYPE (Bash-only, fast)
case "$OSTYPE" in
msys*) echo "Git Bash/MSYS" ;;
cygwin*) echo "Cygwin" ;;
darwin*) echo "macOS" ;;
linux-gnu*) echo "Linux" ;;
esac
Git Bash Path Issues & Solutions:
# Issue: Git commands with paths fail in Git Bash
# Example: git log --follow /path/to/file fails
# Solution 1: Use relative paths
git log --follow ./path/to/file
# Solution 2: Disable path conversion
MSYS_NO_PATHCONV=1 git log --follow /path/to/file
# Solution 3: Use Windows-style paths
git log --follow C:/path/to/file
# Issue: Spaces in paths (Program Files)
# Solution: Always quote paths
git add "/c/Program Files/project/file.txt"
# Issue: Drive letter duplication (D:\dev ā D:\d\dev)
# Solution: Use cygpath for conversion
file=$(cygpath -u "D:\dev\file.txt")
git add "$file"
Git Bash Best Practices:
- Always use forward slashes in Git commands - Git handles them on all platforms
- Quote paths with spaces - Essential in Git Bash
- Use relative paths when possible - Avoids conversion issues
- Detect shell environment - Use $MSYSTEM for Git Bash detection
- Test scripts on Git Bash - Primary Windows Git environment
- Use MSYS_NO_PATHCONV selectively - Only when needed, not globally
Success Criteria
A Git workflow using this skill should:
- ā ALWAYS ask user preference for automatic commits vs manual
- ā ALWAYS warn before destructive operations
- ā ALWAYS create backup branches before risky operations
- ā ALWAYS explain recovery procedures
- ā Use appropriate branch strategy for the project
- ā Write meaningful commit messages
- ā Keep commit history clean and linear
- ā Never commit secrets or large binary files
- ā Test code before committing
- ā Know how to recover from any mistake
Emergency Recovery Reference
Quick recovery commands:
# Undo last commit (keep changes)
git reset --soft HEAD~1
# Undo changes to file
git checkout -- <file>
# Recover deleted branch
git reflog
git branch <name> <commit>
# Undo force push (if recent)
git reflog
git reset --hard <commit-before-push>
git push --force-with-lease
# Recover from hard reset
git reflog
git reset --hard <commit-before-reset>
# Find lost commits
git fsck --lost-found
git reflog --all
# Recover deleted file
git log --all --full-history -- <file>
git checkout <commit>^ -- <file>
When to Use This Skill
Always activate for:
- Any Git command or operation
- Repository management questions
- Branch strategy decisions
- Merge conflict resolution
- History rewriting needs
- Recovery from Git mistakes
- Platform-specific Git questions
- Dangerous operations (with appropriate warnings)
Key indicators:
- User mentions Git, GitHub, GitLab, Bitbucket, Azure DevOps
- Version control questions
- Commit, push, pull, merge, rebase operations
- Branch management
- History modification
- Recovery scenarios
This skill provides COMPLETE Git expertise. Combined with the reference files and safety guardrails, you have the knowledge to handle ANY Git operation safely and effectively.