Git commands
How to cancel a merge in Git after it stops on a conflict
git merge --abort: backing out of a conflicted merge
How to use this page
- slider / ▶Drag the slider, or press play, to watch the command happen. Before and After jump to either end.
- ← → · spaceStep through a multi-step command; space toggles Before / After.
- APlay or pause the loop (the page opens playing). Any manual input takes over.
- hoverA commit shows its message, author, date and parents, with its history highlighted.
- clickCopies the commit sha.
- ctrl + wheelZoom around the cursor (pinch on a trackpad). Double-click resets the view.
- EscStop playback, reset the view, close this menu.
- shareThe Share button copies a link to this graph, copies it as an image, downloads PNG/SVG/page, or posts it. #before, #after or #step=N in the link pins the state.
git-sim visually simulates any Git command in your own repos - from your terminal, IDE, or AI.
Table of Contents
- Introduction
- What is git merge --abort?
- What does "stopped on a conflict" mean?
- Watch it happen
- Before and after
- Is it safe?
- When does it refuse?
- How to undo it
- Useful forms
- Try it on your repository
- Common questions
- Summary
- Next steps
- Related commands
Introduction
If you've merged branches for any length of time, you've seen Git stop halfway with "Automatic merge failed; fix conflicts and then commit the result." Sometimes you're ready to sort it out right there. Other times the conflict is in a file you don't know, or it's late, or you realize you merged the wrong branch. git merge --abort is the way out: it drops the half-finished merge and puts your branch and files back where they were before you typed git merge.
In this article, we'll:
- Look at what a merge stopped on a conflict actually is, and how to tell you're in one
- Watch
git merge --aborton a merge offeatureintomainthat conflicted instyles.css - Cover what it throws away, the older
git reset --mergespelling, and when it refuses
What is git merge --abort?
git merge --abort cancels a merge that is still in progress. It resets the staging area and the working directory to the commit you were on when the merge started, removes the files Git uses to remember the merge, and leaves your branch exactly where it was. No commit is created and no label moves.
It only works while a merge is in progress. Once the merge has been committed, there is nothing to abort, and you undo it a different way.
What does "stopped on a conflict" mean?
When git merge can't combine two changes to the same lines, it doesn't guess. It merges everything it can, stages those files, and stops before making the merge commit. Three things tell you you're in that state.
First, Git writes a file called .git/MERGE_HEAD holding the hash of the commit you're merging in. That file is what makes the next git commit a merge commit with two parents, and it's also what --abort looks for.
Second, the conflicted file has conflict markers in it, showing both versions side by side. In our sample repo, styles.css looks like this:
<<<<<<< HEAD
header { display: grid; }
=======
header { display: flex; gap: 12px; }
>>>>>>> feature
The top half is main's version from "Switch the header to grid", the bottom half is feature's from "Space out the header links". Pro Git has a longer walk through reading these markers.
Third, git status says so, and even suggests the way out:
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abort the merge)
Watch it happen
Our sample repo has a merge of feature into main stopped on a conflict in styles.css. main has "Switch the header to grid" (ada2e79) on top, feature ends in "Space out the header links" (791fd8e), and both changed the same line of styles.css. Here's git merge --abort:
- Before:
mainandHEADpoint atada2e79, andfeaturepoints at "Space out the header links" (791fd8e). Git stopped before making the merge commit, whose two parents would beada2e79and791fd8e.MERGE_HEADpoints at791fd8e, which is how Git remembers what it was merging.styles.cssis unmerged (in conflict), and the two files that merged cleanly,search.htmlandtest_search.py, are staged fromfeature. - Git deletes
MERGE_HEADand resets the index, dropping the conflict and the staged changes. styles.cssgoes back to its version inada2e79, andsearch.htmlandtest_search.pyare removed from the working directory, becausemaindoesn't have them yet. None of that work is lost: all three changes are still onfeature, where the merge found them. Nothing is committed, and any work on the conflicted file is discarded too. NeithermainnorHEADmoves.
Before and after
The two pictures are the same, and they should be. A stopped merge lives in the staging area and the working directory, not in the commit graph. The difference shows up in git status --short --branch. Before the abort, the two files the merge brought in cleanly are staged and styles.css is unmerged:
## main
A search.html
UU styles.css
A test_search.py
After, the status is clean:
## main
search.html and test_search.py are gone from the working directory again, since they only existed on feature. The abort itself prints nothing:
The raw git output, if you want to read along in text
git log --oneline --graph --all
before
* 791fd8e (feature) Space out the header links
* 1117a34 Add search tests
* e5869f0 Fix typo in search box
* fc19889 Add search box
| * ada2e79 (HEAD -> main) Switch the header to grid
| * 8c02d5b Update dependencies
| * a0b2db3 Add user settings page
|/
* 96c4fc2 Fix header layout
* ae65976 Add login page
* 3e1ffe4 Add project skeleton
* 4114b2c Initial commitafter
* 791fd8e (feature) Space out the header links
* 1117a34 Add search tests
* e5869f0 Fix typo in search box
* fc19889 Add search box
| * ada2e79 (HEAD -> main) Switch the header to grid
| * 8c02d5b Update dependencies
| * a0b2db3 Add user settings page
|/
* 96c4fc2 Fix header layout
* ae65976 Add login page
* 3e1ffe4 Add project skeleton
* 4114b2c Initial commitIs it safe?
Caution git-sim pre-flight
Calls off the merge: HEAD stays on ada2e79, and the staging area and working directory are reset to it. Nothing is committed.
What you would lose
- your edits to styles.css since the merge stopped (not recoverable)
The way back
Run the same merge again to get the conflict back; the edits themselves can't be recovered.
For your commits, yes. No commit is created, removed or moved, and feature is untouched. The one thing it throws away is whatever you did to the conflicted file after the merge stopped. If you had spent ten minutes combining the two header rules by hand, that edit is gone, because Git never stored it anywhere. The files that merged cleanly are thrown out too, but those are easy to get back by merging again.
git log -p feature -- styles.css, and then merge again knowing what I'm looking at. --abort has been around since Git 1.7.4 in 2011. Before that, the way out was git reset --merge, which still works.
When does it refuse?
The simplest case is when there's no merge to abort:
fatal: There is no merge to abort (MERGE_HEAD missing).
That usually means the merge already finished, or you're in the middle of a rebase or cherry-pick instead, which have their own --abort.
The trickier case is uncommitted work from before the merge. Git lets you start a merge with edits in files the merge doesn't touch, and --abort normally leaves those alone. But the git merge documentation warns that it "will in some cases be unable to reconstruct" them, especially if you kept editing after the merge stopped. When a file has unstaged changes that the abort would have to overwrite, it stops with an error instead of clobbering them. The safe habit is to commit or stash your changes before merging, so there's nothing for the abort to trip over.
How to undo it
There isn't much to undo, since nothing was committed. To get the conflict back, run the same merge again:
git merge feature
Git stops on styles.css exactly as before, and this time you can resolve it and finish with git merge --continue:
Useful forms
git reset --mergeis the older command--abortis built on. With a merge in progress the two do the same thing.git merge --quitforgets the merge but leaves the staging area and working directory as they are, conflict markers and all. It's for when you want out of the merge state but want to keep the files to pick through by hand.git merge --abortworks after agit pullthat stopped on a conflict too, as long as the pull was merging rather than rebasing.
Try it on your repository
pip install git-sim
git-sim merge --abort
git-sim runs the abort in a copy of your repository and draws what would change, so your own conflicted merge stays exactly as it is.
Common questions
What does git merge --abort do?
It cancels a merge that stopped on a conflict. Your branch stays where it was, and the staging area and working directory go back to that commit. Nothing is committed.
Does git merge --abort delete my changes?
It discards anything you did to the conflicted files after the merge stopped. Uncommitted changes from before the merge are normally kept, but Git can't always rebuild them, so commit or stash before you merge.
What is the difference between git merge --abort and git reset --merge?
While a merge is in progress they do the same thing. --abort is the newer, clearer name, and it also checks that a merge is actually in progress.
What if git merge --abort says there is no merge to abort?
MERGE_HEAD is missing, so Git doesn't think a merge is in progress. Either it already finished (check git log) or you're in a rebase or cherry-pick, which git status will tell you.
Summary
In this article, we looked at what a merge stopped on a conflict is, watched git merge --abort put main back on ada2e79 without a single commit or label moving, and covered what it discards and when it refuses.
Next steps
git merge --continue is the other way out of a stopped merge, once you've resolved the conflict. git merge covers what a finished merge looks like.
Related commands
- git merge --continue, to finish the merge instead
- git merge, the command that stopped
- git status, to see whether a merge is in progress
- git stash, to clear your working directory before merging
- git reset --hard, to undo a merge that was already committed
- git cherry-pick --abort, the same way out for a cherry-pick
