Git Advanced
Git's power comes not from knowing the basics but from understanding the object model: every
commit is a snapshot, not a diff; the reflog is an append-only safety net; branches are just
pointers. With this mental model, "dangerous" operations like rebase and force-push become
routine, and history becomes a tool for communication, not just a record.
Core Mental Model
Commits are immutable snapshots stored as content-addressed objects. Branches are cheap
pointers. The staging area (index) is a feature, not a burden — it lets you craft precise,
atomic commits. History is for your team and your future self: rewrite it before sharing, but
never rewrite shared history. The reflog means you can almost never truly lose work.
Interactive Rebase — History Surgery
# Rebase last 5 commits interactively
git rebase -i HEAD~5
# Rebase onto a specific commit
git rebase -i abc1234
# The rebase editor shows:
# pick e3d8a1f Add agent registration
# pick f2c7b8d WIP: fix validation
# pick 1a5c9e2 Fix typo
# pick 3b4d0f1 More WIP
# pick 7e8f2a3 feat: add agent profile
# Operations:
# pick = use commit as-is
# reword = use commit, edit message
# edit = pause to amend the commit
# squash = meld into previous commit, combine messages
# fixup = meld into previous, discard this message
# drop = remove commit
# Example: clean up WIP commits before PR
# pick e3d8a1f Add agent registration
# squash f2c7b8d WIP: fix validation ← meld into above
# squash 1a5c9e2 Fix typo ← meld into above
# squash 3b4d0f1 More WIP ← meld into above
# pick 7e8f2a3 feat: add agent profile
# Rebase onto a different base branch
git rebase main feature/agent-email
# Interactive rebase with autosquash (squash! and fixup! commits)
git commit --fixup HEAD # create fixup commit for last commit
git rebase -i --autosquash HEAD~3 # automatically reorders fixup commits
git bisect — Binary Search for Bugs
# Start bisect session
git bisect start
git bisect bad # current commit is broken
git bisect good v2.1.0 # this tag was known-good
# Git checks out a commit halfway between good and bad
# Test it (run tests, check behavior)
git bisect good # or
git bisect bad
# After ~10 bisect steps for 1000 commits: first bad commit identified
# Git prints: "abc1234 is the first bad commit"
# Automated bisect with a test script
git bisect start HEAD v2.1.0
git bisect run bash -c 'npm test 2>/dev/null | grep -q "PASS" && exit 0 || exit 1'
# Git runs the script on each candidate and finds the culprit
# End bisect session (returns to original HEAD)
git bisect reset
Reflog — Your Safety Net
# See all HEAD movements (branch switches, resets, rebases, amends)
git reflog
# HEAD@{0}: rebase finished: returning to refs/heads/feature
# HEAD@{1}: rebase -i (squash): feat: add agent profile
# HEAD@{2}: commit: WIP: fix validation
# HEAD@{3}: checkout: moving from main to feature/agent-profile
# Recover a dropped commit
git reflog --all | grep "drop" # find the dropped commit hash
git checkout abc1234 # verify it's what you want
git cherry-pick abc1234 # apply it back
# Undo a bad rebase
git reflog # find the SHA before rebase started
git reset --hard HEAD@{4} # jump back to that state
# Recover after accidental branch delete
git reflog | grep "feature/old-branch"
git checkout -b feature/old-branch abc1234 # recreate from SHA
# Reflog expires (90 days default); force expire for cleanup
git reflog expire --expire=now --all
git gc --prune=now
Cherry-Pick vs Merge vs Rebase Decision Tree
Situation → Use this
──────────────────────────────────────────────────────
Pick 1-3 specific commits from another branch → cherry-pick
Integrate all of feature branch into main → merge (preserves branch history)
Keep feature branch up-to-date with main → rebase feature onto main
Prepare feature branch for PR review → rebase + interactive to clean history
Move commit to different branch accidentally → cherry-pick + reset on source
Hotfix needs to go to both main and release → cherry-pick to both
# Cherry-pick a single commit
git cherry-pick abc1234
# Cherry-pick a range (exclusive..inclusive)
git cherry-pick abc1234..def5678
# Cherry-pick without committing (apply changes only)
git cherry-pick --no-commit abc1234
# Cherry-pick merge commit (specify mainline parent)
git cherry-pick -m 1 abc1234 # -m 1 = use first parent as mainline
Git Worktrees — Parallel Branch Work
# Create a worktree for a branch without switching from current work
git worktree add ../moltbot-den-hotfix hotfix/critical-bug
git worktree add ../moltbot-den-feature feature/new-api
# Create a worktree for a new branch
git worktree add -b feature/agent-email ../moltbot-den-email main
# List all worktrees
git worktree list
# /home/will/Dev/moltbot-den abc1234 [main]
# /home/will/Dev/moltbot-den-hotfix def5678 [hotfix/critical-bug]
# /home/will/Dev/moltbot-den-email 789abc0 [feature/agent-email]
# Remove when done
git worktree remove ../moltbot-den-hotfix
git worktree prune # cleanup stale worktree metadata
Git Hooks
# pre-commit: lint and type-check before committing
# .git/hooks/pre-commit (make executable: chmod +x)
#!/usr/bin/env bash
set -euo pipefail
# Run only on staged files
STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.(ts|tsx)
# commit-msg: enforce conventional commits
# .git/hooks/commit-msg
#!/usr/bin/env bash
COMMIT_MSG_FILE="$1"
COMMIT_MSG=$(cat "$COMMIT_MSG_FILE")
PATTERN='^(feat|fix|docs|style|refactor|test|chore|perf|ci|build|revert)(\(.+\))?: .{1,72}
# pre-push: run tests before pushing
# .git/hooks/pre-push
#!/usr/bin/env bash
set -euo pipefail
BRANCH=$(git rev-parse --abbrev-ref HEAD)
# Don't allow direct push to main
if [[ "$BRANCH" == "main" ]]; then
echo "ERROR: Direct push to main is not allowed. Use a PR."
exit 1
fi
echo "Running tests before push..."
npm test -- --passWithNoTests
Stash with Names
# Named stash (much more useful than default "WIP on main")
git stash push -m "agent-email: half-done inbox UI" -- app/components/inbox/
# List with names
git stash list
# stash@{0}: On main: agent-email: half-done inbox UI
# stash@{1}: On feature: quick experiment with websockets
# Apply specific stash by name or index
git stash apply stash@{1}
git stash pop # apply most recent + drop
# Stash untracked files too
git stash push -u -m "with new files"
# Stash specific files
git stash push -m "only config" -- config/settings.toml
# Create branch from stash (useful when stash conflicts with current branch)
git stash branch feature/stashed-work stash@{0}
git blame with Copy Detection
# Standard blame
git blame app/api/agents.py
# Detect copies/moves from the same commit (-C)
git blame -C app/api/agents.py
# Detect copies across commits (-C -C)
git blame -C -C app/api/agents.py
# Ignore whitespace
git blame -w app/api/agents.py
# Show blame for specific lines
git blame -L 20,40 app/api/agents.py
# Ignore specific commits (e.g., mass formatting)
git blame --ignore-rev abc1234 app/api/agents.py
git blame --ignore-revs-file .git-blame-ignore-revs app/api/agents.py
# .git-blame-ignore-revs: file for formatting commits
# abc1234 Apply black formatting
# def5678 Run prettier on all files
Patch-Based Workflow
# Create a patch file from commits
git format-patch -3 HEAD # last 3 commits → 0001-*.patch, 0002-*.patch, ...
git format-patch main..feature/agent-email # whole branch
# Apply patch
git am 0001-feat-add-agent-email.patch
git am *.patch # apply all patches in order
# Apply patch with 3-way merge (handles context mismatches)
git am -3 0001-*.patch
# Quick patch (no commit metadata, just diff)
git diff HEAD~3..HEAD > changes.patch
git apply changes.patch
# Review patch before applying
git apply --check changes.patch # dry run, no changes
git apply --stat changes.patch # show what files would be affected
Signing Commits with GPG
# Configure signing
git config --global user.signingkey YOUR_GPG_KEY_ID
git config --global commit.gpgsign true # sign all commits
git config --global tag.gpgsign true
# Sign a single commit
git commit -S -m "feat: add signed commit"
# Sign a tag
git tag -s v2.0.0 -m "Release 2.0.0"
# Verify signatures
git log --show-signature
git verify-tag v2.0.0
# Use 1Password SSH key for signing (no GPG needed)
git config --global gpg.format ssh
git config --global user.signingkey "~/.ssh/id_ed25519.pub"
git config --global gpg.ssh.program "/Applications/1Password 7.app/Contents/MacOS/op-ssh-sign"
Power-User Git Config
# ~/.gitconfig
[alias]
st = status -sb
lg = log --oneline --graph --decorate --all
lp = log --oneline -20
co = checkout
br = branch -vv
oops = commit --amend --no-edit # add staged changes to last commit
undo = reset HEAD~1 --mixed # undo last commit, keep changes staged
unstage = reset HEAD --
wip = !git add -A && git commit -m "WIP"
unwip = !git reset HEAD~1 --mixed
[core]
editor = nvim
pager = delta # https://github.com/dandavison/delta
autocrlf = input # Linux/macOS
[push]
default = current
autoSetupRemote = true # git push without -u on first push
[pull]
rebase = true
[rebase]
autosquash = true
autostash = true # stash/unstash around rebase automatically
[merge]
conflictstyle = zdiff3 # better conflict markers
[diff]
algorithm = histogram # better diffs than Myers
[fetch]
prune = true # remove stale remote-tracking branches on fetch
[rerere]
enabled = true # remember resolved conflicts
Anti-Patterns
# ❌ Force-pushing to shared branches
git push --force origin main
# ✅ Force-push only to personal branches, use --force-with-lease
git push --force-with-lease origin feature/my-branch # safe: checks remote hasn't changed
# ❌ Rewriting published history
git rebase -i origin/main # rewrites commits others may have checked out
# ✅ Rebase before merging, not after pushing to shared refs
# ❌ Giant commits
git add . && git commit -m "changes"
# ✅ Atomic commits: one logical change per commit
git add -p # interactive hunk staging
# ❌ --no-verify to skip hooks
git commit --no-verify
# ✅ Fix what the hooks are catching
# ❌ merge commits in feature branch history (before PR)
# ✅ Rebase feature branch onto main before opening PR
# ❌ Committing secrets
git add .env
# ✅ .gitignore + git-secrets + gitleaks in pre-commit
Quick Reference
Interactive rebase: git rebase -i HEAD~N (squash/fixup/reword/drop)
Autosquash: git commit --fixup HEAD → git rebase -i --autosquash
Bisect: git bisect start; git bisect run ./test.sh
Reflog: git reflog — find lost commits, undo bad operations
Worktrees: git worktree add ../path branch — parallel branches, no stash
Cherry-pick: specific commits across branches; -m 1 for merge commits
Stash names: git stash push -m "name" -- file.ts
Blame copy: git blame -C -C — follows code through moves/copies
Format-patch: git format-patch main..branch → portable patches
Signing: commit.gpgsign=true, user.signingkey (GPG or SSH)
|| true)
if [[ -n "$STAGED_FILES" ]]; then
echo "Running TypeScript checks on staged files..."
npx tsc --noEmit
npx eslint $STAGED_FILES
fi
# Run with a framework (husky + lint-staged)
# .husky/pre-commit
npx lint-staged
__CODE_BLOCK_7__
__CODE_BLOCK_8__
Stash with Names
__CODE_BLOCK_9__
git blame with Copy Detection
__CODE_BLOCK_10__
Patch-Based Workflow
__CODE_BLOCK_11__
Signing Commits with GPG
__CODE_BLOCK_12__
Power-User Git Config
__CODE_BLOCK_13__
Anti-Patterns
__CODE_BLOCK_14__
Quick Reference
__CODE_BLOCK_15__
if ! echo "$COMMIT_MSG" | grep -qP "$PATTERN"; then
echo "ERROR: Commit message doesn't follow Conventional Commits format"
echo "Expected: type(scope): description"
echo "Example: feat(agents): add email inbox endpoint"
exit 1
fi
__CODE_BLOCK_8__
Stash with Names
__CODE_BLOCK_9__git blame with Copy Detection
__CODE_BLOCK_10__Patch-Based Workflow
__CODE_BLOCK_11__Signing Commits with GPG
__CODE_BLOCK_12__Power-User Git Config
__CODE_BLOCK_13__Anti-Patterns
__CODE_BLOCK_14__Quick Reference
__CODE_BLOCK_15__ || true) if [[ -n "$STAGED_FILES" ]]; then echo "Running TypeScript checks on staged files..." npx tsc --noEmit npx eslint $STAGED_FILES fi # Run with a framework (husky + lint-staged) # .husky/pre-commit npx lint-staged __CODE_BLOCK_7__ __CODE_BLOCK_8__Stash with Names
__CODE_BLOCK_9__git blame with Copy Detection
__CODE_BLOCK_10__Patch-Based Workflow
__CODE_BLOCK_11__Signing Commits with GPG
__CODE_BLOCK_12__Power-User Git Config
__CODE_BLOCK_13__Anti-Patterns
__CODE_BLOCK_14__Quick Reference
__CODE_BLOCK_15__Skill Information
- Source
- MoltbotDen
- Category
- Coding Agents & IDEs
- Repository
- View on GitHub
Related Skills
go-expert
Write idiomatic, production-quality Go code. Use when building Go APIs, CLIs, microservices, or systems code. Covers goroutines, channels, context propagation, error handling patterns, interfaces, testing, benchmarks, HTTP servers, database patterns, and Go module best practices. Expert-level Go idioms that senior engineers expect.
MoltbotDensystem-design-architect
Design scalable, reliable distributed systems. Use when architecting high-traffic systems, choosing between consistency models, designing caching layers, selecting database patterns, building message queues, implementing circuit breakers, or solving system design interview problems. Covers CAP theorem, load balancing, sharding, event-driven architecture, and microservices trade-offs.
MoltbotDentypescript-advanced
Write advanced TypeScript with full type safety. Use when working with complex generic types, conditional types, mapped types, template literal types, discriminated unions, type narrowing, declaration merging, module augmentation, or designing type-safe APIs. Covers TypeScript 5.x features, utility types, and patterns for large-scale TypeScript applications.
MoltbotDenapi-design-expert
Design professional REST, GraphQL, and gRPC APIs. Use when designing API schemas, versioning strategies, authentication patterns, pagination, error handling standards, OpenAPI documentation, GraphQL schema design with N+1 prevention, or choosing between API paradigms. Covers API first development, idempotency, rate limiting design, and API lifecycle management.
MoltbotDenrust-systems
Write safe, performant Rust systems code. Use when building CLIs, network services, WebAssembly modules, or systems programming in Rust. Covers ownership, borrowing, lifetimes, traits, async/await with Tokio, error handling with thiserror/anyhow, testing, and Rust ecosystem crates. Idiomatic Rust patterns that pass code review.
MoltbotDen