4816

I accidentally ran git merge some_other_branch on my local master branch. I haven't pushed the changes to origin master. How do I undo the merge?


After merging, git status says:

# On branch master
# Your branch is ahead of 'origin/master' by 5 commits.

How do I undo all these commits?

Mateen Ulhaq
  • 24,552
  • 19
  • 101
  • 135
Matt Huggins
  • 81,398
  • 36
  • 149
  • 218
  • 3
    If you need to preserve the history, in other words there is a change that anyone has ever pulled from you or you have pushed it somewhere use the solution in Yuri Ushakov answer down below! – Sedrik Oct 12 '11 at 08:06
  • 6
    Please unselect the current winning answer, it's unsafe (as many pointed out) though still gathering votes. To me "MBO"-s looks the best, although it has way fewer points. – inger Mar 21 '13 at 14:23
  • 5
    [If you need to **preserve history**, use *Yuri*'s solution down below](http://stackoverflow.com/a/6217372/274502)! (just adding a link to @Sedrik comment) – cregox Sep 17 '13 at 19:08
  • Related: [Revert to a previous Git commit](http://stackoverflow.com/q/4114095/456814). –  Oct 13 '15 at 11:04
  • 4
    This is a great resource straight from Github: [How to undo \(almost\) anything with Git](https://github.com/blog/2019-how-to-undo-almost-anything-with-git) – jasonleonhard Feb 03 '17 at 21:13
  • Git - a story of 3 trees (head, index, and working tree explained in a very helpful way): [Reset Demystified](https://git-scm.com/blog/2011/07/11/reset.html) – leanne May 23 '17 at 22:51

35 Answers35

5437

With git reflog check which commit is one prior the merge (git reflog will be a better option than git log). Then you can reset it using:

git reset --hard commit_sha

There's also another way:

git reset --hard HEAD~1

It will get you back 1 commit.

Be aware that any modified and uncommitted/unstashed files will be reset to their unmodified state. To keep them either stash changes away or see --merge option below.


As @Velmont suggested below in his answer, in this direct case using:

git reset --hard ORIG_HEAD

might yield better results, as it should preserve your changes. ORIG_HEAD will point to a commit directly before merge has occurred, so you don't have to hunt for it yourself.


A further tip is to use the --merge switch instead of --hard since it doesn't reset files unnecessarily:

git reset --merge ORIG_HEAD

--merge

Resets the index and updates the files in the working tree that are different between <commit> and HEAD, but keeps those which are different between the index and working tree (i.e. which have changes which have not been added).

Eric Platon
  • 9,819
  • 6
  • 41
  • 48
Marcin Gil
  • 68,043
  • 8
  • 59
  • 60
  • 147
    I don't think this will (always?) work -- the "one prior the merge" will be the most recent commit that was merged in from the other branch -- it won't be the most recent commit on the current branch. Right? (This might just be a result of what `git log` chooses to show by default -- maybe there is a different output of `git log` or `git reflog` could be used for this) – John Bachir Jan 14 '11 at 18:12
  • 6
    I think it might depend whether you squash merge. – Marcin Gil Jan 15 '11 at 12:45
  • 1
    In my case, git log showed a merge commit and listed the two parent commits that were merged to result in the merge commit. I used git log to determine which of the parent commits listed belonged to the branch I merged in to the current branch, and then reset to the other commit (since that had to be the current branch's HEAD prior to the merge). I would be wary of doing using the `HEAD~#` notation, since you probably don't know how many commits were brought in with the merge. – Matt Jun 29 '11 at 17:55
  • 32
    @JohnBachir is right. In the `git log` output, you want to look at the two parent commits. One is the latest commit in your branch, one is the latest commit in the branch you merged into. You want to `git reset --hard` to the parent commit on the branch you merged into. – Justin Oct 12 '11 at 20:21
  • 7
    @JohnBachir: As long as the "merge" isn't really a fast forward, it will result in a new commit that is at the top of the log, and this commit has two parents (or more than 2 if you do an octopus merge). If you remove this one merge commit, then all of the older commits that came in from the merge will disappear, too. To be safe, though, after a reset git will tell you where the new head is: "HEAD is now at 88a04de ". I always look at that to make sure that I ended up where I expected to be. My project uses a standard branch naming scheme to keep things memorable. – Mark E. Haase Nov 21 '11 at 16:36
  • 54
    What i found useful was to look at "git reflog" and look for the last commit that i did in master. Then do `git reset --hard ` – Max Williams Dec 05 '12 at 16:53
  • I think if it is a FF merge you would probably be best off with something like: git reset --keep master@{1} – cyberoblivion Feb 20 '13 at 16:05
  • `git branch -a -v` will show you all local and remote branches and their SHAs, so use the SHA for remote/master if you want to match that – Jason Goemaat May 24 '13 at 20:57
  • 2
    Maybe this **warning** should go into the answer itself: [***Always avoid rewriting git history!***](http://stackoverflow.com/questions/1491001/what-are-the-practical-consequences-of-rewriting-git-history) – cregox Sep 17 '13 at 20:17
  • Using HEAD~N doesn't work for large N, and finding commit hash is a pain for large N – samthebest Oct 09 '13 at 16:28
  • if the merge was the last state change `git reset --hard HEAD@{1}` will work too -- otherwise use `git reflog` to find the sha or revision reference you want. see also `man gitrevisions` – here Oct 24 '13 at 01:26
  • Instead of doing manual work, you could do the line in my answer below which should always work without the manual bits. – odinho - Velmont Mar 06 '14 at 09:12
  • @Velmont: what you don't notice is that my answer is now 4 (FOUR) years old. Remind me: how much git has evolved from that time? Aye, I'll update the answer since you are correct :) – Marcin Gil Mar 06 '14 at 11:46
  • 2
    @MarcinGil ORIG_HEAD existed at least in 2009 :) Which is 5 years ago. – odinho - Velmont Mar 07 '14 at 12:51
  • 1
    @Velmont but AFAIR not --merge ;) Anyway your answer is cool. – Marcin Gil Mar 07 '14 at 14:24
  • 1
    "git reset --merge ORIG_HEAD" just lost a ton of my changes :-\ – Kirby Todd Oct 15 '14 at 16:26
  • 4
    `git reset --hard` will also discard any local modifications irreversibly in addition to walk back in history. `git reset --keep` resets the history while preserving local changes if any, much safer. – Matthieu Moy May 09 '15 at 10:40
  • I had done worse, I changed the origin without paying attention. Fortunately it is to solve! **---** `--- git reset --hard [sha-commit-before-merge] git push [origin] [branch] --force` **---** [source](https://coderwall.com/p/o0krbw/undo-a-git-merge-that-has-been-pushed-to-the-server) – alex Jun 01 '15 at 20:32
  • 3
    You can also do `git reset --hard origin/master` instead of specifying a commit sha. – Maciej Gurban Apr 20 '16 at 10:42
  • @MarcinGil Could you please update the answer to say that YOU WILL LOSE CODE with git reset --hard? Or make git reset --merge the top part of the answer, rather than the end? I just lost some changes. They were relatively trivial, but for the next person they might not be. – stone Oct 17 '16 at 04:35
  • 2
    @skypecakes: well I would assume that if someone wants to do "undo" - one expects some changes are reverted/lost. Anyway I'm curious of the scenario how have you performed the reset if you lost changes. Only the merge commit itself should be removed, nothing more. – Marcin Gil Oct 17 '16 at 07:30
  • @MarcinGil The code I lost was (in my mind) not related to the undo. It was a set of modified files whose changes had never been committed. Changes I'd been sitting on for a month or so; not needed yet, but possibly useful in the future. After the git reset, those changes disappeared. None of those changed files were involved in the merge (or I'd have gotten errors during the merge operation). I'd been moving between branches all this time leaving those changes uncommitted, and git never seemed to care, so it surprised me that suddenly it removed them. – stone Oct 17 '16 at 21:22
  • @skypecakes Sorry for your lost code but sitting for a month on an changed and uncommitted code (even locally, not pushed) is for me truly unbelievable. I would strongly advise to read the Git Book if you haven't been even expecting what reset could do. Anyway sure, I can add a warning. – Marcin Gil Oct 18 '16 at 07:26
  • @MarcinGil Thanks for adding that warning! I wasn't looking for an apology; like I said, it's no big deal for me. But for someone else it might be. And thanks for the suggestion, I will read the Git Book when I get a chance. – stone Oct 18 '16 at 23:45
  • 2
    This is a great resource straight from Github: [How to undo \(almost\) anything with Git](https://github.com/blog/2019-how-to-undo-almost-anything-with-git) – jasonleonhard Feb 03 '17 at 21:14
  • 2
    please menation ORIG_HEAD method first, it is more likely what people want – Alexander Mills Feb 09 '17 at 04:49
  • 1
    "git reset --hard ORIG_HEAD" might actually NOT preserve your changes. Maybe better warn about that. – Pedro Dec 01 '18 at 23:47
  • This only reset the local copy. When you then try to push to apply the change to GitHub you get an error: "Updates were rejected because the tip of your current branch is behind." This message suggests gt pull. If you follow the suggestion the you end up right where you left off. Thus this answer is incomplete. What magical incantation do you need to push to GitHub? – Benilda Key Mar 05 '20 at 02:20
  • 1
    generally "git reset --hard" works alone if you want to go back to the last commit – Shehan Hasintha Feb 22 '21 at 06:53
  • I had the same situation, I merged and then immediately wanted to revert back. The command I gave was : `git reset --hard HEAD~0` and not HEAD~1, the result was exactly what I wanted, revrting back to the same state before the merge command. – Yariv Aug 20 '22 at 13:08
  • This answer by @Parris with example is really helpful https://stackoverflow.com/a/27571343/8265811 – BrunoElo Jan 27 '23 at 09:38
1689

Assuming your local master was not ahead of origin/master, you should be able to do

git reset --hard origin/<branch-name>

So assuming you did this on master, then your local master branch should look identical to origin/master.

mfaani
  • 33,269
  • 19
  • 164
  • 293
randomguy3
  • 17,067
  • 1
  • 14
  • 2
  • 82
    @Carter it actually is not the best answer. It is possible that origin/master may be ahead of your local master just previous to the merge by some commits, in that case this might not give the desired results – Dhruva Sagar Jun 22 '11 at 14:55
  • 16
    @dhruva-sagar Yes, but as long as git doesn't say you're behind, and you don't fetch, you should be fine. – Kelvin Dec 15 '11 at 17:10
  • This is great, but if you did a remote auto-merge (e.g. merge pull request on github), then you'll need to reset to a commit (accepted answer). – Alex Coplan Jul 15 '12 at 10:47
  • 3
    Thanks! This is perfect if (and only if) you have a remote repository. – tomc Jan 31 '13 at 10:59
  • How could I do it if I don't have the remote reference?, do `git reflog` to find where I was previous merge and then `git reset --hard HEAD@{some_number}` work? – sites Feb 16 '13 at 07:19
  • 2
    No it's not the perfect one for this question, see the "assume" clause. MBO's answer actually covers this case, and the case where the merge is not the only local commit. – inger Mar 21 '13 at 14:29
  • 1
    Yes it is the best answer if you read the last sentence of his question: `I don't want my branch to be ahead by any number of commits. How do I get back to that point?`, it seems like he wants to get back to what origin/master points to. – Jason Goemaat May 24 '13 at 20:55
  • 2
    Once again, maybe this **warning** should go into the answer itself: [***Always avoid rewriting git history!***](http://stackoverflow.com/questions/1491001/what-are-the-practical-consequences-of-rewriting-git-history) – cregox Sep 17 '13 at 20:18
  • My answer does the same thing, but is much safer. :) You don't need all the "assuming" stuff. – odinho - Velmont Mar 06 '14 at 09:11
  • This is a great resource straight from Github: [How to undo \(almost\) anything with Git](https://github.com/blog/2019-how-to-undo-almost-anything-with-git) – jasonleonhard Feb 03 '17 at 21:16
  • 1
    git reset --hard origin/ – Enrico Giurin May 29 '17 at 08:34
  • Instead always resetting the origin/master you could do `git reset --hard @{u}` – Gangadhar Jannu May 21 '19 at 13:22
1243

See chapter 4 in the Git book and the original post by Linus Torvalds.

To undo a merge that was already pushed:

git revert -m 1 commit_hash

Be sure to revert the revert if you're committing the branch again, like Linus said.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Yuri Geinish
  • 16,744
  • 6
  • 38
  • 40
  • 10
    @perfectionist agreed :) Kind of wish there was a way to migrate this answer to another question-- (maybe there is?) – mikermcneil Apr 16 '13 at 23:04
  • for more information about revert: [link](https://www.atlassian.com/git/tutorial/undoing-changes#!revert) – assaqqaf Mar 04 '14 at 02:22
  • 3
    To be confident that this revert has worked, you can do **git diff hash1 hash2** where hash1 is the committed revert, and hash2 is the old commit whose state you were trying to get back to. No output == success! I was able to roll back multiple commits by doing this multiple times, starting by reverting the most recent merge and working backwards. **git diff** showed me that I ended up in the state I wanted. – Robert Sinton May 06 '14 at 09:41
  • 7
    Notice that **this does *not* actually solve the original poster's question**. The original poster ***already*** used `git revert -m 1 `. The problem is that doing that doesn't erase the accidental merge that he did (and hasn't pushed yet). The other answers involving hard resets are better for the original poster's problem. –  Jul 05 '14 at 18:12
  • This is a great resource straight from Github: [How to undo \(almost\) anything with Git](https://github.com/blog/2019-how-to-undo-almost-anything-with-git) – jasonleonhard Feb 03 '17 at 21:16
  • This was right answer! – Jin Lim Nov 04 '21 at 11:22
1146

It is strange that the simplest command was missing. Most answers work, but undoing the merge you just did, this is the easy and safe way:

git reset --merge ORIG_HEAD

The ref ORIG_HEAD will point to the original commit from before the merge.

(The --merge option has nothing to do with the merge. It's just like git reset --hard ORIG_HEAD, but safer since it doesn't touch uncommitted changes.)

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
odinho - Velmont
  • 20,922
  • 6
  • 41
  • 33
  • 20
    If you've dirtied your working tree since, `git reset --merge ORIG_HEAD` preserves those changes. – yingted Apr 11 '13 at 11:59
  • 4
    This is the *only* correct answer (I'm not saying this is the best answer - note the difference). Let's say, on master, I did 3 commits at t1, t3, and t5. Let's say, on branch1, I did 3 comments at t2, t4 and t6 (assume t1, t2, t3, t4, t5 and t6 are in chronological order). Any command similar to `git reset --hard HEAD~5` will only reset HEAD (may remove commits in both master and branch1). Only the `--merge` option removes the `merge`. – Manu Manjunath Feb 17 '16 at 07:51
  • 4
    @Manu The `--merge` option doesn't actually remove the merge, you can use `--hard` it will also work well. It's the reference ORIG_HEAD that's the clue here, it is set before you do a merge to where you are standing at that point. :) – odinho - Velmont Feb 25 '16 at 10:26
  • @yingted what do u mean by "If you've dirtied your working tree since, git reset --merge ORIG_HEAD preserves those changes." Did u mean changing the files after merging ? Anyway i did the merge and then did some of resolving conflicts. But then i wanted to reset the merge and did as instructed in this answer. Everything was ok and it has not preserved my changes done after the merge. My local repo is just similar to the position before I did the merge. – Samitha Chathuranga Jun 09 '16 at 07:23
  • 1
    The `git reset --hard ORIG_HEAD` command worked perfectly for me – it may have been helped by the fact that I didn't make any other changes to the repository after the local `git merge` I was trying to undo. The command simply reset the state of the repository back to how it was before the merge. Thanks for the great tip! – bluebinary Jan 27 '17 at 01:00
478

With newer Git versions, if you have not committed the merge yet and you have a merge conflict, you can simply do:

git merge --abort

From man git merge:

[This] can only be run after the merge has resulted in conflicts. git merge --abort will abort the merge process and try to reconstruct the pre-merge state.

Stefan van den Akker
  • 6,661
  • 7
  • 48
  • 63
Travis Reeder
  • 38,611
  • 12
  • 87
  • 87
  • 18
    His merge is committed but not pushed (see title), he has already merged, your command works only when he is still in the middle of a merge – JBoy Mar 27 '19 at 09:42
182

You should reset to the previous commit. This should work:

git reset --hard HEAD^

Or even HEAD^^ to revert that revert commit. You can always give a full SHA reference if you're not sure how many steps back you should take.

In case when you have problems and your master branch didn't have any local changes, you can reset to origin/master.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
MBO
  • 30,379
  • 5
  • 50
  • 52
  • 5
    The best answer IMHO, incorporates the OP's own one (assuming only 1 step to revert, which seemed to be the case in the Q), as well as randomguy3's shortcut one(which works when "your master branch didn't had any local changes") – inger Mar 21 '13 at 14:31
  • 7
    You commenters, @Inger and @Konstantin, why? You came here after my answer was created, and it is more correct. Just going up the HEAD one step is often wrong, and you'd have to actually count how far up you need to go. Git already sets `ORIG_HEAD` for you, why not use it? – odinho - Velmont Aug 03 '14 at 09:55
  • will it reset local changes as well ? #PleaseUpdate. – CoDe Apr 11 '16 at 11:07
  • This worked perfectly for me, resetting head like that makes much more sense than half the answers here. – Varda Elentári Sep 22 '16 at 18:00
  • HEAD^ equals commit prior to HEAD? and ^^ is two commits prior? Guessing this won't work with fast forward merges? – Marcus Leon Sep 28 '16 at 16:17
103

Lately, I've been using git reflog to help with this. This mostly only works if the merge JUST happened, and it was on your machine.

git reflog might return something like:

fbb0c0f HEAD@{0}: commit (merge): Merge branch 'master' into my-branch
43b6032 HEAD@{1}: checkout: moving from master to my-branch
e3753a7 HEAD@{2}: rebase finished: returning to refs/heads/master
e3753a7 HEAD@{3}: pull --rebase: checkout e3753a71d92b032034dcb299d2df2edc09b5830e
b41ea52 HEAD@{4}: reset: moving to HEAD^
8400a0f HEAD@{5}: rebase: aborting

The first line indicates that a merge occurred. The 2nd line is the time before my merge. I simply git reset --hard 43b6032 to force this branch to track from before the merge, and carry-on.

Parris
  • 17,833
  • 17
  • 90
  • 133
  • Great answer, thank you! Needed to undo a merge but the other answers just messed it up more, using `reflog` to get the SHA and pass that into `git reset` worked. – user692942 Jan 21 '19 at 15:10
82

If you are in a middle of merging you can always abort it

git merge --abort
turivishal
  • 34,368
  • 7
  • 36
  • 59
llioor
  • 5,804
  • 4
  • 36
  • 44
  • 10
    thanks bro and i was about to do that scary stuff correct answer. lucky i scrolled down. i just want to delete merge head – Nyuu Apr 13 '19 at 13:22
59

With modern Git, you can:

git merge --abort

Older syntax:

git reset --merge

Old-school:

git reset --hard

But actually, it is worth noticing that git merge --abort is only equivalent to git reset --merge given that MERGE_HEAD is present. This can be read in the Git help for merge command.

git merge --abort is equivalent to git reset --merge when MERGE_HEAD is present.

After a failed merge, when there is no MERGE_HEAD, the failed merge can be undone with git reset --merge, but not necessarily with git merge --abort, so they are not only old and new syntax for the same thing.

Personally I find git reset --merge much more powerful and useful in everyday work, so that's the one I always use.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Martin G
  • 17,357
  • 9
  • 82
  • 98
  • 1
    Worked great for me. Every other post says this is so complicated, but this did exactly what is expected. I suppose it only worked because there were conflicts, which doesn't exactly answer the original question. – Jeremy Jul 07 '15 at 23:56
  • This answer doesn't focus on the OP's situation, and leaves out important context. – Ben Wheeler Oct 13 '15 at 22:26
  • 1
    Thanks! `git reset --merge` helped after a failed `git apply --3way`, when the other answers didn't. This seems to be because there is no MERGE_HEAD. – nckturner Aug 26 '21 at 00:42
58

If branches are merged and not pushed, then git reset command given below will work to undo the merge:

git reset --merge ORIG_HEAD

Example:

git reset --merge origin/master
Kostas Minaidis
  • 4,681
  • 3
  • 17
  • 25
bansi923
  • 839
  • 8
  • 8
43

Okay, the answers other people here gave me were close, but it didn't work. Here's what I did.

Doing this...

git reset --hard HEAD^
git status

...gave me the following status.

# On branch master
# Your branch and 'origin/master' have diverged,
# and have 3 and 3 different commit(s) each, respectively.

I then had to type in the same git reset command several more times. Each time I did that, the message changed by one as you can see below.

> git reset --hard HEAD^
HEAD is now at [...truncated...]
> git status
# On branch master
# Your branch and 'origin/master' have diverged,
# and have 3 and 3 different commit(s) each, respectively.
> git reset --hard HEAD^
HEAD is now at [...truncated...]
> git status
# On branch master
# Your branch and 'origin/master' have diverged,
# and have 2 and 3 different commit(s) each, respectively.
> git reset --hard HEAD^
HEAD is now at [...truncated...]
> git status
# On branch master
# Your branch and 'origin/master' have diverged,
# and have 1 and 3 different commit(s) each, respectively.
> git reset --hard HEAD^
HEAD is now at [...truncated...]
> git status
# On branch master
# Your branch is behind 'origin/master' by 3 commits, and can be fast-forwarded.

At this point, I saw the status message changed, so I tried doing a git pull, and that seemed to work:

> git pull
Updating 2df6af4..12bbd2f
Fast forward
 app/views/truncated |    9 ++++++---
 app/views/truncated |   13 +++++++++++++
 app/views/truncated |    2 +-
 3 files changed, 20 insertions(+), 4 deletions(-)
> git status
# On branch master

So long story short, my commands came down to this:

git reset --hard HEAD^
git reset --hard HEAD^
git reset --hard HEAD^
git reset --hard HEAD^
git pull
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Matt Huggins
  • 81,398
  • 36
  • 149
  • 218
40

You have to change your HEAD, Not yours of course but git HEAD....

So before answering let's add some background, explaining what is this HEAD.

First of all what is HEAD?

HEAD is simply a reference to the current commit (latest) on the current branch.
There can only be a single HEAD at any given time. (excluding git worktree)

The content of HEAD is stored inside .git/HEAD and it contains the 40 bytes SHA-1 of the current commit.


detached HEAD

If you are not on the latest commit - meaning that HEAD is pointing to a prior commit in history its called detached HEAD.

enter image description here

On the command line, it will look like this- SHA-1 instead of the branch name since the HEAD is not pointing to the tip of the current branch

enter image description here

enter image description here

A few options on how to recover from a detached HEAD:


git checkout

git checkout <commit_id>
git checkout -b <new branch> <commit_id>
git checkout HEAD~X // x is the number of commits t go back

This will checkout new branch pointing to the desired commit.
This command will checkout to a given commit.
At this point, you can create a branch and start to work from this point on.

# Checkout a given commit. 
# Doing so will result in a `detached HEAD` which mean that the `HEAD`
# is not pointing to the latest so you will need to checkout branch
# in order to be able to update the code.
git checkout <commit-id>

# create a new branch forked to the given commit
git checkout -b <branch name>

git reflog

You can always use the reflog as well.
git reflog will display any change which updated the HEAD and checking out the desired reflog entry will set the HEAD back to this commit.

Every time the HEAD is modified there will be a new entry in the reflog

git reflog
git checkout HEAD@{...}

This will get you back to your desired commit

enter image description here


git reset --hard <commit_id>

"Move" your HEAD back to the desired commit.

# This will destroy any local modifications.
# Don't do it if you have uncommitted work you want to keep.
git reset --hard 0d1d7fc32

# Alternatively, if there's work to keep:
git stash
git reset --hard 0d1d7fc32
git stash pop
# This saves the modifications, then reapplies that patch after resetting.
# You could get merge conflicts if you've modified things which were
# changed since the commit you reset to.
  • Note: (Since Git 2.7)
    you can also use the git rebase --no-autostash as well.

git revert <sha-1>

"Undo" the given commit or commit range.
The reset command will "undo" any changes made in the given commit.
A new commit with the undo patch will be committed while the original commit will remain in the history as well.

# add new commit with the undo of the original one.
# the <sha-1> can be any commit(s) or commit range
git revert <sha-1>

This schema illustrates which command does what.
As you can see there reset && checkout modify the HEAD.

enter image description here

CodeWizard
  • 128,036
  • 21
  • 144
  • 167
29

It can be done multiple ways.

1) Abort Merge

If you are in-between a bad merge (mistakenly done with wrong branch), and wanted to avoid the merge to go back to the branch latest as below:

git merge --abort

2) Reset HEAD to remote branch

If you are working from remote develop branch, you can reset HEAD to the last commit on remote branch as below:

git reset --hard origin/develop

3) Delete current branch, and checkout again from the remote repository

Considering, you are working on develop branch in local repo, that syncs with remote/develop branch, you can do as below:

git checkout master 
##to delete one branch, you need to be on another branch, otherwise you will fall with the branch :) 

git branch -D develop
git checkout -b develop origin/develop
Amit Kaneria
  • 5,466
  • 2
  • 35
  • 38
24

You could use git reflog to find the previous checkout. Sometimes that's a good state you want to return back to.

Concretely,

$ git reflog
$ git reset --hard HEAD@{0}
stephjang
  • 939
  • 1
  • 8
  • 13
21

I was able to resolve this problem with a single command that doesn't involve looking up a commit id.

git reset --hard remotes/origin/HEAD

The accepted answer didn't work for me but this command achieved the results I was looking for.

Ralph Ritoch
  • 3,260
  • 27
  • 37
  • Exactly! It resets your changes to the HEAD of the branch! Not doing one by one – Carlos Zinato Sep 21 '18 at 13:05
  • didn't work for me. actually ended up sending local branch back a month or two. Thankfully this is all local so i can always destroy the branch and fetch it again. Just wanted to point that out in case others tried this. – Matt Pengelly Jun 03 '19 at 20:16
  • @MattPengelly this method is largely undocumented and usually works if your branch is in sync with the remote branch before you did the merge. Has it been months since your branch was in sync with the remote branch? – Ralph Ritoch Jun 06 '19 at 09:51
  • @MattPengelly it also depends on what branch the HEAD is pointed to. I'm using gitflow on one of my projects, and even though I'm on the develop branch, the remotes/origin/HEAD is pointed to origin/master so if I needed to undo a merge I would probably need to reset to remotes/origin/develop – Ralph Ritoch Jun 06 '19 at 09:55
20

if no conflict and merge completed then:

git reset --hard HEAD~1

if while doing a merge got conflict then abort will take you out of the recent merge changes:

git merge --abort

or if you want to revert back to a specific commit id.

git reset --hard <commit-id>
Penny Liu
  • 15,447
  • 5
  • 79
  • 98
vidur punj
  • 5,019
  • 4
  • 46
  • 65
16

If you didn't commit it yet, you can only use

$ git checkout -f

It will undo the merge (and everything that you did).

Idealmind
  • 1,278
  • 15
  • 8
16

Got to this question also looking to revert to match origin (ie, NO commits ahead of origin). Researching further, found there's a reset command for exactly that:

git reset --hard @{u}

Note: @{u} is shorthand for origin/master. (And, of course, you need that remote repository for this to work.)

leanne
  • 7,940
  • 48
  • 77
15

Answering the question "Undo a Git merge that hasn't been pushed yet"

You can use git reset --hard HEAD~1

Consider the following situation where there are 2 branches master and feature-1:


$ git log --graph --oneline --all

Do Git merge

$ git merge feature-1

$ git log --graph --oneline --all

Undo Git merge

$ git reset --hard HEAD~1

$ git log --graph --oneline --all

bl3ssedc0de
  • 780
  • 1
  • 11
  • 15
12

You can use only two commands to revert a merge or restart by a specific commit:

  1. git reset --hard commitHash (you should use the commit that you want to restart, eg. 44a587491e32eafa1638aca7738)
  2. git push origin HEAD --force (Sending the new local master branch to origin/master)

Good luck and go ahead!

Matheus Abreu
  • 3,357
  • 1
  • 18
  • 21
12

The simplest answer is the one given by odinho - Velmont

First do git reset --merge ORIG_HEAD

For those looking to reset after changes are pushed, do this (Because this is the first post seen for any git reset merge questions)

git push origin HEAD --force

This will reset in a way that you won't get the merged changes back again after pull.

Harsha
  • 717
  • 1
  • 11
  • 23
11

Just for an extra option to look at, I've been mostly following the branching model described here: http://nvie.com/posts/a-successful-git-branching-model/ and as such have been merging with --no-ff (no fast forward) usually.

I just read this page as I'd accidentally merged a testing branch instead of my release branch with master for deploying (website, master is what is live). The testing branch has two other branches merged to it and totals about six commits.

So to revert the whole commit I just needed one git reset --hard HEAD^ and it reverted the whole merge. Since the merges weren't fast forwarded the merge was a block and one step back is "branch not merged".

Damien Byrne
  • 111
  • 1
  • 2
9

If your merge and the corresponding commits were not pushed yet, you can always switch to another branch, delete the original one and re-create it.

For example, I accidentally merged a develop branch into master and wanted to undo that. Using the following steps:

git checkout develop
git branch -D master
git branch -t master origin/master

Voila! Master is at the same stage as origin, and your mis-merged state is erased.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Stephan
  • 136
  • 1
  • 1
8

Use this command to abort a merge:

git merge --abort
Penny Liu
  • 15,447
  • 5
  • 79
  • 98
De Bonheur
  • 742
  • 10
  • 13
6

Strategy: Create a new branch from where everything was good.

Rationale: Reverting a merge is hard. There are too many solutions, depending on many factors such as whether you've committed or pushed your merge or if there were new commits since your merge. Also you still need to have a relatively deep understanding of git to adapt these solutions to your case. If you blindly follow some instructions, you can end up with an "empty merge" where nothing will be merged, and further merge attempts will make Git tell you "Already up to date".

Solution:

Let's say you want to merge dev into feature-1.

  1. Find the revision that you want to receive the merge:

    git log --oneline feature-1
    a1b2c3d4 Merge branch 'dev' into 'feature-1' <-- the merge you want to undo
    e5f6g7h8 Fix NPE in the Zero Point Module <-- the one before the merge, you probably want this one
    
  2. Check it out (go back in time):

    git checkout e5f6g7h8
    
  3. Create a new branch from there and check it out:

    git checkout -b feature-1
    

Now you can restart your merge:

  1. Merge: git merge dev

  2. Fix your merge conflicts.

  3. Commit: git commit

  4. When you're satisfied with the results, delete the old branch: git branch --delete feature-1

pyb
  • 4,813
  • 2
  • 27
  • 45
5

If you want a command-line solution, I suggest to just go with MBO's answer.

If you're a newbie, you might like the graphical approach:

  1. Kick off gitk (from the command line, or right click in file browser if you have that)
  2. You can easily spot the merge commit there - the first node from the top with two parents
  3. Follow the link to the first/left parent (the one on your current branch before the merge, usually red for me)
  4. On the selected commit, right-click "Reset branch to here", pick the hard reset there
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
inger
  • 19,574
  • 9
  • 49
  • 54
5

Just create new branch, then cherry-pick desired commits to it.

Its saver and simpler then resets described in many answers above

gdbdable
  • 4,445
  • 3
  • 30
  • 46
  • 2
    I agree with this suggestion, especially if you are not entirely comfortable with the git commands listed. This may be slower with more "toil", but if it doesn't come up much and you are concerned with losing your work, it's worth the effort. – Greg Feb 05 '20 at 18:06
3

I think you can do git rebase -i [hash] [branch_name] where [hash] is the identifying hash for however far back you want to rewind plus one (or however many commits back you want to go) and then delete the lines for the commits in the editor that you don't want any more. Save the file. Exit. Pray. And it should be rewound. You might have to do a git reset --hard, but it should be good at this point. You can also use this to pull specific commits out of a stack, if you don't want to keep them in your history, but that can leave your repository in a state that you probably don't want.

tychoish
  • 661
  • 4
  • 7
  • Just one detail, interactive rebase lets drop commits by deleting lines, but if you remove everything, rebase will be simply aborted. Easiest trick here is removing all lines but one, and label this last one as "drop" so everything is discarded. – jesjimher May 26 '21 at 10:35
2
  1. First, make sure that you've committed everything.

  2. Then reset your repository to the previous working state:

    $ git reset f836e4c1fa51524658b9f026eb5efa24afaf3a36
    

    or using --hard (this will remove all local, not committed changes!):

    $ git reset f836e4c1fa51524658b9f026eb5efa24afaf3a36 --hard
    

    Use the hash which was there before your wrongly merged commit.

  3. Check which commits you'd like to re-commit on the top of the previous correct version by:

    $ git log 4c3e23f529b581c3cbe95350e84e66e3cb05704f
    
    commit 4c3e23f529b581c3cbe95350e84e66e3cb05704f
    
    ...
    
    commit 16b373a96b0a353f7454b141f7aa6f548c979d0a
    
    ...
    
  4. Apply your right commits on the top of the right version of your repository by:

    • By using cherry-pick (the changes introduced by some existing commits)

          git cherry-pick ec59ab844cf504e462f011c8cc7e5667ebb2e9c7
      
    • Or by cherry-picking the range of commits by:

      • First checking the right changes before merging them:

        git diff 5216b24822ea1c48069f648449997879bb49c070..4c3e23f529b581c3cbe95350e84e66e3cb05704f
        
      • First checking the right changes before merging them:

        git cherry-pick 5216b24822ea1c48069f648449997879bb49c070..4c3e23f529b581c3cbe95350e84e66e3cb05704f
        

        where this is the range of the correct commits which you've committed (excluding wrongly committed merge).

kenorb
  • 155,785
  • 88
  • 678
  • 743
1

The simplest of the simplest chance, much simpler than anything said here:

Remove your local branch (local, not remote) and pull it again. This way you'll undo the changes on your master branch and anyone will be affected by the change you don't want to push. Start it over.

Luis
  • 2,833
  • 3
  • 27
  • 41
1

If you committed the merge:

git reset HEAD~1
# Make sure what you are reverting is in fact the merge files
git add .
git reset --hard
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Dorian
  • 22,759
  • 8
  • 120
  • 116
1
  1. git stash

  2. git branch -d the_local_branch

  3. git checkout -t <name of remote>

  4. git stash apply

This worked for me..!!

Siva Kumar
  • 560
  • 6
  • 11
0

If you notice that you need to revert immediately after the merge and you haven't done anything else after the merge attempt, you can just issue this command: git reset --hard HEAD@{1}.

Essentially, your merge sha will be pointing to HEAD@{0} if nothing else was committed after the merge and so HEAD@{1} will be the previous point before the merge.

Dut A.
  • 1,029
  • 11
  • 22
0

In this case, you will want to reset your branch with git reset --hard <branch_name>. If you want to save your changes before reseting them be sure to create a new branch and git checkout <branch_name>.

You can reset the state to a specific commit with git reset --hard <commit_id> as well.

If the changes have been pushed you can use git revert <branch_name> instead. Be sure to check out how to use git revert and git checkout in other scenarios as well.

Nesha Zoric
  • 6,218
  • 42
  • 34
-13

You can use the git-reset command.

git-reset - Reset current HEAD to the

specified state. git reset [--mixed |

--soft | --hard | --merge] [-q] [] git reset [-q] []

[--] … git reset --patch

[] [--] […]

GIT-Reset

Community
  • 1
  • 1
NebuSoft
  • 3,962
  • 2
  • 22
  • 24
  • 1
    I tried `git reset`, `git reset --merge`, and `git reset --hard`, but I still end up with the same message about being 5 commits ahead of origin/master. – Matt Huggins Mar 05 '10 at 19:30