Git:在最新提交之前还原功能分支中的所有提交

时间:2019-01-22 14:49:30

标签: git git-reset git-revert

我的一个分支由于主分支中的强制推入而导致提交历史记录错误。基本上,我在此分支历史中具有以下提交:A,B,C,D,E,其中应保留E,但应删除ABCD。之所以添加它们,是因为在将这些提交强制从主服务器原点删除之前,主服务器已合并到分支中。我该怎么做?

如果A是要保留的那个,我可以git reset --hard A,但这是另一个方向。...

3 个答案:

答案 0 :(得分:3)

# make a backup of the current state of your branch
git branch backup your_branch

# reset to the commit prior to A
git reset --hard A^

# then re-apply E
git cherry-pick E

将是这样做的一种方式。变基是另一个(请参阅msanford's very detailed answer

答案 1 :(得分:3)

带底基+ drop

的选项

正如罗曼(Romain)建议的“重新设置基准”一样,这是一种方法,假设您确实希望按照拉西的要求将@-A-B-C-D-E的最终结果设为@-E

我就像您工具栏中的另一个工具一样提供了它:这不是解决问题的更简单方法。但是,它确实允许您删除不按顺序提交的内容(例如,删除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),然后继续进行基础调整,直到修复分支为止。

如果此后发生了一些不可思议的事情(例如,您将提交哈希更改为不存在的提交哈希,或者变基停止执行某些操作并且您不知道为什么),则可以使用git rebase --abort完全放弃变基这将带您回到初始状态。

如果您的分支看起来正确,请强行推入。

git push -f

关于推力的重要说明

鲜为人知,但git 2之前的默认推送策略为matching,这意味着当您git push时,它将推送 all 本地分支以及匹配的远程分支名称,而不仅仅是您当前的分支。

因此,当您git push -f时,它将强行推送所有分支机构的所有(这是昨天发生在同事身上的)。检查git config --global push.default。这意味着,如果您玩弄其他分支,也可能会强行推动它。

如果不是changing the default push strategysimple,我会建议。这是git 2的默认设置。

分支保护

如果您使用的是Stash / BitBucket,Gitlab或Github等集中托管的git解决方案,它们都提供所谓的“分支保护”规则,以防止开发人员强行推入分支机构。 / p>

添加一条规则以防止强制推送到master甚至可能是release分支。

答案 2 :(得分:2)

您可以使用git reset --hard A^进行最后一次“良好”提交,然后使用git cherry-pick E应用您要保留的提交。

然后,您必须强行将其推入分支以重置内容。确保让团队中的其他所有人知道发生了什么。