Bil*_*ill 877 git commit git-revert
我有一个git存储库,如下所示:
A -> B -> C -> D -> HEAD
Run Code Online (Sandbox Code Playgroud)
我希望分支的头部指向A,即我希望B,C,D和HEAD消失,我希望头部与A同义.
听起来我可以尝试改变(不适用,因为我推动了之间的变化),或者还原.但是如何恢复多个提交?我一次还原一个吗?订单重要吗?
Jak*_*ski 1229
扩展我在评论中写的内容
一般规则是您不应该重写(更改)您已发布的历史记录,因为有人可能已将其工作基于它.如果您重写(更改)历史记录,则会在合并更改和更新时遇到问题.
所以解决方案是创建一个新的提交,它可以恢复你想要删除的更改.您可以使用git revert命令执行此操作.
您有以下情况:
A <-- B <-- C <-- D <-- master <-- HEAD
(这里的箭头指的是指针的方向:提交时的"父"引用,分支头(分支引用)的顶部提交,以及HEAD引用的分支名称).
您需要创建的内容如下:
A <-- B <-- C <-- D <-- [(BCD)^-1] <-- master <-- HEAD
其中"[(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"
Run Code Online (Sandbox Code Playgroud)
替代解决方案是检查 提交A的内容,并提交此状态:
$ git checkout -f A -- .
$ git commit -a
Run Code Online (Sandbox Code Playgroud)
那么你会遇到以下情况:
A <-- B <-- C <-- D <-- A' <-- master <-- HEAD
提交A'与提交A具有相同的内容,但是是不同的提交(提交消息,父项,提交日期).
由Charles Bailey修改的Jeff Ferland的解决方案建立在同样的想法上,但使用git reset:
$ git reset --hard A
$ git reset --soft @{1} # (or ORIG_HEAD), which is D
$ git commit
Run Code Online (Sandbox Code Playgroud)
小智 214
为此,您只需使用revert命令,指定要恢复的提交范围.
考虑到你的例子,你必须这样做(假设你在分支'master'):
git revert master~3..master
Run Code Online (Sandbox Code Playgroud)
这将在您的本地创建一个新的提交,使用B,C和D的反向提交(意味着它将撤消这些提交引入的更改):
A <- B <- C <- D <- BCD' <- HEAD
Run Code Online (Sandbox Code Playgroud)
dee*_*ive 190
干净的方式,我发现有用
git revert --no-commit HEAD~3..
Run Code Online (Sandbox Code Playgroud)
此命令仅使用一次提交恢复最后3次提交.
也不会重写历史记录.
kon*_*yak 64
与Jakub的答案类似,这使您可以轻松选择要还原的连续提交.
# revert all commits from B to HEAD, inclusively
$ git revert --no-commit B..HEAD
$ git commit -m 'message'
Run Code Online (Sandbox Code Playgroud)
Jef*_*and 55
git reset --hard a
git reset --mixed d
git commit
Run Code Online (Sandbox Code Playgroud)
这将立刻成为所有人的回复.给出一个好的提交消息.
mat*_*lka 36
首先要确保您的工作副本未被修改.然后:
git diff HEAD commit_sha_you_want_to_revert_to | git apply
Run Code Online (Sandbox Code Playgroud)
然后只是提交.不要忘记记录恢复的原因.
meh*_*meh 36
Restore您还可以使用restore命令:
A <- B <- C <- D <- HEAD
Run Code Online (Sandbox Code Playgroud)
假设您想HEAD看起来一模一样A。确保您已拉取最新的main. 然后剪出一个新的树枝。
git switch -c feature/flux-capacitor # synonymous with checkout -b
git restore --source A .
git add .
git commit
git push
Run Code Online (Sandbox Code Playgroud)
该restore命令将所有内容 ( .) 更改为提交时的内容--source。然后,您将其提交到本地分支并将其推送到原点。然后你可以针对它打开一个 PR。
这样做的好处是不会改变其他人可能基于工作的任何历史。也为后人留下了有用的历史。
文档:git 恢复
Sua*_*ere 28
我很沮丧,这个问题不能回答.所有其他问题都与如何正确还原和保存历史有关.这个问题说"我希望分支的负责人指向A,即我希望B,C,D和HEAD 消失,我希望头部与A同义".
git checkout <branch_name>
git reset --hard <commit Hash for A>
git push -f
Run Code Online (Sandbox Code Playgroud)
我学到了很多阅读Jakub的帖子,但该公司的一些人(可以通过推送到我们的"测试"分支而没有Pull-Request)推动了5个糟糕的提交,试图修复并修复并修复他5次提交之前的错误.不仅如此,还接受了一两个Pull请求,现在已经很糟糕了.所以忘掉它,我找到了最后一个好的提交(abc1234)并且只运行了基本脚本:
git checkout testing
git reset --hard abc1234
git push -f
Run Code Online (Sandbox Code Playgroud)
我告诉在这个回购中工作的其他5个人,他们最好记下他们在过去几个小时内的变化以及最新测试中的Wipe/Re-Branch.故事的结局.
这是Jakub答案中提供的解决方案之一的扩展
我面临的情况是,我需要回滚的提交有点复杂,其中几个提交是合并提交,我需要避免重写历史记录.我无法使用一系列git revert命令,因为我最终遇到了添加的返回更改之间的冲突.我最终使用了以下步骤.
首先,检查目标提交的内容,同时将HEAD留在分支的顶端:
$ git checkout -f <target-commit> -- .
Run Code Online (Sandbox Code Playgroud)
( - 确保<target-commit>被解释为提交而不是文件;.指的是当前目录.)
然后,确定在回滚的提交中添加了哪些文件,因此需要删除:
$ git diff --name-status --cached <target-commit>
Run Code Online (Sandbox Code Playgroud)
添加的文件应该在行的开头显示"A",并且不应存在其他差异.现在,如果需要删除任何文件,请暂存这些文件以进行删除:
$ git rm <filespec>[ <filespec> ...]
Run Code Online (Sandbox Code Playgroud)
最后,提交reversion:
$ git commit -m 'revert to <target-commit>'
Run Code Online (Sandbox Code Playgroud)
如果需要,请确保我们恢复到所需的状态:
$git diff <target-commit> <current-commit>
Run Code Online (Sandbox Code Playgroud)
应该没有差异.
在共享存储库(人们使用并且您希望保留历史记录)上恢复一组提交的简单方法是git revert与 git 结合使用rev-list。后者将为您提供提交列表,前者将自行执行还原。
有两种方法可以做到这一点。如果您希望在一次提交中恢复多个提交,请使用:
for i in `git rev-list <first-commit-sha>^..<last-commit-sha>`; do git revert --no-commit $i; done
Run Code Online (Sandbox Code Playgroud)
这将恢复您需要的一组提交,但将所有更改保留在您的工作树上,之后您应该像往常一样提交所有更改。
另一种选择是对每个还原的更改进行一次提交:
for i in `git rev-list <first-commit-sha>^..<last-commit-sha>`; do git revert --no-edit -s $i; done
Run Code Online (Sandbox Code Playgroud)
例如,如果你有一个像这样的提交树
o---o---o---o---o---o--->
fff eee ddd ccc bbb aaa
Run Code Online (Sandbox Code Playgroud)
要将更改从eee恢复为bbb,请运行
for i in `git rev-list eee^..bbb`; do git revert --no-edit -s $i; done
Run Code Online (Sandbox Code Playgroud)
在我看来,一个非常简单和干净的方法可能是:
git checkout -f A
Run Code Online (Sandbox Code Playgroud)
git symbolic-ref HEAD refs/heads/master
Run Code Online (Sandbox Code Playgroud)
git commit
Run Code Online (Sandbox Code Playgroud)
这些都不适合我,所以我有三个提交要恢复(最后三个提交),所以我做了:
git revert HEAD
git revert HEAD~2
git revert HEAD~4
git rebase -i HEAD~3 # pick, squash, squash
Run Code Online (Sandbox Code Playgroud)
像魅力一样工作:)
可能不如这里的其他方法优雅,但我总是用来get reset --hard HEAD~N撤消多个提交,其中N是您想要返回的提交数量。
或者,如果不确定提交的确切数量,只需git reset --hard HEAD^多次运行(返回一次提交),直到达到所需状态。