Advanced Git
Beyond daily commit-and-push workflows, Git offers powerful tools for debugging history, automating tasks, and managing complex projects.
Stash — Temporary Storage
Save uncommitted work without committing:
# Stash all tracked changes
git stash
# Stash with message
git stash push -m "WIP authentication refactor"
# Stash including untracked files
git stash -u
# List stashes
git stash list
# stash@{0}: WIP on main: a1b2c3d Add login
# Apply most recent stash (keep in list)
git stash apply
# Apply and remove from list
git stash pop
# Apply specific stash
git stash apply stash@{1}
# Drop a stash
git stash drop stash@{0}
Use case: urgent hotfix on main while mid-feature on another branch.
Cherry-Pick — Copy Specific Commits
Apply one commit from another branch without merging the entire branch:
git log --oneline feature/payments
# f7g8h9i Fix payment validation
git checkout main
git cherry-pick f7g8h9i
Cherry-pick creates a new commit with the same changes but a different hash.
Multiple commits:
git cherry-pick a1b2c3d..e4f5g6h
Interactive Rebase
Rewrite commit history before pushing:
git rebase -i HEAD~4
Editor opens:
pick a1b2c3d Add user model
pick b2c3d4e Fix typo in user model
pick c3d4e5f Add user tests
pick d4e5f6g WIP debugging
# Commands:
# p, pick = use commit
# r, reword = change message
# s, squash = merge into previous commit
# f, fixup = squash, discard message
# d, drop = remove commit
Result: clean, logical commit history for code review.
Reflog — Safety Net
Git records every HEAD movement in the reflog — recover “lost” commits:
git reflog
# a1b2c3d HEAD@{0}: commit: Add feature
# b2c3d4e HEAD@{1}: reset: moving to HEAD~1
# c3d4e5f HEAD@{2}: commit: Important work
# Recover a "lost" commit
git checkout c3d4e5f
git checkout -b recovered-work
Reflog entries expire after ~90 days by default.
Git Bisect — Find Bug-Introducing Commit
Binary search through history:
git bisect start
git bisect bad # current commit has the bug
git bisect good v1.0.0 # this tag worked
# Git checks out middle commit — test it
git bisect good # or git bisect bad
# Repeat until Git identifies the culprit commit
git bisect reset # return to original branch
Automate with a test script:
git bisect start HEAD v1.0.0
git bisect run npm test
Git Hooks — Automation
Hooks are scripts that run on Git events. Located in .git/hooks/ (or managed via tools like husky).
pre-commit Hook
Run linting before every commit:
#!/bin/sh
# .git/hooks/pre-commit
npm run lint
if [ $? -ne 0 ]; then
echo "Lint failed — commit aborted"
exit 1
fi
Make executable: chmod +x .git/hooks/pre-commit
commit-msg Hook
Enforce commit message format:
#!/bin/sh
# .git/hooks/commit-msg
commit_msg=$(cat "$1")
if ! echo "$commit_msg" | grep -qE '^(feat|fix|docs|chore)(\(.+\))?: .+'; then
echo "Commit message must follow Conventional Commits format"
echo "Example: feat(auth): add login endpoint"
exit 1
fi
Using Husky (Node.js projects)
npm install -D husky
npx husky init
echo "npm test" > .husky/pre-commit
Tags — Mark Releases
# Lightweight tag
git tag v1.0.0
# Annotated tag (recommended for releases)
git tag -a v1.0.0 -m "Release 1.0.0 — user authentication"
# Push tags to remote
git push origin v1.0.0
git push origin --tags
# List tags
git tag -l "v1.*"
# Checkout a tag
git checkout v1.0.0
Submodules — Nested Repositories
Include one Git repo inside another:
git submodule add https://github.com/org/shared-lib.git libs/shared
git commit -m "Add shared-lib submodule"
Clone a repo with submodules:
git clone --recurse-submodules https://github.com/org/main-project.git
# Or after clone
git submodule update --init --recursive
Update submodule to latest:
cd libs/shared
git pull origin main
cd ../..
git add libs/shared
git commit -m "Update shared-lib to latest"
Signed Commits
Verify commit authenticity with GPG:
gpg --gen-key
git config --global user.signingkey YOUR_KEY_ID
git commit -S -m "Signed commit"
git log --show-signature
GitHub displays a “Verified” badge on signed commits.
Worktrees — Multiple Branches Simultaneously
Work on two branches without stashing:
git worktree add ../hotfix-work hotfix/critical-bug
# Creates ../hotfix-work directory on hotfix/critical-bug branch
cd ../hotfix-work
# Fix bug, commit, push
git worktree list
git worktree remove ../hotfix-work
What Comes Next
Apply these techniques in Collaboration workflows with Pull Requests, code review, and protected branches.