搞砸了主 git 分支......无法弄清楚我需要恢复啥
Posted
技术标签:
【中文标题】搞砸了主 git 分支......无法弄清楚我需要恢复啥【英文标题】:Screwed up the master git branch... Can't figure out what I need to revert搞砸了主 git 分支......无法弄清楚我需要恢复什么 【发布时间】:2012-05-08 12:26:22 【问题描述】:我正在开发一个 git 存储库,它有一个 master 分支,我们称之为 ab
分支。我的团队正在开发ab
分支,并且使用 github 有一个拉取请求工作流。我的一位队友从他的分支jeremy_ab_deletions
向ab
分支提出了拉取请求。我正在查看/测试他的更改,但是当我将它们合并到 ab
分支时,我不小心将它们合并到了 master 中,并在我发现错误之前将 master 推送到了 github。认为我可以 git-revert 我所做的更改 git revert SHA
并且它似乎有效......
我认为这已经足够了,我很高兴地切换回我的 ab 分支并继续工作。然而,现在,我意识到来自 ab
分支的先前提交应该永远最终在 master 中,都在 master 中。这……真是一团糟。由于他的分支最初是从ab
中分离出来的,然后我将其合并到master 中,所以我应该使用git revert -m 1 SHA
将其还原。
今天我试图弄清楚我到底哪里出错了,根据 git 历史和我的 reflog,我感到很困惑。首先,我尝试还原还原,然后执行 git revert -m 1 SHA
但 git 告诉我:
fatal: Mainline was specified but commit 4c431c345dfe0a856967c090932c32f153824085 is not a merge.
所以我认为可以...也许这不是合并提交,我需要针对不同的 SHA。但是看看历史,我一生都无法弄清楚其中哪一个是合并提交......
This was supposed to be on AB...
…
d985b5bcf8 Browse code
Nathan B authored 8 days ago
This was supposed to be on AB...
…
0e01911273 Browse code
Nathan B authored 8 days ago
removed unecessary tests
4c431c345d Browse code
Nathan B authored 8 days ago
Apr 17, 2012
removing un-used views and pages
a546f90ed3 Browse code
jeremychurch authored 10 days ago
说“这应该在 AB 上”的两个提交是还原提交以还原“已删除的不必要测试”和“删除未使用的视图和页面”提交。对 master 的下一次提交是今天,之前的提交是在 16 日,两者都不相关。我没有看到实际的 merge 发生在哪里。
我查看了我的 reflog,看看究竟是哪里出了问题。我使用git reset --hard HEAD@NUM
对 reflog 版本进行了上下调整,然后检查关键文件以查看是否存在错误更改。最后,我将范围缩小到这些 reflog:
1fe2be2 HEAD@79: checkout: moving from 1fe2be29c6eda9f9fc9eb0b372ee83b7c15dfc2c to jeremy_ab_deletions
1fe2be2 HEAD@80: HEAD@3: updating HEAD
4c431c3 HEAD@81: HEAD@1: updating HEAD
47a97af HEAD@82: commit: removed unecessary tests, routes, and controller actions
4c431c3 HEAD@83: merge jeremy_ab_deletions: Fast-forward
1fe2be2 HEAD@84: checkout: moving from master to ab
d985b5b HEAD@85: revert: This was supposed to be on AB...
0e01911 HEAD@86: revert: This was supposed to be on AB...
4c431c3 HEAD@87: merge jeremy_ab_deletions: Fast-forward
c121a08 HEAD@88: checkout: moving from jeremy_ab_deletions to master
4c431c3 HEAD@89: commit: removed unecessary tests
a546f90 HEAD@90: checkout: moving from ab_page_changes to jeremy_ab_deletions
511b340 HEAD@91: checkout: moving from jeremy_ab_deletions to ab_page_changes
a546f90 HEAD@92: pull git@github.com:REDACTED/repo.git ab-remove-stuff: Fast-forward
特别是 HEAD@88 这里没有错误的提交,而 HEAD@87 有。因此,可以合理地假设我在merge jeremy_ab_deletions: Fast-forward
提交上搞砸了……但我无法弄清楚那将是哪个“合并提交”。我试过这个:
$ git revert -m 1 4c431c3
fatal: Mainline was specified but commit 4c431c345dfe0a856967c090932c32f153824085 is not a merge.
我...似乎找不到实际的合并提交?有谁知道我做错了什么:/我现在很迷茫。
【问题讨论】:
【参考方案1】:如果没有其他人拉过这个主人(或者拉了但肯定没有使用它),这就是我会做的:
-
如果自“事故”以来没有对 master 进行任何操作,我只需将其重置为最后一次好的提交,然后更新远程 master 分支(通过使用 -f 推送)。
如果某些工作已经完成,您可以将其重置为最后一个好的提交,然后使用
git rebase -i
并删除有问题的提交,将好的提交留在列表中。然后你需要再次推送(使用-f
)。
或者,您可以在新分支中完成所有这些操作:
-
在 master 中检查最后一个好的提交,在那里创建一个分支,
然后使用
git rebase -i master
过滤掉错误提交。
然后你可以回到master并手动“合并”,从新分支引入所有更改,并覆盖master中的所有内容(你可以使用--no-commit
和git checkout --theirs
)
推送(没有-f
)固定的master。
希望这会有所帮助!我讨厌紧急情况。
【讨论】:
如果有人已经拉了坏主人会有什么影响?我可以在那里执行第 1 步(完全删除发生这种情况的历史),然后他们可以拉取并接收正确的主人吗?或者当他有上游不知道的变化时,git会感到困惑吗? 如果其他人拉出了糟糕的“master”分支,他们将不得不经历基本相同的步骤。如果他们从那时起没有对 他们的 副本进行任何更改,他们可以通过fetch
ing 固定的主副本并更新他们的参考来缩短它。很容易理解为什么如果您只记得每个克隆都以 就像 从中克隆它的“原始”开始:所以如果您必须在“原始”上执行步骤 1、2、3那么您还必须在克隆上执行步骤 1、2、3。
将在此处执行第 1 步,并确保拉动 master 的另一个人也将其修复。哈哈,这会教我随意合并和推送!【参考方案2】:
更新:虽然这可能对其他人有所帮助,但这实际上让我更沮丧。我会把它放在这里以防其他人偶然发现它。
sinelaw 为我指明了正确的方向……但我在这里找到了更合适的答案:Revert to a commit by a SHA hash in Git?
答案的信息如下:
如果您想在当前 HEAD 之上以确切状态提交 在不同的提交中,撤消所有中间提交,然后你 可以使用 reset 来创建索引的正确状态以使 提交。
这正是我想要的。我想恢复到 HEAD@88 但是让它恢复它自己的提交,因为有些人已经拉了 master 分支,我不想让他们像我必须的那样经历重置步骤......所以这些是我使用的命令:
# reset the index to the desired tree
git reset HEAD@88
# move the branch pointer back to the previous HEAD
git reset --soft HEAD@1
git commit -m "Revert the bad ab merge"
# Update working copy to reflect the new commit
git reset --hard
# Clean untracked files
git clean -f -d
查看历史记录,我可以看到我刚刚创建了一个提交,其中完全反转了所有本应专属于 ab 分支的更改。
(更新):没关系,这不是我想要的。我们的仓库有几个分支,以及“主”分支。 master 旨在保存其他 3 个分支中通用的更改,并且它经常合并到这些分支中。执行此 revert-with-a-commit 系列命令会使 master 合并到“ab”分支(或任何分支)中,这是合并冲突和意外删除文件的严重噩梦(因为他们应该 住在 ab 里,只是不在 master 里)。我采用了上述 sinelaw 的解决方案,并与一位非技术设计师合作,该设计师也将 master 拉回了好的版本。
【讨论】:
如果你在一个单独的分支上完成(我描述的“替代”),其他人只需要再次拉主,而无需任何特殊工作。我错了吗? 这涉及通过交互式变基来确定要保留哪些提交以及哪些提交应该是ab
独有的。 ab
上存在 很多 的提交,我不一定想过滤掉它们……最后在他的机器上,我们只是做了 git branch -D master
git fetch upstream
git checkout -b master upstream/master
这使他的主人与上游的正确主人保持一致。似乎奏效了。以上是关于搞砸了主 git 分支......无法弄清楚我需要恢复啥的主要内容,如果未能解决你的问题,请参考以下文章