17 Git Rebase vs Merge Interview Questions

·18 min read
By ·Updated
gitinterview-questionsversion-controlrebasemergedevops

The rebase-versus-merge question is really about commit identity, graph topology, collaboration contracts, review, and recovery. A strong answer explains what each command changes and then follows the repository's branch policy instead of repeating a universal slogan.

Table of Contents

  1. Git Merge vs Rebase Fundamentals Questions
  2. Commit Graph and History Questions
  3. The Golden Rule Questions
  4. Interactive Rebase Questions
  5. Conflict Resolution Questions
  6. Recovery and Undo Questions
  7. Workflow Questions
  8. Quick Reference

Git Merge vs Rebase Fundamentals Questions

These questions test your understanding of the core difference between merge and rebase.

What is the difference between git merge and git rebase?

A true merge joins two development histories with a commit whose parents are the previous tips. If the current tip is already an ancestor of the other, default git merge can fast-forward the current ref without creating a merge commit; --no-ff requests an integration commit and --ff-only refuses a non-fast-forward merge.

Merge normally leaves existing commit objects unchanged and can preserve branch topology. It still moves refs and updates the index and working tree, so “non-destructive” should not be read as “no state changes” or “impossible to make a mistake.” A squash merge deliberately does not record the other tip as a parent.

Rebase finds a selected commit range, resets the working branch to a new base, and reapplies changes commit by commit. Reapplied commits normally have new parents and therefore new object IDs, even when their patch is similar. The old objects may remain reachable through reflogs or other refs for a time. By default, merge commits in the rebased range are not preserved; --rebase-merges attempts to recreate their topology.

When should you use git rebase vs merge?

The choice depends on whether you're working with shared or local branches and what kind of history you want to maintain.

Use the repository's documented policy. Merge is useful when branch topology or an explicit integration point matters and when a shared ref should advance without replacing published commits. Rebase is useful when a topic branch's owners accept rewritten objects and a linearized review helps. Squash merge can land one aggregate change without importing the topic branch as a parent.

A team may rebase topic branches and merge them with --no-ff, fast-forward rebased commits, squash through the hosting platform, or merge the target branch into the topic. The decision affects open reviews, stacked branches, bisectability, signatures, CI, release automation, and how conflicts are paid. No single combination is best for every repository.

Key principle: Rewrite only refs whose collaboration contract permits it; choose the integration shape deliberately.


Commit Graph and History Questions

These questions test your understanding of how Git's commit graph changes with each operation.

How does the commit graph change with merge vs rebase?

Understanding the visual difference is crucial. Imagine you have a main branch with three commits (A, B, C), and you created a feature branch from commit B with two commits (D, E):

main:     A---B---C
               \
feature:        D---E

When both tips have diverged, a normal merge creates a new merge commit (M) with two parents:

main:     A---B---C-------M
               \         /
feature:        D---E---/

The merge commit records both tips as parents, retaining this topology.

When you rebase feature onto main instead, Git identifies commits D and E, temporarily sets them aside, moves the feature branch pointer to C, and replays D and E on top:

main:     A---B---C
                   \
feature:            D'---E'

Notice D' and E' instead of D and E—these are new commits with different object IDs and parents. Their patches may also differ because of conflict resolution. After rebasing, integrating the feature can be a fast-forward if main has not advanced again:

main:     A---B---C---D'---E'

This history is linear, but whether it is easier to review or debug depends on the project and what topology/context was removed.

What is a fast-forward merge?

A fast-forward merge occurs when the target branch (like main) hasn't diverged from the source branch. Instead of creating a merge commit, Git simply moves the branch pointer forward.

This can happen after rebasing when the target has not advanced again. It also happens without rebase whenever the target tip is already an ancestor of the source tip.

# After rebasing feature onto main
git checkout main
git merge feature  # Fast-forward, no merge commit created

If you want to always create a merge commit even when fast-forward is possible (to preserve the record that a feature branch existed), use:

git merge --no-ff feature

The Golden Rule Questions

These questions test your understanding of when rebasing becomes dangerous.

What is the golden rule of rebasing?

Do not rewrite a shared ref unless its owners and consumers expect the rewrite and coordinate around it. “Pushed” is not the decisive property: many personal review branches are intentionally rebased, while protected integration branches usually reject non-fast-forward updates.

Rebase creates replacement commits. Collaborators, stacked branches, open review comments, signatures, tags, build attestations, and automation may still reference the old objects. Replacing a remote tip without agreement can duplicate changes, invalidate references, or hide commits from the updated branch.

