简体   繁体   English

如何使用 git 撤消推送的提交?

[英]How can I undo pushed commits using git?

I have a project in a remote repository, synchronized with a local repository (development) and the server one (prod).我在远程存储库中有一个项目,与本地存储库(开发)和服务器(产品)同步。 I've been making some commited changes already pushed to remote and pulled from the server.我一直在进行一些已提交的更改,这些更改已经推送到远程并从服务器中拉出。 Now, I want to undo those changes.现在,我想撤消这些更改。 So I could just git checkout to the commit before the changes and commit the new changes, but I'm guessing that there will be problems to push them again to remote.所以我可以在更改之前将git checkout提交到提交并提交新的更改,但我猜测将它们再次推送到远程会有问题。 Any suggestion on how should I proceed?关于我应该如何进行的任何建议?

You can revert individual commits with:您可以通过以下方式恢复单个提交:

git revert <commit_hash>

This will create a new commit which reverts the changes of the commit you specified.这将创建一个新的提交,它会还原您指定的提交的更改。 Note that it only reverts that specific commit, and not commits that come after that.请注意,它只恢复该特定提交,而不是之后的提交。 If you want to revert a range of commits, you can do it like this:如果你想恢复一系列提交,你可以这样做:

git revert <oldest_commit_hash>..<latest_commit_hash>

It reverts all the commits after <oldest_commit_hash> up to and including <latest_commit_hash> .它将<oldest_commit_hash>之后的所有提交还原到并包括<latest_commit_hash> On some versions of git it also reverts the <oldest_commit_hash> , so double check if that commit gets reverted or not.在某些版本的 git 上,它还会还原<oldest_commit_hash> ,因此请仔细检查该提交是否被还原。 You can always drop the latest revert commit (which reverts the oldest commit) with g reset --hard HEAD~ .您始终可以使用g reset --hard HEAD~删除最新的还原提交(还原最旧的提交)。

To know the hash of the commit(s) you can use git log .要知道提交的哈希值,您可以使用git log

Look at the git-revert man page for more information about the git revert command.有关git revert命令的更多信息,请查看git-revert 手册页 Also, look at this answer for more information about reverting commits.另外,请查看此答案以获取有关恢复提交的更多信息。

A solution that keeps no traces of the "undo".一种不保留“撤消”痕迹的解决方案。

NOTE: don't do this if someone already pulled your change (I would use this only on my personal repo.)注意:如果有人已经提取了您的更改,请不要这样做(我只会在我的个人回购中使用它。)

run:跑:

git reset <previous label or sha1>

this will re-checkout all the updates locally (so git status will list all updated files)这将在本地重新签出所有更新(因此 git status 将列出所有更新的文件)

then you "do your work" and re-commit your changes (Note: this step is optional)然后你“做你的工作”并重新提交你的更改(注意:这一步是可选的)

git commit -am "blabla"

At this moment your local tree differs from the remote此时您的本地树与远程树不同

git push -f <remote-name> <branch-name>

will force the remote branch to take this push and remove the previous one (specifying remote-name and branch-name is not mandatory but is recommended to avoid updating all branches with update flag).将强制远程分支进行此推送并删除前一个(指定远程名称和分支名称不是强制性的,但建议避免使用更新标志更新所有分支)。

!! !! watch-out some tags may still be pointing removed commit !!注意一些标签可能仍然指向删除提交! how-to-delete-a-remote-tag 如何删除远程标签

What I do in these cases is:在这些情况下,我所做的是:

  • In the server, move the cursor back to the last known good commit:在服务器中,将光标移回最后一个已知的良好提交:

     git push -f origin <last_known_good_commit>:<branch_name>
  • Locally, do the same:在本地,执行相同的操作:

     git reset --hard <last_known_good_commit> # ^^^^^^ # optional



See a full example on a branch my_new_branch that I created for this purpose:请参阅我为此目的创建的分支my_new_branch的完整示例:

$ git branch
my_new_branch

This is the recent history after adding some stuff to myfile.py :这是在myfile.py添加一些东西后的最近历史:

$ git log
commit 80143bcaaca77963a47c211a9cbe664d5448d546
Author: me
Date:   Wed Mar 23 12:48:03 2016 +0100

    Adding new stuff in myfile.py

