![](/img/trans.png)
[英]Can I revert to an old Git commit, while preserving the latest commits?
[英]Git: Revert all commits in feature branch prior to latest commit
我有一个分支,由于我们的主分支中的强制推送而导致错误的提交历史记录。 基本上我在这个分支历史中有以下提交:A,B,C,D,E,其中应该保留E但是应该删除ABCD。 添加它们是因为在主要来源强制删除这些提交之前,主要合并到分支中。 我怎么能做到这一点?
如果A是保存的那个我可以git reset - 硬A但是它是另一个方向....
drop
选项 正如Romain所说,“rebase是另一种”,这是一种方法,假设你确实希望@-ABCDE
的最终结果是@-E
,正如Lasse所说的那样。
我提供这个作为你的工具带中的另一个工具 :它不是解决这个问题的简单方法。 但它确实允许您删除不按顺序的提交(例如,删除A,C,E并保留B,D):
git rebase -i HEAD~6
这将使用如下所示的缓冲区打开您的编辑器(可能是vi
):
pick 4231648cb4 Some previous commit
pick 4bccf2ce81 A some message
pick 7b4cd5ff17 B some message
pick faa44efb7c C some message
pick 0ce0525a79 D some message
pick f104648cc3 E some message
# Rebase 76eb9131b5..ed71142fcb onto 4231648cb4 (6 commands)
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup <commit> = like "squash", but discard this commit's log message
# x, exec <command> = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop <commit> = remove commit
# l, label <label> = label current HEAD with a name
# t, reset <label> = reset HEAD to a label
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
# . create a merge commit using the original merge commit's
# . message (or the oneline, if no original merge commit was
# . specified). Use -c <commit> to reword the commit message.
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out
是的,从顶部到底部的提交顺序是反向时间顺序(与git log
相反),最近的顺序在底部。 这就是为什么“线从上到下执行” - 从最旧到最近。
按照说明,将单词pick
更改为要删除的行上的d
(或drop
)。
pick 4231648cb4 Some previous commit
d 4bccf2ce81 A some message
d 7b4cd5ff17 B some message
d faa44efb7c C some message
d 0ce0525a79 D some message
pick f104648cc3 E some message
如果你犯了一个不可恢复的错误,比如删除一行,则在不保存的情况下退出( :q!
)并重试。
如果一切看起来都不错,请保存并退出缓冲区( :wq
)并继续重新定位,直到您的分支被修复为止。
如果在那之后发生了一些不稳定的事情(就像你将一个提交哈希改为一个不存在的,或者rebase停止做某事而你不知道为什么)你可以用git rebase --abort
完全中止git rebase --abort
会带来你回到了初始状态。
如果您的分支看起来正确,请强制推送。
git push -f
可能鲜为人知,但是在git 2之前的默认推送策略是matching
,这意味着当你git push
,它将推送所有本地分支机构的匹配远程分支名称,而不仅仅是当前分支。
所以,当你git push -f
它会强制推送你所有的分支(这发生在昨天的同事身上)。 检查git config --global push.default
。 这意味着,如果你玩弄其他一些分支,它也可以强制推动它。
如果不是那样,我建议将默认推送策略更改为simple
。 这是git 2的默认值。
如果您使用集中托管的git解决方案,如Stash / BitBucket,Gitlab或Github,它们都提供所谓的“分支保护”规则,以防止开发人员强行推送到分支机构。
添加规则以防止强制推送到master
并可能release
分支。
您可以使用git reset --hard A^
转到最后一个“好”提交,然后git cherry-pick E
来应用您想要保留的提交。
然后你必须强制将它推到分支重置的东西。 一定要让团队中的其他人知道发生了什么。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.