ChatGPT解决这个技术问题 Extra ChatGPT

Undo a particular commit in Git that's been pushed to remote repos

What is the simplest way to undo a particular commit that is:

not in the head or HEAD

Has been pushed to the remote.

Because if it is not the latest commit,

git reset HEAD

doesn't work. And because it has been pushed to a remote,

git rebase -i

and

git rebase --onto

will cause some problem in the remotes.

More so, I don't want to modify the history really. If there was bad code, it was there in the history and can be seen. I just want it out in the working copy, and I don't mind a reverse merge commit.

In other words, what is the Git equivalent of the following svn commands:

svn merge -r 303:295 http://svn.example.com/repos/calc/trunk

which removes all changes from 295 to 302 by reverse merging all changes in those revisions, as a new commit.

svn merge -c -302 ^/trunk

which undoes the 302 commit, of course by adding another commit that reverse merges the changes from that respective commit.

I thought it should be a fairly simple operation in Git and a fairly common use case. What else is the point of atomic commits?

We have staging stashing and all to ensure the commits are perfectly atomic, shouldn't you be able to undo one or more of those atomic commits easily?

Does this answer your question? How can I undo pushed commits using git?

A
Andrew Aylett

Identify the hash of the commit, using git log, then use git revert <commit> to create a new commit that removes these changes. In a way, git revert is the converse of git cherry-pick -- the latter applies the patch to a branch that's missing it, the former removes it from a branch that has it.


And use the -n switch if you want the code back, but not automatically committed in again
What does the "m" option do? I tried git revert 8213f7d but got this instead:error: Commit 8213f7dad1ed546b434a0d8a64cb783b530a5a30 is a merge but no -m option was given. fatal: revert failed
To revert a merge: git revert -m 1
A warning to anyone who wants to revert a merge: git revert will undo all the data changes (ie, the file changes will get reverted), but the the merge still remains in the history. Because of this if you try to merge that same branch in again later it won't include any commits from the merging branch prior to the reverted merge. This is most likely not what you want. In order to fully merge the branch in again you will need to first revert the commit where you reverted the original merge. Learn more here: kernel.mirrors.pair.com/pub/software/scm/git/docs/howto/…
The link in the comment by @etreworgy is 404. I suspect this is an up to date version of the link: kernel.org/pub/software/scm/git/docs/howto/…
M
Mulan

I don't like the auto-commit that git revert does, so this might be helpful for some.

If you just want the modified files not the auto-commit, you can use --no-commit

% git revert --no-commit <commit hash>

which is the same as the -n

% git revert -n <commit hash>

You could also do git reset HEAD~1 --soft if you already reverted without -n
But git reset HEAD~n won't solve undoing of any commit not continuously reachable from the head. The query is to revert any particular commit.
I used this solution but hit a conflict in the middle of the revert. After resolving the conflict, I did git revert --continue as it instructed me. It worked, but sadly committed the results. Perhaps I needed to do git revert --no-commit --continue.
@sangeethkumarp the comment by Daniel is an additional step you can take after the git revert, if you forgot the -n; because at that point the last commit is the reversion, so the soft reset will undo that commit but not the associated code changes of the revert
@Daniel provided solutions by comment work for me Thanks lot ''git reset HEAD~1 --soft''
m
moatPylon

Because it has already been pushed, you shouldn't directly manipulate history. git revert will revert specific changes from a commit using a new commit, so as to not manipulate commit history.


M
Meysam Sadeghi

If the commit you want to revert is a merged commit (has been merged already), then you should either -m 1 or -m 2 option as shown below. This will let git know which parent commit of the merged commit to use. More details can be found HERE.

git revert -m 1

git revert -m 2