commit b4zad078237fa48746a4feb6517fa409f6bf238e
Author: me
Date:   Tue Mar 18 12:46:59 2016 +0100

    Initial commit

I want to get rid of the last commit, which was already pushed, so I run:我想摆脱已经推送的最后一次提交,所以我运行:

$ git push -f origin b4zad078237fa48746a4feb6517fa409f6bf238e:my_new_branch
Total 0 (delta 0), reused 0 (delta 0)
To git@github.com:me/myrepo.git
 + 80143bc...b4zad07 b4zad078237fa48746a4feb6517fa409f6bf238e -> my_new_branch (forced update)

Nice!好的! Now I see the file that was changed on that commit ( myfile.py ) shows in "not staged for commit":现在我看到该提交( myfile.py )中更改的文件显示在“未暂存提交”中:

$ git status
On branch my_new_branch
Your branch is up-to-date with 'origin/my_new_branch'.

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   myfile.py

no changes added to commit (use "git add" and/or "git commit -a")

Since I don't want these changes, I just move the cursor back locally as well:由于我不想要这些更改,我也只是将光标移回本地:

$ git reset --hard b4zad078237fa48746a4feb6517fa409f6bf238e
HEAD is now at b4zad07 Initial commit

So now HEAD is in the previous commit, both in local and remote:所以现在 HEAD 在本地和远程的上一个提交中:

$ git log
commit b4zad078237fa48746a4feb6517fa409f6bf238e
Author: me
Date:   Tue Mar 18 12:46:59 2016 +0100

    Initial commit

This will remove your pushed commits这将删除您推送的提交

git reset --hard 'xxxxx'

git clean -f -d

git push -f

