4

我正在开发一个 git 存储库,它有一个 master 分支,我们称之为ab分支。我的团队正在ab分支上工作,并且有一个使用 github 的拉取请求工作流。我的一个队友从他的分支jeremy_ab_deletionsab分支提出了拉取请求。我正在审查/测试他的更改,但是当我将它们合并到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 日,两者都不相关。我没有看到实际合并发生在哪里。

我浏览了我的 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.

我......似乎找不到实际的合并提交?有谁知道我做错了什么:/我现在很迷茫。

4

2 回答 2

4

如果没有其他人拉过这个主人(或拉过但肯定没有使用它),这就是我会做的:

  1. 如果自“意外”以来没有在 master 上完成任何工作,我只需将其重置为最后一次好的提交,然后更新远程 master 分支(通过使用 -f 推送)。
  2. 如果某些工作已经完成,您可以将其重置为最后一个好的提交,然后使用git rebase -i并删除有问题的提交,将好的提交留在列表中。然后你需要再次推动(使用-f)。

或者,您可以在新分支中执行所有这些操作:

  1. 签出 master 中最后一个好的提交,在那里创建一个分支,
  2. 然后用于git rebase -i master过滤掉错误的提交。
  3. 然后您可以返回 master 并手动“合并”,从新分支中引入所有更改,并覆盖 master 中的所有内容(您可以使用--no-commitand git checkout --theirs
  4. 推( -f)固定的主人。

希望这可以帮助!我讨厌合并

于 2012-04-27T18:44:30.810 回答
1

更新:虽然这可能对其他人有所帮助,但这实际上让我更沮丧。我会把这个留在这里,以防其他人偶然发现它。

sinelaw 为我指明了正确的方向……但我在这里找到了更合适的答案: Revert to a commit by a SHA hash in Git?

答案的信息如下:

如果您想在当前 HEAD 之上以不同提交的确切状态提交,撤消所有中间提交,那么您可以使用 reset 来创建索引的正确状态以进行提交。

这正是我想要的。我想恢复到 HEAD@{88} 但是让它恢复它自己的提交,因为有些人已经拉了主分支,我不想让他们像我必须的那样经历重置步骤......所以这些是我使用的命令:

# 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 拉回了好版本。

于 2012-04-27T19:50:55.980 回答