Consider this scenario: you're working on a feature branch and push it so your teammate can collaborate:

Your feature:  A---B---C  (pushed to origin)
                       \
Teammate's:             D---E

Now you rebase your feature branch onto main:

Your feature:  A---B'---C'  (remote ref now points to replacements)

Teammate's:    D---E  (still based on original C)

Your teammate's commits D and E are still based on C, while the rewritten branch contains C'. Git sees divergent histories; recovery might require rebasing with the old/new boundary, cherry-picking, or merging, and careless integration can duplicate patches.

How do you safely force push after rebasing?

After coordinating a permitted rewrite, fetch and protect the exact remote ref you intend to replace. A plain lease is safer than blind force, but an explicit expected object ID is stronger:

git fetch origin
expected=$(git rev-parse origin/feature)
 
# Inspect expected and the outgoing range before updating one named ref.
git log --oneline --graph "$expected"..feature
git push --force-with-lease=refs/heads/feature:"$expected" \
  origin feature:refs/heads/feature

The explicit lease succeeds only if the server-side ref still has the expected value. Plain --force-with-lease usually compares against a remote-tracking ref, which background fetches can update and thereby weaken the “what I actually saw” assumption. --force-if-includes can add a reachability check for the implicit form, but it does not replace review of the exact ref and commits.

Avoid plain --force: it disables non-fast-forward and lease checks and can affect more refs than intended depending on refspec configuration. Hosting-platform protection, required review, and server policy remain the strongest controls for important branches.


Interactive Rebase Questions

These questions test your ability to clean up commit history.

What is interactive rebase and how do you use it?

Interactive rebase (git rebase -i) lets you modify commits during the rebase process. You can squash multiple commits into one, reword commit messages, reorder commits, edit commit contents, or drop commits entirely.

Say your commit history looks like this:

abc123 Add login form
def456 Fix typo in login form
ghi789 Add validation to login form
jkl012 Fix validation bug
mno345 Add password strength indicator
pqr678 Fix password strength indicator styling

Run git rebase -i HEAD~6 to interactively rebase the last 6 commits. Git opens your editor:

pick abc123 Add login form
pick def456 Fix typo in login form
pick ghi789 Add validation to login form
pick jkl012 Fix validation bug
pick mno345 Add password strength indicator
pick pqr678 Fix password strength indicator styling

Edit to squash related commits:

pick abc123 Add login form
squash def456 Fix typo in login form
squash ghi789 Add validation to login form
squash jkl012 Fix validation bug
pick mno345 Add password strength indicator
squash pqr678 Fix password strength indicator styling

The result is a smaller rewritten history (with new object IDs):

new111 Add login form with validation
new222 Add password strength indicator

What are the interactive rebase commands?

The available commands give you powerful control over commit history:

CommandEffect
pickKeep the commit as-is
rewordKeep the commit but edit its message
editPause the rebase to amend the commit
squashCombine with previous commit, edit message
fixupCombine with previous commit, discard message
dropRemove the commit entirely
execRun a shell command and stop if it fails
breakPause so you can inspect or amend state
update-refMove another ref to the rewritten commit at the end

A useful workflow is git commit --fixup=<commit> followed by git rebase -i --autosquash <upstream>. Inspect the todo list and run the relevant tests. For histories containing merges, decide explicitly whether flattening is acceptable or whether --rebase-merges should attempt to recreate topology; complex merges can still require manual work.

How do you fix a typo in a commit message from 3 commits ago?

Use interactive rebase with the reword command:

git rebase -i HEAD~3

In the editor, change pick to reword for the commit with the typo:

reword abc123 Add login form  # Will prompt to edit message
pick def456 Add validation
pick ghi789 Add tests

When you save and close, Git opens another editor where you can fix the commit message. This creates new commits with corrected messages (and new hashes) for that commit and all subsequent commits.


Conflict Resolution Questions

These questions test your understanding of how conflicts differ between merge and rebase.

How do you resolve conflicts during merge vs rebase?

In a true merge, Git performs one merge operation between the selected tips and common ancestors. Paths that cannot be resolved automatically remain unmerged until you resolve and stage them before the merge commit.

During rebase, Git reapplies commits one at a time, so it can stop more than once and the same conceptual conflict can recur. Inspect git status and git rebase --show-current-patch. A frequent trap is terminology: during rebase, “ours” is the partially rebased upstream side and “theirs” is the commit being replayed. Do not choose a side by label without inspecting the intended result.

Rebase conflict workflow:

# Start the rebase
git rebase main
 