You can REVERT (or you can also call it DELETE ) the Git Commit BOTH Locally and Remotely if you follow the steps as given below via git command line.如果您通过 git 命令行按照下面给出的步骤操作,您可以 REVERT(或者您也可以将其称为DELETE本地和远程Git 提交。

Run the following command to see the commit id that you want to revert运行以下命令以查看要还原的提交 ID

git log --oneline --decorate --graph

You will get like a following screenshot你会得到如下截图在此处输入图像描述

If you also check remote (via Web Interface) then you can see that this would be same as shown below如果您还检查远程(通过 Web 界面) ,那么您可以看到这将与如下所示相同

在此处输入图像描述

As per screenshot currently you are on commit id e110322 however you want to revert back to 030bbf6 BOTH LOCALLY and REMOTELY .根据当前屏幕截图,您正在提交 id e110322但是您想在本地和远程恢复到030bbf6

Perform the following steps to DELETE/REVERT Commits Locally+Remotely执行以下步骤以本地+远程删除/恢复提交


First Locally Reverting to commit id 030bbf6第一次本地恢复到提交 id 030bbf6

git reset --hard 030bbf6

followed by其次是

git clean -f -d

These two commands clean force reset to commit stage 030bbf6 as shown below in snapshot这两个命令 clean 强制重置为提交阶段030bbf6 ,如下图所示

在此处输入图像描述

now if you run git status then you'll see that you are TWO Commits BEHIND from the remote branch as shown below现在如果你运行 git status 那么你会看到你是来自远程分支的两个 Commits BEHIND ,如下所示在此处输入图像描述

Run following to update your indexes (if there are any updates).运行以下以更新您的索引(如果有任何更新)。 It is recommended that you ask all developers not to accept any pull requests on main remote branch.建议您要求所有开发人员不要在主远程分支上接受任何拉取请求。

git fetch --all

Once you are done with it then you are required to Push this commit forcefully by using + symbol in-front of branch as shown below.完成后,您需要通过在分支前面使用+符号来强制推送此提交,如下所示。 I have used here as master branch, you can replace it with any我在这里用作主分支,您可以将其替换为任何

在此处输入图像描述 Code代码

git push -u origin +master

now if you see the web interface of remote then commit there should be reverted as well.现在,如果您看到远程的 Web 界面,那么提交也应该被还原。

在此处输入图像描述

Let's say 61234 is the sha-number of the last good commit you want to keep.假设61234是您要保留的最后一个良好提交的 sha 编号。

git reset --hard 61234
git push -f

will remove completely all wrong commits without any trace.将完全删除所有错误的提交,没有任何痕迹。

Note: If you wanted to push (the commit you reset to) to a specific branch you'd use git push -f origin branch-name instead.注意:如果您想将(您重置的提交)推送到特定分支,您可以使用git push -f origin branch-name代替。

2020 Simple way : 2020 简单方法:

git reset <commit_hash>

(The hash of the last commit you want to keep). (您要保留的最后一次提交的哈希值)。

You will keep the now uncommitted changes locally.您将在本地保留现在未提交的更改。

If you want to push again, you have to do :如果你想再次推送,你必须这样做:

git push -f
git revert HEAD -m 1

In the above code line.在上面的代码行中。 "Last argument represents" “最后一个参数代表”

  • 1 - reverts one commits. 1 - 恢复一个提交。

  • 2 - reverts last two commits. 2 - 恢复最后两次提交。

  • n - reverts last n commits. n - 恢复最后 n 次提交。

You need to push after this command to take the effect on remote.您需要在此命令之后推送才能远程生效。 You have other options like specifying the range of commits to revert.您还有其他选项,例如指定要还原的提交范围。 This is one of the option.这是选项之一。


Later use git commit -am "COMMIT_MESSAGE" then git push or git push -f稍后使用git commit -am "COMMIT_MESSAGE"然后git pushgit push -f

Here is my way:这是我的方式:

Let's say the branch name is develop .假设分支名称是develop

# Checkout a new temp branch based on one history commit(cmd to get history: git log)
git checkout <last_known_good_commit_hash>

# Delete the original develop branch 
git branch -D develop
# Create a new develop branch based on the temp branch
git checkout -b develop

# Force update this new branch
git push -f origin develop

The reset hard worked for me: Thanks @ Mo D Genensis and @ vibs2006重置为我辛苦了:谢谢@Mo D Genensis 和@ vibs2006


git reset --hard 'your last working commit hash'

git clean -f -d

git push -f

To do it cleanly:要干净地做到这一点:

git rebase -i <hash of last good commit, 9 chars is enough>

Now you will get a list of the commits from the last good commit to the HEAD with options what to do with each commit.现在,您将获得从最后一次良好提交到HEAD的提交列表,其中包含如何处理每个提交的选项。 DROP will throw away that commit. DROP将丢弃该提交。 Save the file.保存文件。

Now to fix the upstream do :现在修复上游做:

git push --force-with-lease

( With lease so you don't accidentally cause problems for someone else working on your pushed update) 使用租约,这样您就不会意外地给处理您推送更新的其他人带来问题)

This keeps the log clean by removing the wrong commit instead of introducing new commits fixing earlier erroneous commits.这通过删除错误的提交而不是引入修复早期错误提交的新提交来保持日志清洁。

你可以做类似的事情

git push origin +<short_commit_sha>^:<branch_name>

git reset <commit_hash> (to get the<commit_hash> use git log --oneline) git reset <commit_hash> (获取 <commit_hash> 使用 git log --oneline)

git restore . to restore all the changed files to the version of yout target commit将所有更改的文件恢复到您的目标提交的版本

git push origin master --force to force the push to your remote master branch. git push origin master --force强制推送到您的远程主分支。 But be careful when using the force push if there is anyone working with you in the same branch但是如果有人在同一个分支中与你一起工作,使用强制推送时要小心

Another way to do this without revert (traces of undo):另一种无需还原(撤消痕迹)的方法:

Don't do it if someone else has pushed other commits如果其他人推送了其他提交,请不要​​这样做

Create a backup of your branch, being in your branch my-branch .创建您的分支的备份,位于您的分支my-branch中。 So in case something goes wrong, you can restart the process without losing any work done.因此,如果出现问题,您可以重新启动该过程而不会丢失任何已完成的工作。

git checkout -b my-branch-temp

Go back to your branch.回到你的分支。

git checkout my-branch

Reset, to discard your last commit (to undo it):重置,放弃你的最后一次提交(撤销它):

git reset --hard HEAD^

Remove the branch on remote (ex. origin remote).删除远程分支(例如origin远程)。

git push origin :my-branch

Repush your branch (without the unwanted commit) to the remote.将您的分支(没有不需要的提交)重新推送到远程。

git push origin my-branch

Done!完毕!

I hope that helps!我希望这会有所帮助! ;) ;)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM