Git Workflow Cheat Sheet
Daily Git commands and workflows for technical leads managing feature development, code reviews, and releases.
For setup instructions (multi-identity, conventional commits, ghq, git-cliff), see Git Setup
Daily Workflow
Morning Routine
# Navigate to repo
cd $(ghq root)/forgejo.company.com/platform/auth-service
# Update main branch
git checkout main
git pull # ff-only, safe
# Update feature branch
git checkout feat/oauth-integration
git fetch origin
git rebase origin/main # Keep history clean
Feature Development
# Start new feature
git checkout main
git pull
git checkout -b feat/add-2fa-support
# Work and commit
git add -p # Stage interactively (review chunks)
git commit # Opens vim with template
# Quick commit (when template not needed)
git commit -m "feat: add TOTP generation for 2FA"
# Push to remote
git push -u origin feat/add-2fa-support
Rebase vs Merge:
Feature branch workflow:
main: A---B---C---D
\
feature: E---F---G
After rebase (cleaner history):
main: A---B---C---D
\
feature: E'--F'--G'
After merge (preserves history):
main: A---B---C---D---M
\ /
feature: E---F---G
# Rebase (recommended for feature branches)
git checkout feat/add-2fa-support
git rebase origin/main
# If conflicts occur
git status # See conflicted files
# Fix conflicts in editor
git add <resolved-files>
git rebase --continue
git rebase --abort # Abort if needed
# Merge (use for long-lived branches)
git checkout main
git merge --no-ff feat/add-2fa-support
Reviewing Code
# Fetch latest from remote
git fetch origin
# Review someone's PR branch
git checkout -b review/oauth-pr origin/feat/oauth-integration
# Compare with main (delta shows side-by-side)
git diff main...feat/oauth-integration
# See what commits are in the branch
git log main..feat/oauth-integration --oneline
# Check file history
git log --follow -- src/auth/oauth.js
git blame src/auth/oauth.js # Who changed what, line by line
# Search for specific changes
git log --grep="oauth" # Search commit messages
git log -S "generateToken" # Search code changes (when was this added/removed)
git log --author="Prashant" # Filter by author
Cleaning Up Commits
# Squash last 3 commits into one
git rebase -i HEAD~3
# In vim, change 'pick' to 's' (squash):
# pick abc1234 feat: add oauth client
# s def5678 fix: typo in oauth
# s ghi9012 refactor: cleanup oauth code
# Save and edit combined commit message
# Squash all commits in feature branch
git rebase -i origin/main
# Amend last commit (fix message or add forgotten files)
git commit --amend
git add forgotten-file.js
git commit --amend --no-edit # Don't edit message
# Push after rewriting history
git push --force-with-lease # Safer than --force (checks remote hasn't changed)
Hotfix Workflow
# Create hotfix from production
git checkout main
git pull
git checkout -b hotfix/fix-payment-crash
# Make fix and test
git add src/payment/processor.js
git commit -m "fix: prevent null pointer in payment processor"
# Review before pushing
git diff origin/main # What changed
git log origin/main..HEAD --oneline # Commits to be pushed
# Push and create PR
git push -u origin hotfix/fix-payment-crash
Branch Management
Comparing Branches
# See commits in feature not in main
git log main..feat/oauth-integration --oneline
# See commits in main not in feature
git log feat/oauth-integration..main --oneline
# Visual graph of all branches
git log --graph --oneline --all
# Diff between branches (changes in feature only)
git diff main...feat/oauth-integration
Understanding branch divergence:
main: A---B---C---D
\
feature: E---F
git log main..feature # Shows: E, F (what's new in feature)
git log feature..main # Shows: C, D (what's new in main)
git diff main...feature # Shows changes in E, F only
Branch Cleanup
# Delete merged local branch
git branch -d feat/completed-feature
# Force delete unmerged branch
git branch -D feat/abandoned-feature
# Delete remote branch
git push origin --delete feat/old-feature
# Clean up stale remote references
git fetch --prune
# List branches with tracking info
git branch -vv
# Clean up all merged branches (except main/develop)
git branch --merged | grep -v '\*\|main\|develop' | xargs -n 1 git branch -d
Context Switching
Using Stash
# Save work in progress
git stash # Quick stash
git stash push -m "WIP: oauth token refresh logic"
# List stashes
git stash list
# Apply stash (keep in stash list)
git stash apply stash@{0}
# Apply and remove from list
git stash pop
# Create branch from stash
git stash branch feat/recovered-work stash@{0}
# Drop specific stash
git stash drop stash@{0}
# Clear all stashes
git stash clear
Merging & Releasing
Merge Strategies
# Fast-forward merge (no merge commit)
git checkout main
git merge feat/simple-fix # Only if ff possible
# No fast-forward (always create merge commit)
git merge --no-ff feat/oauth-integration
# Squash merge (combine all commits into one)
git merge --squash feat/small-feature
git commit -m "feat: add rate limiting"
Merge commit visualization:
Before merge:
main: A---B---C
\
feature: D---E
After --no-ff:
main: A---B---C-------M
\ /
feature: D---E
After --squash:
main: A---B---C---S
\
feature: D---E (not in history, just content)
Tagging Releases
# Semantic versioning: vMAJOR.MINOR.PATCH
# MAJOR: breaking changes (v2.0.0)
# MINOR: new features (v1.3.0)
# PATCH: bug fixes (v1.2.1)
# Create annotated tag
git tag -a v1.3.0 -m "Release v1.3.0: OAuth integration"
# Tag specific commit
git tag -a v1.2.1 abc1234 -m "Hotfix: payment crash"
# Push tags
git push origin v1.3.0
git push origin --tags # Push all tags
# List tags (sorted by version)
git tag -l --sort=-v:refname
# Delete tag
git tag -d v1.3.0 # Local
git push origin --delete v1.3.0 # Remote
# Checkout tag for hotfix
git checkout v1.2.0
git checkout -b hotfix/v1.2.1 v1.2.0
Release with Changelog
# Preview unreleased changes
git cliff --unreleased
# Create release with changelog
git tag -a v1.3.0 -m "Release v1.3.0"
git cliff --tag v1.3.0 --output CHANGELOG.md
git add CHANGELOG.md
git commit -m "chore: update changelog for v1.3.0"
git push origin main --tags
# Or combine into one command
git cliff --tag v1.3.0 -o CHANGELOG.md && \
git add CHANGELOG.md && \
git commit -m "chore: update changelog for v1.3.0" && \
git push origin main --tags
Undoing Changes
Reset (Rewrite History)
# Undo last commit, keep changes staged
git reset --soft HEAD~1
# Undo last commit, keep changes unstaged
git reset HEAD~1 # Default is --mixed
# Undo last commit, discard changes
git reset --hard HEAD~1
# Reset to match remote (discard all local changes)
git fetch origin
git reset --hard origin/main
Reset modes:
Initial: A---B---C (HEAD)
Changes staged and in working dir
--soft HEAD~1:
A---B (HEAD)
Changes still staged (ready to commit)
--mixed HEAD~1 (default):
A---B (HEAD)
Changes unstaged but in working dir
--hard HEAD~1:
A---B (HEAD)
Changes discarded (gone forever)
Revert (Safe Undo)
# Create new commit that undoes a commit (safe for shared branches)
git revert abc1234
# Revert without committing (review first)
git revert -n abc1234
# Revert merge commit
git revert -m 1 <merge-commit-hash> # -m 1 keeps first parent
Discard Changes
# Discard unstaged changes
git checkout -- src/auth/login.js # Single file
git checkout -- . # All files
# Unstage files (keep changes in working dir)
git reset HEAD src/auth/login.js
# Remove untracked files and directories
git clean -fd # -f force, -d directories
git clean -fdn # Dry run (preview what will be deleted)
git clean -fdx # Also remove ignored files
Recovery
Using Reflog
Reflog records every HEAD movement - your safety net for recovering “lost” commits.
# View all Git actions (commits, resets, checkouts)
git reflog
# Recover lost commit
git reflog
git checkout abc1234
git checkout -b recovered-branch
# Undo accidental reset
git reflog
git reset --hard HEAD@{2} # Go back 2 actions
# Recover deleted branch
git reflog
git checkout -b recovered-branch HEAD@{5}
Reflog example:
abc1234 HEAD@{0}: commit: feat: add oauth
def5678 HEAD@{1}: reset: moving to HEAD~1
ghi9012 HEAD@{2}: commit: fix: typo
Advanced Operations
Cherry-pick
Apply specific commits from one branch to another.
# Apply specific commit to current branch
git cherry-pick abc1234
# Cherry-pick without committing (review first)
git cherry-pick -n abc1234
# Cherry-pick range
git cherry-pick abc1234^..def5678
# Abort cherry-pick
git cherry-pick --abort
Interactive Staging
# Stage changes interactively (review each chunk)
git add -p
# Options during interactive staging:
# y - stage this hunk
# n - don't stage this hunk
# s - split into smaller hunks
# e - manually edit the hunk
# q - quit
Bisect (Find Bug Introduction)
# Start bisect
git bisect start
git bisect bad # Current commit is bad
git bisect good v1.2.0 # Known good commit
# Git checks out middle commit, test it
git bisect good # If test passes
git bisect bad # If test fails
# Repeat until bug is found
git bisect reset # Return to original state
Pull Strategy
Config uses pull.ff = only - this prevents accidental merge commits.
# With ff = only configured:
git pull # Only succeeds if fast-forward possible
# If remote has diverged:
git pull --rebase # Rebase your commits (recommended)
git pull --no-ff # Create merge commit
Recommendation: Keep pull.ff = only for main/develop. Use git pull --rebase on feature branches.
Quick Reference
Conventional Commits
feat: New feature (minor bump)
fix: Bug fix (patch bump)
docs: Documentation
refactor: Code restructuring
test: Tests
chore: Maintenance
perf: Performance
ci: CI/CD
build: Build system
revert: Revert commit
Semantic Versioning
v1.0.0 - Initial release
v1.1.0 - New feature (minor bump)
v1.1.1 - Bug fix (patch bump)
v2.0.0 - Breaking change (major bump)
Delta Navigation
n / N Next/previous file
Ctrl+d / u Scroll down/up
q Quit
Git Aliases
From ~/.gitconfig:
git st # status -sb
git co <branch> # checkout
git br # branch -vv
git ci # commit
git unstage <file> # reset HEAD
git last # log -1 HEAD
git lg # log --graph --oneline --all
git amend # commit --amend --no-edit
git undo # reset --soft HEAD~1
git wip # commit -am "WIP"
git cleanup # delete merged branches
Common Patterns
# Daily start
git checkout main && git pull
git checkout feat/my-feature && git rebase origin/main
# Before PR
git rebase -i origin/main # Clean up commits
git push --force-with-lease
# After PR merged
git checkout main && git pull
git branch -d feat/my-feature
git fetch --prune
# Generate changelog and release
git cliff --unreleased # Preview
git cliff --tag v1.3.0 -o CHANGELOG.md
git add CHANGELOG.md
git commit -m "chore: update changelog for v1.3.0"
git push origin main --tags
Useful Log Formats
# Compact log with graph
git log --graph --oneline --all --decorate
# Detailed log with dates
git log --pretty=format:'%C(yellow)%h%Creset %C(blue)%ad%Creset %s %C(green)(%an)%Creset' --date=short
# Show files changed in each commit
git log --stat
# Show actual changes
git log -p
# One-line summary
git log --oneline -10
Tips for Leads
Code Review Workflow
# Fetch all branches
git fetch --all
# List remote branches
git branch -r
# Review PR locally
git checkout -b review/feature-123 origin/feat/feature-123
git diff main...review/feature-123
git log main..review/feature-123 --oneline
# Test locally, then delete review branch
git checkout main
git branch -D review/feature-123
Managing Multiple Features
# List all feature branches
git branch | grep feat/
# See what's in each feature
for branch in $(git branch | grep feat/); do
echo "=== $branch ==="
git log main..$branch --oneline
done
# Clean up merged features
git branch --merged main | grep feat/ | xargs -n 1 git branch -d
Emergency Hotfix
# Quick hotfix from production tag
git checkout v1.2.0
git checkout -b hotfix/critical-fix
# Make fix
git commit -m "fix: critical security issue"
git tag -a v1.2.1 -m "Hotfix: security patch"
git push origin hotfix/critical-fix --tags
For setup instructions, see Git Setup