# Git stops at the first conflicting commit
# CONFLICT (content): Merge conflict in src/auth.js
 
# Open the file and resolve the conflict markers
<<<<<<< HEAD
const AUTH_URL = '/api/v2/auth';
=======
const AUTH_URL = '/api/v1/auth';
>>>>>>> feat: Add login form
 
# Edit to resolve, then stage
git add src/auth.js
 
# Continue to the next commit
git rebase --continue
 
# Repeat until all commits are replayed

How do you abort a rebase in progress?

If things go badly wrong during a rebase, abort and return to your pre-rebase state:

git rebase --abort

--abort resets HEAD to the original branch/state recorded for the rebase. Starting with unrelated uncommitted work is still risky; inspect status and stash or commit intentionally before a history edit. --quit is different: it stops the rebase without resetting HEAD and leaves the index/working tree as they are.

--skip does not merely bypass conflict handling; it drops the current commit's patch from the rewritten result. Use it only after confirming that the change is already present or intentionally unwanted:

git rebase --skip

Recovery and Undo Questions

These questions test your ability to recover from Git mistakes.

How do you undo a rebase if something goes wrong?

First stop changing state, inspect git status and the local reflog, identify the exact pre-rebase object ID, and create a rescue ref. Reflog selectors move as new actions occur, so use the resolved SHA in subsequent commands:

# View the history of HEAD movements
git reflog
 
# Output shows something like:
abc123 HEAD@{0}: rebase finished
def456 HEAD@{1}: rebase: Add validation
ghi789 HEAD@{2}: rebase: Add login form
jkl012 HEAD@{3}: checkout: moving from feature to main
mno345 HEAD@{4}: commit: Add tests  # <- Before rebase!
 
# Preserve the old tip before choosing a recovery operation
git branch rescue/pre-rebase mno345
 
# If you intentionally want the current branch to point there and the worktree is clean:
git reset --hard mno345

git reset --hard discards tracked index and working-tree changes, so it is not the first diagnostic step. Often you can switch to the rescue branch, compare both histories, and then decide. Reflogs are local and expire; old objects can be pruned. A remote ref, tag, backup, or collaborator's clone may be the remaining recovery source.

What is the difference between git reset and git revert?

Both undo changes, but in fundamentally different ways.

In its commit form, git reset moves HEAD/the current branch and, depending on --soft, --mixed, --merge, --keep, or --hard, changes the index and working tree. Path and patch forms instead adjust staged content. Commits may become unreachable from that branch, but other refs or reflogs can still reach them.

git revert applies an inverse change and normally creates a new commit, leaving the original topology reachable. Reverting a merge requires choosing a mainline parent with -m and has future-merge consequences, so it is not automatically trivial or conflict-free.

# Reset: only after preserving anything needed and checking branch policy
git branch rescue/before-reset
git reset --hard HEAD~2
 
# Revert: adds new commit (safe for shared branches)
git revert abc123  # Create commit that undoes abc123

Guideline: Prefer revert when a shared ref must retain an append-only audit trail. Use reset when moving the ref is authorized and you understand the selected mode's effect on commits, index, and working tree.

What is git cherry-pick and when would you use it?

Cherry-pick applies the change introduced by one or more existing commits onto the current branch and normally creates new commit objects. It does not preserve the source commit as a parent and can conflict or duplicate a patch that arrived another way.

# Apply a specific commit to current branch
git cherry-pick abc123
 
# Apply multiple commits
git cherry-pick abc123 def456
 
# Apply without committing (stage changes only)
git cherry-pick --no-commit abc123

Use cases:

  • A specific bug fix from a release branch is needed in your feature branch
  • A commit was accidentally made on the wrong branch
  • You want to selectively apply changes without bringing in everything else

Cherry-pick is a precision tool for specific situations rather than an everyday operation.


Workflow Questions

These questions test your understanding of real-world Git workflows.

What is the difference between merge --squash and rebase followed by merge?

Both can result in cleaner history but work differently.

git merge --squash feature takes all commits from the feature branch and combines them into a single set of staged changes. You then commit as a single commit. The original branch history isn't recorded, so you lose visibility into individual commits.

Rebase followed by merge first rebases your feature branch onto main (creating new commits in a linear sequence), then merges the rebased branch. If main hasn't moved, this is a fast-forward merge and your individual commits are preserved in the linear history.

ApproachPreserves Individual CommitsCreates Merge Commit
Merge --squashNo (all combined into one)No
Rebase + mergeYes (linear history)Optional
Regular mergeYes (with branch structure)Yes

