题
我有一个 git 存储库,如下所示:
A -> B -> C -> D -> HEAD
我希望分支头指向A,即我希望 B、C、D 和 HEAD 消失,并且我希望 head 与 A 同义。
听起来我可以尝试重新设置基准(不适用,因为我已经在两者之间推送了更改),或者恢复。但如何恢复多次提交呢?我是否一次恢复一个?顺序重要吗?
解决方案
扩展我在评论中写的内容
一般规则是您不应该重写(更改)您已发布的历史记录,因为有人可能以此为基础进行工作。如果您重写(更改)历史记录,则在合并更改和更新它们时会遇到问题。
所以解决方案是创建一个 新提交 哪个 恢复更改 你想要摆脱的。您可以使用以下方法执行此操作 git 恢复 命令。
您有以下情况:
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"
替代解决方案是 查看 内容 提交 A,并提交此状态:
$ git checkout -f A -- .
$ git commit -a
那么你就会出现下面的情况:
A <-- B <-- C <-- D <-- A' <-- master <-- HEAD
提交 A' 与提交 A 具有相同的内容,但是不同的提交(提交消息、父级、提交日期)。
这 Jeff Ferland 的解决方案,Charles Bailey 修改 建立在相同的想法之上,但使用 git重置:
$ git reset --hard A
$ git reset --soft @{1} # (or ORIG_HEAD), which is D
$ git commit
其他提示
有关这样做,你只需要使用的恢复的命令,指定你想要得到恢复提交的范围。
考虑到你的榜样,你就必须做到这一点(假设你在分支“主”):
git revert master~3..master
这将产生在本地与逆一个新的提交B的提交,C和d(这意味着它将撤消由这些提交引入的变化):
A <- B <- C <- D <- BCD' <- HEAD
清洁方式,我发现有用
git revert --no-commit HEAD~3..
此命令恢复最后3个提交只有一个提交。
也没有改写历史。
要的Jakub的答案相似,这可以让你轻松选择连续提交恢复。
# revert all commits from B to HEAD, inclusively
$ git revert --no-commit B..HEAD
$ git commit -m 'message'
git reset --hard a
git reset --mixed d
git commit
这将在一次充当所有它们的复归。提供一个良好的提交消息。
首先要确保你的工作副本没有被修改。然后:
git diff HEAD commit_sha_you_want_to_revert_to | git apply
,然后就提交。不要忘记记录什么对于撤销的原因。
我很沮丧,这个问题不能仅仅回答。每另一个问题是关于如何正确地恢复和保存历史。这个问题说“我要分支的头部指向A,即我想要B,C,d,和HEAD为消失并欲头为与A.同义”
git checkout <branch_name>
git reset --hard <commit Hash for A>
git push -f
我学到了很多阅读的Jakub的职位,但在公司的一些人(访问推送到我们的“测试”不拉请求分支)推像5不良承诺试图修复和修复和修复他做了5个错误前提交。不仅如此,但一个或两个引入请求被接受,这是现在糟糕。就这样算了吧,我找到的最后一个良好的提交(ABC1234)和刚刚运行的基本脚本:
git checkout testing
git reset --hard abc1234
git push -f
我跟其它五人在此回购他们更好地记下他们的变化在过去的几个小时,从最新的测试擦拭/重科的工作。故事的结束。
这是在的Jakub的回答提供的解决方案中的一个的膨胀
我面临着在提交我需要回滚的情况是有些复杂的,具有多个所述感提交合并提交的,我需要避免重写历史。我无法使用一系列git revert
命令,因为我终于遇到了冲突之间的变化所添加的逆转。我最终使用以下步骤。
首先,检查出的目标的内容提交,同时留下HEAD在分支的末端:
$ git checkout -f <target-commit> -- .
(该 - 确保<target-commit>
被解释为一个提交而不是文件;所述指当前目录。)
然后,确定在提交加入哪些文件被回滚,并且因此需要被删除:
$ git diff --name-status --cached <target-commit>
添加的应该显示了一个“A”在该行的开头,并且不应该有其他的差异文件。现在,如果任何文件需要被去除,舞台这些文件用于去除:
$ git rm <filespec>[ <filespec> ...]
最后,提交回复:
$ git commit -m 'revert to <target-commit>'
如果需要,确保我们又回到了期望的状态:
$git diff <target-commit> <current-commit>
不应该有差异。
在简单的方法来恢复一组共享库的提交(即人们使用和要保留历史)与混帐git revert
一起使用rev-list
。后者将为您提供所有提交的名单,前者会做复归本身。
有两种方法可以做到这一点。如果您希望还原多个在单个提交使用承诺:
for i in `git rev-list <first-commit-sha>^..<last-commit-sha>`; do git revert -n $i; done
这将返回一组需要提交的,但保留所有对你的工作树的变化,你应该提交他们都和往常一样。
另一种选择是具有每收归变化单个提交:
for i in `git rev-list <first-commit-sha>^..<last-commit-sha>`; do git revert --no-edit -s $i; done
举例来说,如果你有一个像
提交树 o---o---o---o---o---o--->
fff eee ddd ccc bbb aaa
恢复从变化的 EEE 至 BBB ,运行
for i in `git rev-list eee^..bbb`; do git revert --no-edit -s $i; done
这些都不为我工作,所以我有三个提交恢复(最后三个提交),所以我所做的:
git revert HEAD
git revert HEAD~2
git revert HEAD~4
git rebase -i HEAD~3 # pick, squash, squash
工作就像一个魅力:)
在我看来,一个非常简单和干净的方式可以是:
回到A
git checkout -f A
点主人的头到当前状态
git symbolic-ref HEAD refs/heads/master
保存
git commit
如果你想暂时恢复功能的提交,那么你可以使用该系列下面的命令。
git的日志--pretty = ONELINE | grep的 'FEATURE_NAME' |切-d '' -f1 | xargs的-n1 GIT中恢复--no编辑