Git Cheatsheet
Rebasing
Use this Git reference while you build software engineering projects, review code, or refresh the syntax you reach for most.
Basic Rebase
Rebase replays commits from the current branch on top of another base commit, producing a linear history.
git rebase <branch> # Rebase current branch onto <branch> git rebase main # Most common: rebase current feature onto main git rebase origin/main # Rebase onto remote-tracking branch git rebase <sha> # Rebase onto a specific commit git rebase --onto <newbase> <upstream> <branch> # Three-argument form (see below)
Merge vs. Rebase
Before: main: A---B---C feature: D---E git merge main → preserves fork: feature: A---B---C---M (merge commit) \ / D-E git rebase main → linear history: feature: A---B---C---D'---E'
Interactive Rebase
Rewrite, reorder, squash, edit, or drop commits in a range:
git rebase -i HEAD~3 # Interactively rebase the last 3 commits git rebase -i HEAD~10 # Last 10 commits git rebase -i <sha> # Commits after a specific commit git rebase -i <sha>^ # Include that commit too git rebase -i --root # Edit the entire history from the very first commit
Interactive Rebase Commands
| Command | Alias | Action |
|---|---|---|
pick | p | Keep the commit as-is |
reword | r | Keep commit but edit the message |
edit | e | Pause to amend the commit (changes or message) |
squash | s | Meld into the previous commit (keep both messages) |
fixup | f | Meld into the previous commit (discard this message) |
drop | d | Remove the commit entirely |
exec | x | Run a shell command after this commit |
break | b | Pause here (use --continue to resume) |
label | l | Label the current HEAD for use by reset |
reset | t | Reset HEAD to a label |
merge | m | Create a merge commit (preserves branches in rebase) |
# Example: squash last 3 commits into one git rebase -i HEAD~3 # In the editor, change "pick" to "squash" (or "fixup") for commits 2 and 3
Rebase Flow Control
git rebase --continue # Continue after resolving a conflict git rebase --skip # Skip the current conflicting commit git rebase --abort # Abort the entire rebase, return to pre-rebase state git rebase --quit # Abort but leave HEAD where it is (Git ≥2.12) git rebase --edit-todo # Re-open the todo list in interactive rebase git rebase --show-current-patch # Show the current conflicting patch
The --onto Flag
Replays commits from <upstream>...<branch> onto <newbase>:
git rebase --onto <newbase> <upstream> <branch>
# Move feature2 (branched from feature1) directly onto main git rebase --onto main feature1 feature2 # Move the last 4 commits to a different base git rebase --onto main HEAD~4 HEAD # Remove a range of commits from the middle git rebase --onto HEAD~5 HEAD~3 HEAD # Drop the 2 commits at HEAD~4 and HEAD~3
Visual Example
Before: main: A---B feature1: A---B---C---D feature2: A---B---C---D---E---F git rebase --onto main feature1 feature2 After: main: A---B feature1: A---B---C---D (unchanged) feature2: A---B---E'---F'
Rebasing onto a Remote
git fetch origin git rebase origin/main # Rebase onto the fetched remote main git pull --rebase # Fetch + rebase in one step git pull --rebase=interactive # Fetch + interactive rebase
Autosquash
Automatically squash commits whose messages start with fixup! or squash!:
git commit --fixup=<sha> # Create a "fixup! <original-message>" commit git commit --squash=<sha> # Create a "squash! <original-message>" commit git rebase -i --autosquash HEAD~10 # Auto-arrange fixup!/squash! commits
Auto-enable autosquash:
git config --global rebase.autoSquash trueAuto-Stash During Rebase
git rebase --autostash main # Stash dirty state, rebase, re-apply stash git config --global rebase.autoStash true # Always auto-stash
Rebase Preserving Merges
git rebase -p <branch> # Preserve merge commits (--preserve-merges, deprecated) git rebase --rebase-merges <branch> # Modern replacement (Git ≥2.18) git rebase -r <branch> # Shorthand for --rebase-merges
Resolving Rebase Conflicts
git status # See which file has a conflict # Edit the file and resolve conflict markers git add <resolved-file> git rebase --continue # Move to the next commit # or: git rebase --skip # Drop this commit's changes and continue # or: git rebase --abort # Give up and return to pre-rebase state
During interactive rebase with edit:
# Git pauses at that commit in detached HEAD git commit --amend # Amend the commit (message or changes) git rebase --continue # Resume
exec Command
Run a command after each (or a specific) commit during interactive rebase:
# In the todo list:
pick abc1234 feat: add login
exec npm test
pick def5678 feat: add logout
exec npm testOr run a command across all commits:
git rebase -i --exec "npm test" HEAD~10
Splitting a Commit
git rebase -i HEAD~3 # Mark the commit you want to split as "edit" # Git pauses at that commit: git reset HEAD^ # Unstage all changes from this commit git add -p # Stage first portion interactively git commit -m "part one" git add -p # Stage second portion git commit -m "part two" git rebase --continue
Safety Rules
Never rebase commits that have been pushed to a shared branch. Rebase rewrites commit SHAs; pushing rewritten commits forces everyone else to reconcile diverged history.
Safe to rebase: local-only commits, personal feature branches not shared with others.
If you've already pushed and must rebase anyway: coordinate with the team, then
git push --force-with-lease.
Configuring Rebase Defaults
git config --global pull.rebase true # Always rebase on pull git config --global rebase.autoSquash true # Enable --autosquash by default git config --global rebase.autoStash true # Auto-stash dirty state git config --global rebase.stat true # Show diffstat after rebase git config --global sequence.editor "code --wait" # Editor for todo list
Checking for Rebase Conflicts Ahead of Time
git merge-base main HEAD # Find the common ancestor SHA git log main..HEAD # Commits that will be replayed git diff main...HEAD # Changes introduced since branch point