Choose from repository policy and desired audit/review/bisect behavior. Well-structured commits can be retained through fast-forward or non-fast-forward integration; a squash commit can intentionally represent only the aggregate change. “Messy” is a review problem to fix, not a universal reason to discard authorship or topology.

How do you update a feature branch with changes from main?

You can rebase the topic branch when its collaboration contract permits rewriting, or merge the target branch when preserving published commit identity matters. For a rebase workflow:

# Fetch latest changes
git fetch origin
 
# Rebase your feature branch onto main
git rebase origin/main
 
# If conflicts occur, resolve commit-by-commit
# git add <resolved-files>
# git rebase --continue
 
# If the branch is intentionally rewriteable, use an explicit lease as shown above.

This reapplies the selected topic commits on origin/main. It does not prove integration correctness; run the relevant tests and review the rewritten range. If the branch is shared, coordinate or merge origin/main instead.

How do you clean up commits before creating a pull request?

Use interactive rebase to squash WIP commits into logical units:

# Rebase the last N commits interactively
git rebase -i HEAD~8
 
# In the editor:
# - Mark first commit of each logical group as 'pick'
# - Mark related commits as 'squash' or 'fixup'
# - Reorder if needed
 
# After saving, write clear commit messages for each logical group

The goal is reviewable commits whose messages explain intent and whose boundaries support the project's review, bisect, revert, signature, and release needs. Whether every intermediate commit must build is a repository policy, not a Git invariant.


Quick Reference

AspectMergeRebase
History shapeTrue merge records both parents; fast-forward does notReapplies a selected range; normally linearizes it
Commit identityExisting commits remain; merge commit may be newReapplied commits normally get new object IDs
Shared-ref impactUsually advances without replacing reachable historyRequires explicit rewrite policy and coordination
Conflict cadenceOne merge operationCan stop for each replayed commit
Merge topologyRetained by a true mergeFlattened by default; --rebase-merges can recreate it
RecoveryAbort in progress; revert/reset based on policyAbort in progress; rescue old tip via reflog/other refs


Git Rebase vs Merge FAQ

What is the difference between git merge and git rebase?

A true merge joins histories with a commit that has both tips as parents; when one tip is already an ancestor, the default merge can instead fast-forward a ref. Rebase selects commits from one line of development and reapplies their changes onto a new base, normally creating new commit objects. Merge can retain branch topology; rebase can linearize selected history, but neither shape is universally clearer or safer.

When should I use git rebase vs merge?

Follow the repository's integration and branch policy. Merge when topology and a non-fast-forward integration record are useful or a shared ref must advance without rewriting. Rebase when the owners of a topic branch accept rewritten commits and linear review is useful. Squash merge is another option when only the aggregate change should land. Evaluate signatures, audit rules, CI, stacked branches, and collaborator coordination.

What is the golden rule of rebasing in Git?

Do not rewrite a shared ref unless its owners and consumers expect that rewrite and have coordinated recovery. A pushed personal review branch may be intentionally rebased; a protected integration branch usually may not. Rebase creates replacement commits, so collaborators, open reviews, signatures, tags, automation, and stacked work that reference the old objects must be considered before force-updating the ref.

What is interactive rebase and when should I use it?

Interactive rebase lets you reorder, reword, edit, squash, fix up, drop, test, or pause while rewriting a selected commit range. Use it only where rewriting is allowed, inspect the todo range and merge topology, preserve a rescue ref for risky work, and run relevant checks. --autosquash can place fixup commits; --rebase-merges can attempt to recreate merges rather than flattening them.

How do I resolve conflicts during a git rebase?

Inspect the stopped commit and conflict stages, resolve each path, stage the intended result with git add, run tests, and continue with git rebase --continue. Repeat for later commits. During rebase, ours refers to the partially rebased upstream side and theirs to the commit being replayed, which can surprise users. git rebase --skip drops the current commit; use it only after verifying its change is truly unnecessary. Use --abort to return to the pre-rebase branch state.

Can I undo a git rebase if something goes wrong?

Usually. Stop and inspect git status and git reflog, identify the exact old tip, and first create a rescue branch such as git branch rescue/pre-rebase OLD_SHA. Then choose a non-destructive branch switch or an appropriate reset. git reset --hard discards tracked working-tree and index changes, so do not use it as a reflex. Reflogs are local and expire; remote refs, tags, backups, or another clone may be needed.

Sources

Ready to ace your interview?

Get 550+ interview questions with detailed answers in our comprehensive PDF guides.

View PDF Guides