Search code examples
gitgithubgit-mergegit-revert

error: mainline was specified but commit is not a merge; fatal: revert failed


I want to revert the reverted pull requests i.e. the 4 commits 6283c90, f665a5a, 09ed268, 05ed1bc.

But when I use the command git revert -m 1 6283c90, I am running into the following error:

error: mainline was specified but commit 6283c90bd35598635fe1d4f96d3a5a8c6ed91206 is not a merge.
fatal: revert failed

The git log graph looks something like below:

* 6283c90 (HEAD -> main, origin/main, origin/HEAD) Revert "Merge pull request #1 from kgarg8/checkpoint-patch"
* f665a5a Revert "Merge pull request #2 from kgarg8/entmax-patch"
* 09ed268 Revert "Merge pull request #3 from kgarg8/decoding"
* 05ed1bc Revert "Merge pull request #4 from kgarg8/decoding"
*   2a8519e Merge pull request #4 from kgarg8/decoding
|\  
| * e170320 (origin/decoding) Fix bugs in decoding
* |   63f0f4c Merge pull request #3 from kgarg8/decoding
|\ \  
| |/  
| * f5ce256 Add temperature, top_k, top_p sampling
* |   168685e Merge pull request #2 from kgarg8/entmax-patch
|\ \  
| |/  
| * 6a44c22 (origin/entmax-patch) Add entmax support
* |   7f61831 Merge pull request #1 from kgarg8/checkpoint-patch
|\ \  
| |/  
| * ea0a7db (origin/checkpoint-patch) Checkpoint load for CPU
|/  
* 4c2d50c Update Seq2Seq_agent.py
... continues

Any help will be appreciated.


Solution

  • One will have to understand the git revert vs git reset.

    revert is when you try to add another commit on top with the exact diff as inverse of the last commit(s). In your case as equivalent of a squashed (i.e. --squash) of all the previous 4 commits.

    It's problematic to do this, when your repo is not configured as merge strategy with: rebase + ff-only. Based on the history you showed, the actual issue is the merge strategy used by your project.

    Still, if you want to achieve a revert, you'd do (more) :

    $ git revert --no-commit <SHA-1 (previous)>
    $ git revert --no-commit <SHA-1 (previous - 1)>
    $ git revert --no-commit <SHA-1 (previous - 2)>
    $ git revert --no-commit <SHA-1 (previous - 3)>
    $ git commit -m "your message message"
    $ git push
    

    reset is to get the content to be at the SHA-1 (commit = pointer) as it was 4 commits ago. Most of the time people are looking for revert-ing, they actually refer to reset. Not sure in your case. The benefit is around governance. If you can't change history, if your user is not allowed to push --force (push with force), then you probably need to use revert as the governance model of your project, wants to ensure that people don't hide the mistakes, or remove (by mistake) something from history. Otherwise, reset is the default way to go back, especially when working on your local fork (a common example when reset is not allowed in teams, is for a DevOps team - for a configuration management repo).

    $ git reset --hard <SHA-1 (previous - 3)>
    $ git push --force
    

    Where <SHA-1 (previous - 3)> is probably 05ed1bc for you, so an actual commit SHA-1.

    UPDATE: (Note) When reset is being used, the previous (forward) commits are not deleted, but remain orphan. They remain in the history until a gc (garbage collection) is being called. They remain basically in the tree (like on a different branch - but without a branch. Think of it as the TREE data structure - Computer Science). You can retrieve that commit if one wants to analyze it.