How to permanently remove few commits from remote branch

Git

Git Problem Overview


I know that's rewriting of history which is bad yada yada.

But how to permanently remove few commits from remote branch?

Git Solutions


Solution 1 - Git

You git reset --hard your local branch to remove changes from working tree and index, and you git push --force (or git push --force-with-lease) your revised local branch to the remote.
(other solution here, involving deleting the remote branch, and re-pushing it)

This SO answer illustrates the danger of such a command, especially if people depends on the remote history for their own local repos.
You need to be prepared to point out people to the RECOVERING FROM UPSTREAM REBASE section of the git rebase man page


With Git 2.23 (August 2019, nine years later), you would use the new command git switch.
That is: git switch -C mybranch origin/mybranch~n
(replace n by the number of commits to remove)

That will restore the index and working tree, like a git reset --hard would.
The documentation adds:

> -C > --force-create > > Similar to --create except that if <new-branch> already exists, it will be reset to <start-point>.
This is a convenient shortcut for: > > $ git branch -f > $ git switch

Solution 2 - Git

Just note to use the last_working_commit_id, when reverting a non-working commit

git reset --hard <last_working_commit_id>

So we must not reset to the commit_id that we don't want.

Then sure, we must push to remote branch:

git push --force

Solution 3 - Git

Important: Make sure you specify which branches on "git push -f" or you might inadvertently modify other branches![*]

There are three options shown in this tutorial. In case the link breaks I'll leave the main steps here.

  1. Revert the full commit
  2. Delete the last commit
  3. Delete commit from a list

1 Revert the full commit

git revert dd61ab23

2 Delete the last commit

git push <<remote>> +dd61ab23^:<<BRANCH_NAME_HERE>>

or, if the branch is available locally

git reset HEAD^ --hard
git push <<remote>> -f

where +dd61... is your commit hash and git interprets x^ as the parent of x, and + as a forced non-fastforwared push.

3 Delete the commit from a list

git rebase -i dd61ab23^

This will open and editor showing a list of all commits. Delete the one you want to get rid off. Finish the rebase and push force to repo.

git rebase --continue
git push <remote_repo> <remote_branch> -f

Solution 4 - Git

If you want to delete for example the last 3 commits, run the following command to remove the changes from the file system (working tree) and commit history (index) on your local branch:

git reset --hard HEAD~3

Then run the following command (on your local machine) to force the remote branch to rewrite its history:

git push --force

Congratulations! All DONE!

Some notes:

You can retrieve the desired commit id by running

git log

Then you can replace HEAD~N with <desired-commit-id> like this:

git reset --hard <desired-commit-id>

If you want to keep changes on file system and just modify index (commit history), use --soft flag like git reset --soft HEAD~3. Then you have chance to check your latest changes and keep or drop all or parts of them. In the latter case runnig git status shows the files changed since <desired-commit-id>. If you use --hard option, git status will tell you that your local branch is exactly the same as the remote one. If you don't use --hard nor --soft, the default mode is used that is --mixed. In this mode, git help reset says:

> 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.

Solution 5 - Git

TL:DR;

  1. git switch -C branch_name origin/branch_name~n
  2. git push --force

Done, remote branch will be reverted by n commits.


Explaination:

  1. Use git switch, resets the branch by n number of commits. The -C option will force create a new branch with same name.

    • replace branch_name with your branch name,
    • replace n (at the end of command), with number of commits you want to revert.

    Command #1: git switch -C branch_name origin/branch_name~n

    Example: git switch -C feature/dashboard origin/feature/dashboard~1 // This command reverts 1 commit in dashboard branch.

  2. Force push the local change

    Command #2: git push --force


Tip: To undo committed(unpushed) changes git reset HEAD~

Solution 6 - Git

Simplifying from pctroll's answer, similarly based on this blog post.

# look up the commit id in git log or on github, e.g. 42480f3, then do
git checkout master
git checkout your_branch
git revert 42480f3
# a text editor will open, close it with ctrl+x (editor dependent)
git push origin your_branch
# or replace origin with your remote

Solution 7 - Git

This might be too little too late but what helped me is the cool sounding 'nuclear' option. Basically using the command filter-branch you can remove files or change something over a large number of files throughout your entire git history.

It is best explained here.

Solution 8 - Git

Sometimes the easiest way to fix this issue is to make a new branch from the place where you know the code is good. Then you can leave the errant branch history alone in case you need to cherry-pick other commits from it later. This also ensures you did not lose any commit history.

From your local errant branch:

git log

copy the commit hash that you wanted the branch to be at and exit the git log

git checkout theHashYouJustCopied
git checkout -b your_new_awesome_branch

Now you have a new branch just the way you want it.

If you also needed to keep a specific commit from the errant branch that is not on your new branch, you can just cherry-pick that specific commit you need:

git checkout the_errant_branch
git log

Copy the commit hash of the one commit you need to pull into the good branch and exit the git log.

git checkout your_new_awesome_branch
git cherry-pick theHashYouJustCopied

Pat yourself on the back.

Solution 9 - Git

 git reset --soft commit_id
 git stash save "message"
 git reset --hard commit_id
 git stash apply stash stash@{0}
 git push --force

Solution 10 - Git

I like to do this using rebase. Below, n is the last n commits. So, if you want to delete the third one, replace n by 3.

git rebase -i HEAD~n

then, find the desired commit in the listing and change it from "pick" to "drop". Exit the rebase and use git push with the "-f" option as you just did a rebase.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionArnis LapsaView Question on Stackoverflow
Solution 1 - GitVonCView Answer on Stackoverflow
Solution 2 - Githd84335View Answer on Stackoverflow
Solution 3 - GitreefaktorView Answer on Stackoverflow
Solution 4 - GitAbdollahView Answer on Stackoverflow
Solution 5 - GitSaifView Answer on Stackoverflow
Solution 6 - Gitted.straussView Answer on Stackoverflow
Solution 7 - Gitjansmolders86View Answer on Stackoverflow
Solution 8 - GitDouglas.SesarView Answer on Stackoverflow
Solution 9 - GitpandoragoView Answer on Stackoverflow
Solution 10 - GitJohnView Answer on Stackoverflow