A git rebase stops on a conflict — what do --continue, --skip, and --abort each do?
answer
- Think of it as a queue being worked through
- One exit discards a commit, not a conflict
- The branch ref has not moved while paused
- Staging is what makes the resume possible
- A fourth exit keeps the partial result
basics
~20 sAfter you stage a resolution, git rebase --continue records that commit and resumes the replay. git rebase --skip discards the commit being replayed entirely and moves on. git rebase --abort ends the whole operation and returns the branch to its pre-rebase tip.
solid answer
~50 sA rebase is a sequencer: it holds a list of commits to replay and works through them one at a time. When one fails to apply cleanly it pauses, leaving the conflicted paths unmerged and the remaining list on disk under `.git/rebase-merge`, with HEAD detached on the partially rebuilt branch. From there you have three exits. Resolve the conflict, `git add` the paths, and `git rebase --continue` — Git records the resolved commit and carries on with the rest. `git rebase --skip` **drops the current commit from the result** and moves to the next one; that is right when the commit's change is already upstream (Git often reports it as now empty) and destructive when you meant to resolve it. `git rebase --abort` throws the whole partial replay away and puts the branch back exactly where it started. There is also `git rebase --quit`, which stops the rebase but leaves HEAD where the replay reached.
go deeper
Memorise the three exits and, above all, that skipping drops a commit. Aborting is always safe and is the right move when confused.
Describe the sequencer: a todo list worked through one commit at a time, a detached HEAD during the pause, staging as the resume signal, and per-commit conflicts.
Show the judgement calls — when an empty commit legitimately warrants skipping, when to abort rather than push through, and how you verify afterwards that nothing was silently dropped.
Own the risk: rebases that stop repeatedly are a signal about branch lifetime and review latency. Decide what the team does when a replay fights back rather than letting people skip their way out.
## Why a rebase pauses at all Rebase does not compute one combined result the way a merge does. It replays commits individually, applying each commit's change to the state built so far. Any one of those applications can conflict, so a branch of N commits offers up to N separate pauses. This surprises people who expect a rebase to behave like a merge with a single conflict resolution. ## The paused state When a replay conflicts, Git leaves a well-defined state: - Conflicted paths are unmerged in the index, with markers written into the working tree. - HEAD is detached, pointing at the last successfully replayed commit — your branch ref has *not* moved yet. - The remaining todo list and the bookkeeping live in `.git/rebase-merge`, which is why `git status` can tell you which commit of how many you are on. A useful detail: because HEAD is detached and the branch ref still points at the original tip, an abort has an unambiguous place to return to, and the pre-rebase tip is also recorded in `ORIG_HEAD` and the reflog. ## --continue This is the normal exit. Resolve the conflicted files to the content you want, `git add` each one so the path becomes resolved in the index, then `git rebase --continue`. Git creates the commit for the current step from the staged content and proceeds to the next entry in the todo list — where it may conflict again. If you staged nothing and the resolution left no changes at all, Git tells you the commit has become empty and asks you to choose explicitly rather than guessing. A frequent error is running `--continue` while paths are still unmerged; Git refuses, because it will not commit an unresolved index. `git status` is the checklist. ## --skip `git rebase --skip` abandons the commit currently being replayed. It does not skip the *conflict*; it skips the *commit*, so that commit's change is simply absent from the rebased branch. There is a legitimate use: when the change is already present in the new base — a cherry-pick that was landed upstream, a fix applied twice — Git reports the commit as empty and skipping is exactly right. There is also a very common misuse: reaching for `--skip` to make an annoying conflict stop, which silently deletes work. If in doubt, abort and restart rather than skip. ## --abort `git rebase --abort` discards the partial replay and restores the branch to its pre-rebase tip and the working tree with it. Nothing you had committed before the rebase is lost, because the original commits were never modified — the branch ref simply goes back to pointing at them. Aborting is cheap and is the right reflex whenever you have lost track of what you resolved or suspect you resolved a hunk the wrong way round. ## --quit The fourth exit is `git rebase --quit`: it clears the rebase state but leaves HEAD where the replay currently sits, rather than rewinding. It is the tool for "I want to keep what has been replayed so far and stop treating this as a rebase" — rare, sharp, and easy to leave a confusing state behind, so it should be used deliberately. ## Recovering after the fact Once a rebase has completed, `--abort` is no longer available, but recovery is: the branch's previous tip is in the reflog, and resetting to it restores the pre-rebase branch exactly, since the original commits still exist as objects. This makes the whole operation far less frightening than it first appears — the question is never "can I get back?" but "do I know which position to get back to?". ## What a good answer includes State the three exits precisely, and be explicit that `--skip` drops a commit rather than a conflict — that single distinction is what the question is really probing. Adding that each pause is per commit, that the branch ref has not moved during the pause, and that a completed rebase is still recoverable through the reflog, turns a memorised triple into a demonstrated model of the sequencer.
- When is git rebase --skip the right choice rather than a way to lose work?When the commit's change is already present in the new base, so replaying it produces nothing. Git usually reports the commit as having become empty in that situation. Skipping to make a genuine conflict go away silently drops that commit's change from the branch — if unsure, abort and restart instead.
- Why does Git refuse git rebase --continue sometimes even after you edited the files?Because paths are still unmerged in the index. Editing the working tree does not resolve anything; `git add` collapses a conflicted path's stage entries into a resolved entry. Until every conflicted path is staged, Git will not create the commit for the current step. `git status` lists what remains.
- A rebase already finished and you want the pre-rebase branch back. What now?`--abort` no longer applies, but the original commits still exist and the branch's previous tip is recorded in the reflog and in ORIG_HEAD. Read the pre-rebase position from the reflog and reset the branch to it; the replayed copies become unreferenced and the branch is exactly as it was.
saying these in an interview costs you the question
- Thinks --skip skips the conflict but keeps the commit
- Believes --abort loses the commits being replayed
- Runs --continue without staging the resolved paths
- Expects one conflict stop for the whole rebase
- Assumes the branch already moved while the rebase is paused