如何恢复多个 git 提交?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1463340/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to revert multiple git commits?
提问by Bill
I have a git repository that looks like this:
我有一个看起来像这样的 git 存储库:
A -> B -> C -> D -> HEAD
I want the head of the branch to point to A, i.e. I want B, C, D, and HEAD to disappear and I want head to be synonymous with A.
我希望分支的头部指向 A,即我希望 B、C、D 和 HEAD 消失并且我希望 head 与 A 同义。
It sounds like I can either try to rebase (doesn't apply, since I've pushed changes in between), or revert. But how do I revert multiple commits? Do I revert one at a time? Is the order important?
听起来我可以尝试变基(不适用,因为我已经推动了两者之间的更改),或者恢复。但是我如何恢复多次提交?我一次还原一个吗?顺序重要吗?
回答by Jakub Nar?bski
Expanding what I wrote in a comment
扩展我在评论中写的内容
The general rule is that you should not rewrite (change) history that you have published, because somebody might have based their work on it. If you rewrite (change) history, you would make problems with merging their changes and with updating for them.
一般规则是您不应该重写(更改)您已发布的历史记录,因为有人可能已经在此基础上进行了工作。如果您重写(更改)历史记录,则会在合并更改和更新它们时遇到问题。
So the solution is to create a new commitwhich reverts changesthat you want to get rid of. You can do this using git revertcommand.
所以解决方案是创建一个新的提交来恢复你想要删除的更改。您可以使用git revert命令执行此操作。
You have the following situation:
您有以下情况:
A <-- B <-- C <-- D <-- master <-- HEAD
(arrows here refers to the direction of the pointer: the "parent" reference in the case of commits, the top commit in the case of branch head (branch ref), and the name of branch in the case of HEAD reference).
(这里的箭头指的是指针的方向:提交时为“父”引用,分支头(branch ref)时为顶部提交,HEAD 引用时为分支名称)。
What you need to create is the following:
您需要创建的是以下内容:
A <-- B <-- C <-- D <-- [(BCD)^-1] <-- master <-- HEAD
where "[(BCD)^-1]" means the commit that reverts changes in commits B, C, D. Mathematics tells us that (BCD)^-1 = D^-1 C^-1 B^-1, so you can get the required situation using the following commands:
其中 "[(BCD)^-1]" 表示恢复提交 B、C、D 中的更改的提交。数学告诉我们 (BCD)^-1 = D^-1 C^-1 B^-1,所以您可以使用以下命令获得所需的情况:
$ git revert --no-commit D
$ git revert --no-commit C
$ git revert --no-commit B
$ git commit -m "the commit message"
Alternate solution would be to checkoutcontentsof commit A, and commit this state:
替代解决方案是签出提交 A 的内容,并提交此状态:
$ git checkout -f A -- .
$ git commit -a
Then you would have the following situation:
那么你会遇到以下情况:
A <-- B <-- C <-- D <-- A' <-- master <-- HEAD
The commit A' has the same contents as commit A, but is a different commit (commit message, parents, commit date).
提交 A' 与提交 A 具有相同的内容,但是是不同的提交(提交消息、父项、提交日期)。
The solution by Jeff Ferland, modified by Charles Baileybuilds upon the same idea, but uses git reset:
由 Charles Bailey 修改的 Jeff Ferland的解决方案基于相同的想法,但使用git reset:
$ git reset --hard A
$ git reset --soft @{1} # (or ORIG_HEAD), which is D
$ git commit
回答by deepdive
Clean way which I found useful
我发现有用的清洁方式
git revert --no-commit HEAD~3..
This command reverts last 3 commits with only one commit.
此命令仅使用一次提交还原最后 3 次提交。
Also doesn't rewrite history.
也不会改写历史。
回答by Victor
For doing so you just have to use the revertcommand, specifying the range of commits you want to get reverted.
为此,您只需要使用revert命令,指定要恢复的提交范围。
Taking into account your example, you'd have to do this (assuming you're on branch 'master'):
考虑到您的示例,您必须这样做(假设您在分支“master”上):
git revert master~3..master
This will create a new commit in your local with the inverse commit of B, C and D (meaning that it will undo changes introduced by these commits):
这将使用 B、C 和 D 的反向提交在您的本地创建一个新提交(这意味着它将撤消这些提交引入的更改):
A <- B <- C <- D <- BCD' <- HEAD
回答by konyak
Similar to Jakub's answer, this allows you to easily select consecutive commits to revert.
与 Jakub 的回答类似,这使您可以轻松选择要还原的连续提交。
# revert all commits from B to HEAD, inclusively
$ git revert --no-commit B..HEAD
$ git commit -m 'message'
回答by Jeff Ferland
git reset --hard a
git reset --mixed d
git commit
That will act as a revert for all of them at once. Give a good commit message.
这将立即恢复所有这些。给出一个好的提交信息。
回答by mateusz.fiolka
First be sure that your working copy is not modified. Then:
首先确保您的工作副本没有被修改。然后:
git diff HEAD commit_sha_you_want_to_revert_to | git apply
and then just commit. Don't forget to document what's the reason for revert.
然后就提交。不要忘记记录恢复的原因。
回答by Suamere
I'm so frustrated that this question can't just be answered. Every other question is in relation to how to revert correctly and preserve history. This question says "I want the head of the branch to point to A, i.e. I want B, C, D, and HEAD to disappearand I want head to be synonymous with A."
我很沮丧,无法回答这个问题。其他所有问题都与如何正确还原和保存历史有关。这个问题说“我希望分支的头部指向 A,即我希望 B、C、D 和 HEAD消失,我希望 head 与 A 同义。”
git checkout <branch_name>
git reset --hard <commit Hash for A>
git push -f
I learned a lot reading Jakub's post, but some guy in the company (with access to push to our "testing" branch without Pull-Request) pushed like 5 bad commits trying to fix and fix and fix a mistake he made 5 commits ago. Not only that, but one or two Pull Requests were accepted, which were now bad. So forget it, I found the last good commit (abc1234) and just ran the basic script:
我通过阅读 Jakub 的帖子学到了很多东西,但是公司中的某个人(可以在没有 Pull-Request 的情况下推送到我们的“测试”分支)推送了 5 个错误的提交,试图修复和修复他在 5 个提交前犯的错误。不仅如此,还接受了一两个拉取请求,这些请求现在很糟糕。所以算了,我找到了最后一个好的提交(abc1234)并运行了基本脚本:
git checkout testing
git reset --hard abc1234
git push -f
I told the other 5 guys working in this repo that they better make note of their changes for the last few hours and Wipe/Re-Branch from the latest testing. End of the story.
我告诉在这个 repo 中工作的其他 5 个人,他们最好记下过去几个小时的更改,并从最新的测试中擦除/重新分支。故事的结局。
回答by Warren Dew
This is an expansion of one of the solutions provided in Jakub's answer
这是 Jakub 回答中提供的解决方案之一的扩展
I was faced with a situation where the commits I needed to roll back were somewhat complex, with several of the commits being merge commits, and I needed to avoid rewriting history. I was not able to use a series of git revert
commands because I eventually ran into conflicts between the reversion changes being added. I ended up using the following steps.
我遇到了一种情况,我需要回滚的提交有些复杂,其中一些提交是合并提交,我需要避免重写历史记录。我无法使用一系列git revert
命令,因为我最终遇到了添加的还原更改之间的冲突。我最终使用了以下步骤。
First, check out the contents of the target commit while leaving HEAD at the tip of the branch:
首先,检查目标提交的内容,同时将 HEAD 留在分支的尖端:
$ git checkout -f <target-commit> -- .
(The -- makes sure <target-commit>
is interpreted as a commit rather than a file; the . refers to the current directory.)
( -- 确保<target-commit>
被解释为提交而不是文件; . 指的是当前目录。)
Then, determine what files were added in the commits being rolled back, and thus need to be deleted:
然后,确定在回滚的提交中添加了哪些文件,因此需要删除:
$ git diff --name-status --cached <target-commit>
Files that were added should show up with an "A" at the beginning of the line, and there should be no other differences. Now, if any files need to be removed, stage these files for removal:
添加的文件应该在行的开头显示为“A”,并且应该没有其他差异。现在,如果需要删除任何文件,请暂存这些文件以进行删除:
$ git rm <filespec>[ <filespec> ...]
Finally, commit the reversion:
最后,提交还原:
$ git commit -m 'revert to <target-commit>'
If desired, make sure that we're back to the desired state:
如果需要,请确保我们回到所需的状态:
$git diff <target-commit> <current-commit>
There should be no differences.
应该没有区别。
回答by Ruslan Kabalin
The easy way to revert a group of commits on shared repository (that people use and you want to preserve the history) is to use git revert
in conjunction with git rev-list
. The latter one will provide you with a list of commits, the former will do the revert itself.
在共享存储库(人们使用并且您希望保留历史记录)上恢复一组提交的简单方法是git revert
与 git 结合使用rev-list
。后者将为您提供提交列表,前者将自行执行还原。
There two ways to do that. If you want the revert multiple commits in a single commit use:
有两种方法可以做到这一点。如果您希望在一次提交中恢复多个提交,请使用:
for i in `git rev-list <first-commit-sha>^..<last-commit-sha>`; do git revert -n $i; done
this will revert a group of commits you need, but leave all the changes on your working tree, you should commit them all as usual.
这将恢复您需要的一组提交,但将所有更改保留在您的工作树上,您应该像往常一样提交所有更改。
Another option is to have a single commit per reverted change:
另一种选择是对每个还原的更改进行一次提交:
for i in `git rev-list <first-commit-sha>^..<last-commit-sha>`; do git revert --no-edit -s $i; done
For instance, if you have a commit tree like
例如,如果你有一个像这样的提交树
o---o---o---o---o---o--->
fff eee ddd ccc bbb aaa
to revert the changes from eeeto bbb, run
要将更改从eee恢复为bbb,请运行
for i in `git rev-list eee^..bbb`; do git revert --no-edit -s $i; done
回答by Dorian
None of those worked for me, so I had three commits to revert (the last three commits), so I did:
这些都不适合我,所以我有三个提交要恢复(最后三个提交),所以我做了:
git revert HEAD
git revert HEAD~2
git revert HEAD~4
git rebase -i HEAD~3 # pick, squash, squash
Worked like a charm :)
像魅力一样工作:)