DevOps

Git Advanced: Rebase, Cherry-Pick, and Interactive History

Tech Setup2 min read
TS

Tech Setup

Published August 2, 2026 · Editorial policy

Git Advanced: Rebase, Cherry-Pick, and Interactive History

Interactive Rebase

Interactive rebase lets you rewrite commit history — squash, reorder, edit, or drop commits.

Basic Syntax

# Rebase last 3 commits
git rebase -i HEAD~3

# Rebase since a specific commit
git rebase -i abc1234

The Editor

pick a1b2c3d Add login page
pick d4e5f6g Add password validation
pick h7i8j9k Fix typo in login
pick l0m1n2o Add remember me checkbox

Commands

CommandAction
pickKeep commit as-is
rewordKeep commit, edit message
editPause to amend commit content
squashMerge with previous commit
fixupLike squash, discard this message
dropRemove commit entirely

Squash Example

pick a1b2c3d Add login page
squash d4e5f6g Add password validation
squash h7i8j9k Fix typo in login
pick l0m1n2o Add remember me checkbox

Result: First 3 commits become one.

Reorder Commits

Just reorder the lines:

pick l0m1n2o Add remember me checkbox
pick a1b2c3d Add login page
pick d4e5f6g Add password validation
pick h7i8j9k Fix typo in login

Cherry-Pick

Apply specific commits from one branch to another.

Single Commit

# Get commit hash from source branch
git log feature-branch --oneline
# a1b2c3d Fix critical bug

# Apply to current branch
git cherry-pick a1b2c3d

Multiple Commits

# Cherry-pick range (exclusive of start)
git cherry-pick abc123..def456

# Cherry-pick specific commits
git cherry-pick a1b2c3d d4e5f6g h7i8j9k

Cherry-Pick Without Committing

# Apply changes but don't commit
git cherry-pick --no-commit a1b2c3d

# Review changes
git diff --staged

# Commit manually
git commit -m "Applied fix from feature-branch"

Git Bisect

Binary search through commits to find when a bug was introduced.

# Start bisect
git bisect start

# Mark current commit as bad
git bisect bad

# Mark a known good commit
git bisect good abc1234

# Git checks out middle commit
# Test it, then mark as good or bad
git bisect good  # or
git bisect bad

# Continue until Git finds the culprit
# Result: "xyz789 is the first bad commit"

# Return to original branch
git bisect reset

Automated Bisect

git bisect start
git bisect bad HEAD
git bisect good abc1234

# Git runs test script automatically
git bisect run npm test

# Returns the exact commit that broke tests

Reflog: Undo Anything

The reflog tracks every HEAD movement. Nothing is truly lost until garbage collected.

# View reflog
git reflog

# Output:
# abc1234 HEAD@{0}: reset: moving to HEAD~3
# def5678 HEAD@{1}: commit: Add feature
# ghi9012 HEAD@{2}: commit: Fix bug
# jkl3456 HEAD@{3}: commit: Initial work

Recover Deleted Branch

# Find the commit where the branch pointed
git reflog

# Create branch at that commit
git checkout -b recovered-branch def5678

Undo a Bad Rebase

# Before rebase: abc1234 was HEAD
git reflog
# Find the pre-rebase commit
git reset --hard HEAD@{5}  # or whatever the reflog shows

Stashing Advanced

Stash with Message

git stash push -m "WIP: half-done login feature"

Stash Specific Files

git stash push -m "login changes" src/login.ts src/auth.ts

Stash Untracked Files

git stash --include-untracked

Apply Stash Without Removing

git stash apply stash@{0}

Stash as Branch

git stash branch new-feature-branch stash@{0}

Worktrees

Work on multiple branches simultaneously without stashing.

# Create worktree for hotfix
git worktree add ../hotfix-branch hotfix-123

# Work in the hotfix directory
cd ../hotfix-branch
# ... fix bug, commit ...

# Return to main worktree
cd ../main-repo

# List worktrees
git worktree list

# Remove worktree
git worktree remove ../hotfix-branch

Cleaning Up

Remove Untracked Files

# Preview what will be deleted
git clean -fd --dry-run

# Delete untracked files and directories
git clean -fd

Remove Merged Branches

# List merged branches
git branch --merged main

# Delete merged branches (except main/master)
git branch --merged main | grep -v "main\|master" | xargs git branch -d

# Force delete unmerged branches
git branch --merged main | grep -v "main\|master" | xargs git branch -D

Commit Amendments

Change Last Commit Message

git commit --amend -m "New commit message"

Add Files to Last Commit

git add forgotten-file.ts
git commit --amend --no-edit

Undo Last Commit (Keep Changes)

git reset --soft HEAD~1

Undo Last Commit (Discard Changes)

git reset --hard HEAD~1

Blame (Who Changed What)

git blame src/auth.ts

# Show changes within a range
git blame -L 10,20 src/auth.ts

# Ignore whitespace changes
git blame -w src/auth.ts

Search Commits

# Search commit messages
git log --grep="fix" --oneline

# Search code changes
git log -S "functionName" --oneline

# Search for pattern in diffs
git log -G "regex pattern" --oneline

Add to ~/.gitconfig:

[alias]
    st = status
    co = checkout
    br = branch
    cm = commit
    lg = log --oneline --graph --decorate --all
    unstage = reset HEAD --
    last = log -1 HEAD
    amend = commit --amend --no-edit
    wip = !git add -A && git commit -m 'WIP'
    undo = reset --soft HEAD~1
    Visual = !gitk

Cheat Sheet

TaskCommand
Squash last 3git rebase -i HEAD~3
Cherry-pick commitgit cherry-pick abc123
Find bad commitgit bisect start
Recover deleted branchgit refloggit checkout -b branch hash
Undo last commitgit reset --soft HEAD~1
Stash with namegit stash push -m "name"
Work on 2 branchesgit worktree add ../branch branch-name
Clean untrackedgit clean -fd
Search code historygit log -S "function" --oneline