我的一个分支由于主分支中的强制推入而导致提交历史记录错误。基本上,我在此分支历史中具有以下提交:A,B,C,D,E,其中应保留E,但应删除ABCD。之所以添加它们,是因为在将这些提交强制从主服务器原点删除之前,主服务器已合并到分支中。我该怎么做?
如果A是要保留的那个,我可以git reset --hard A,但这是另一个方向。...
答案 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 strategy到simple
,我会建议。这是git 2的默认设置。
如果您使用的是Stash / BitBucket,Gitlab或Github等集中托管的git解决方案,它们都提供所谓的“分支保护”规则,以防止开发人员强行推入分支机构。 / p>
添加一条规则以防止强制推送到master
甚至可能是release
分支。
答案 2 :(得分:2)
您可以使用git reset --hard A^
进行最后一次“良好”提交,然后使用git cherry-pick E
应用您要保留的提交。
然后,您必须强行将其推入分支以重置内容。确保让团队中的其他所有人知道发生了什么。