Matt Joiner
Matt Joiner

Reputation: 118500

Cancel git merge but keep local changes

I started a git merge, but made local changes that I want to keep. I no longer want to merge, and instead continue to work on the local changes. How do I do this?

Upvotes: 26

Views: 10991

Answers (8)

Jeremy Baron
Jeremy Baron

Reputation: 166

As per this answer to a similar question, since Git 2.23 (Q3 2019) you can use:

git merge --quit

This will:

  • Forget about the current merge in progress.
  • Leave the index and the working tree as-is.

Upvotes: 15

kelvin
kelvin

Reputation: 1614

Abort Commit

If the text editor is already opened (to write the commit message), closing it normally/successfully will commit the merge (if there are no unmerged paths). To avoid that, the text editor should exit with an error (if desired, make sure that the content is saved to a backup file first). If using vim, that can be done with :cq (to discard everything and exit with error 1). For other text editors, a generic way would be to kill the proccess, either in a task manager or more directly with:

kill -9 EDITOR_PID

Background

After running git merge, the hunks that are merged successfully (i.e.: without conflicts) are added to the index. If there are conflicts, the affected hunks are left with conflict markers in the working tree and a .git/MERGE_HEAD file is created to track that you're in the middle of a merge.

So the goals are:

  • Get out of the merge state
  • Keep the working tree as is
  • Remove all changes from the index to match the working tree (optional)

The first command that comes to mind that does all of the above is git reset.

Reset

To reset the index while keeping the working tree intact (including the conflict markers, if any), it should suffice to simply run the following:

git reset --mixed

Or, alternatively:

git reset

This should also remove the file .git/MERGE_HEAD, which should make git stop thinking that you're in the middle of a merge.

From git-reset(1):

git reset [<mode>] [<commit>]
    This form resets the current branch head to <commit> and possibly updates
    the index (resetting it to the tree of <commit>) and the working tree
    depending on <mode>. If <mode> is omitted, defaults to --mixed. The
    <mode> must be one of the following:

    --soft
        Does not touch the index file or the working tree at all (but resets
        the head to <commit>, just like all modes do). This leaves all your
        changed files "Changes to be committed", as git status would put it.

    --mixed
        Resets the index but not the working tree (i.e., the changed files
        are preserved but not marked for commit) and reports what has not
        been updated. This is the default action.

As mentioned above, the default git reset behavior (i.e.: --mixed) is to reset what is in the index (i.e.: what is about to be committed), but it does not touch the working tree.

Other Methods

For completeness, note that git merge --abort should not be done if you want to keep local changes intact, as it will try to "reconstruct the pre-merge state". From git-merge(1):

The second syntax ("git merge --abort") 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. However, if there were uncommitted changes when the merge started (and especially if those changes were further modified after the merge was started), git merge --abort will in some cases be unable to reconstruct the original (pre-merge) changes. Therefore:

Warning: Running git merge with non-trivial uncommitted changes is discouraged: while possible, it may leave you in a state that is hard to back out of in the case of a conflict.

Upvotes: 1

Sarah
Sarah

Reputation: 72

I suppose you want to merge a branch to current with some conflicts. If you are, follow the steps below.

  1. Before your merging, use git stash to save your local changes.
  2. Use git merge branch to merge the branch, then git commit.
  3. Then, use git stash pop to restore your changes.
  4. Step 3 may show some conflicts if there have, solve them, and do git commit.

If you just want to know how to exit the merging process, try git merge --abort to terminate it. Hope this will help you~~

Upvotes: 0

Ruhul Amin
Ruhul Amin

Reputation: 1

If you have not committed the merge yet and if you have a merge conflict you can use:

git merge --abort

Or you can reset to the previous commit:

git reset --hard HEAD^

Also, You can get help from git reflog command to find the previous checkout. It's a good thing to return back to the previous state.

git reset --hard HEAD@{0}

Upvotes: 0

FabianSilva
FabianSilva

Reputation: 405

It happened today to me, I need to do a merge in a new branch created from develop with certain changes from another branch...

I tried the solution from Michael Sorens but it need an additional step... git add . if you have some conflict

git checkout -b mynewbranchfromdevelop
git merge AnotherBranchToMergeIntoMynewbranchfromdevelop

it have conflicts, I tried to make a git stash but "needs merge" messages appears, simply what I have to do is to use

git add .

to take those conflicts as resolved and staged (but still need git commit to conclude merge), then

git stash

will save those changes in a stash, and if you check with "git status" there is nothing to commit and working tree clean

git stash apply

and you will have those changes in local directory of current branch without commit

Upvotes: 1

Botak
Botak

Reputation: 19

Found a tested solution for:

  1. keep all current changes in the working directory, whether you manually edited those files OR the merge that you are in the middle of brought them in
rm .git/MERGE*
rm .git/ORIG_HEAD

Might be a bit dangerous as you're basically directly interfering with git's internal working, so maybe back up your folder first :)

Upvotes: 1

Michael Sorens
Michael Sorens

Reputation: 36708

Language is notoriously ambiguous. :-) When you say "keep local changes" you could mean either:

  1. keep all current changes in the working directory, whether you manually edited those files OR the merge that you are in the middle of brought them in; or
  2. discard any changes brought in by the merge and retain any changes that you have introduced.

This simple solution addresses point (1):

$ git stash save
$ git stash pop

Here's a transcript showing the affect:

$ git status
On branch stuff-217/apply-new-config-details
All conflicts fixed but you are still merging.  <<<<<< notice this line!

Changes to be committed:
        modified:   package.json
        modified:   src/wallabyTest.ts
        modified:   wallaby.js

$ git stash save
Saved working directory and index state WIP on stuff-217/apply-new-config-details...

$ git status
On branch stuff-217/apply-new-config-details
nothing to commit, working tree clean

$ git stash pop
On branch stuff-217/apply-new-config-details
                                             <<<<<< no longer in the merge!
Changes not staged for commit:
        modified:   package.json
        modified:   src/wallabyTest.ts
        modified:   wallaby.js

Upvotes: 18

ddsnowboard
ddsnowboard

Reputation: 922

First, copy the folder you're working in in case something bad happens. Git is usually pretty bulletproof, but if you start using git reset --hard, it's possible for bad things to happen.

Then, do a git commit --patch, picking only the changes that you want to keep and leaving everything that the merge did. Once you've committed those changes, do a git reset --hard, and the merge should be gone, but your changes should still be there.

Upvotes: 1

Related Questions