Undo a Git Merge
The short answer
In Git, the easiest and safest way to undo a merge is to create a new commit that reverts the changes introduced by a specific commit using the [.inline-code]git revert[.inline-code] command as follows:
Adding the option [.inline-code]-m 1[.inline-code] to the [.inline-code]git revert[.inline-code] command tells Git that you want to keep the parent side of the merge (the branch you merged into). If you want to keep the side of the branch merged, you change the [.inline-code]1[.inline-code] to a [.inline-code]2[.inline-code] instead.
For example:
[#easily-recall-syntax-with-ai] Easily retrieve this command using Warp’s AI Command Suggestions [#easily-recall-syntax-with-ai]
If you’re using Warp as your terminal, you can easily retrieve this command using the Warp AI Command Suggestions feature:
Entering [.inline-code]git revert merge[.inline-code] in the AI Command Suggestions will prompt a [.inline-code]git[.inline-code] command that can then be quickly inserted into your shell by doing [.inline-code]CMD+ENTER[.inline-code].
[#discard-all-changes] Undoing a merge by discarding all changes [#discard-all-changes]
To completely discard all changes in the working directory and the staging area that have not been committed so that the state of the repository matches a specific commit exactly, you can use the [.inline-code]git reset[.inline-code] command with the [.inline-code]--hard[.inline-code] flag as follows:
Note that this command will effectively rewrite the commit history by removing all the commits after the specified commit.
For example:
[#preserve-non-conflicting-changes] Undoing a merge and preserving changes [#preserve-non-conflicting-changes]
To reset the repository to a specific commit and keep the local changes in the working directory and the staging area that are not conflicting with the changes introduced by the reset, you can use the [.inline-code]git reset[.inline-code] command with the [.inline-code]--merge[.inline-code] flag as follows:
Note that this command will automatically abort if conflicting changes are detected.
For example:
[#undo-local-vs-remote-changes] Undoing local vs remote merges [#undo-local-vs-remote-changes]
It is important to note that unlike [.inline-code]git revert[.inline-code], [.inline-code]git reset[.inline-code] rewrites the history of the branch so you need to use this with caution, especially if the branch has already been pushed to a remote repository.
Undoing a local merge as opposed to one that has already been pushed to a remote repository differs in the implications for the history of the repository. To undo a local merge you can use any of the methods discussed above as long as you are okay with changing the history of your repository.
However, if the merge has already been pushed to a remote repository, you should be cautious about using [.inline-code]git reset[.inline-code] and [.inline-code]git push --force[.inline-code] as this can cause issues for collaborators who have already pulled the changes. In such cases it is generally recommended to use [.inline-code]git revert[.inline-code] to create a new commit that undoes the changes without altering the history.