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.