Git混乱!提交记录出现在错误分支中

3
我刚在一个 Git 仓库上做了一件可怕的事情,我不知道该如何解决这个问题。我甚至不知道自己是如何把它搞成这样的...!
在这个仓库(托管在 GitHub 上),有三个分支我很感兴趣:主分支 master,分支 A 和分支 B。分支 A 和分支 B 没有关联(涉及不同的文件)。
以下是目前的情况:
A -- B -- C -- D -- master
     \               \ change_from_B_1..4 -- change_from_A_1+2 -- brancheA 
      \ -- merge_from_master -- change_from_A_1 -- change_from_A_2 -- brancheB

我想哭:> 是的,change_from_A 意味着“应该在分支 A 中的更改”!最糟糕的是,在分支 A 中,有 4 个提交曾经在分支 B 中(change_from_B_1..4),在我将主分支合并到分支 B 之前。现在,这些 4 个提交位于分支 A 中(怎么回事?),不再位于分支 B 中。

我不知道我做了什么才会陷入这种情况,以下是我的 git reflog 的一些摘录,如果有帮助:

    b8b5db7 HEAD@{0}: checkout: moving from brancheA to brancheB
    015fdc1 HEAD@{1}: checkout: moving from brancheB to brancheA
    b8b5db7 HEAD@{2}: checkout: moving from brancheA to brancheB
    015fdc1 HEAD@{3}: checkout: moving from master to brancheA
    3830ccb HEAD@{4}: checkout: moving from brancheB_tmp to master
    2a9ba60 HEAD@{5}: cherry-pick: change_from_B_1
    3830ccb HEAD@{6}: checkout: moving from 3830cc to brancheB_tmp
    3830ccb HEAD@{7}: pull origin master: Fast-forward
    8ef3368 HEAD@{8}: checkout: moving from brancheB to master
    b8b5db7 HEAD@{9}: pull origin brancheA: Merge made by recursive.
    cc17c2e HEAD@{10}: pull origin brancheB: Fast-forward
    d867eff HEAD@{11}: HEAD^^: updating HEAD
    cc17c2e HEAD@{12}: checkout: moving from brancheA to brancheB
    015fdc1 HEAD@{13}: commit: change_from_B_6?? (lost :<)
    2f650f6 HEAD@{14}: commit: change_from_B_5?? (lost :<)
    9098bfa HEAD@{15}: commit: change_from_A_1+2
    01c7a5e HEAD@{16}: HEAD^^^: updating HEAD
    cc17c2e HEAD@{17}: checkout: moving from brancheB to brancheA
    cc17c2e HEAD@{18}: merge brancheA: Fast-forward
    d867eff HEAD@{19}: checkout: moving from brancheA to brancheB
    cc17c2e HEAD@{20}: commit: change_from_A_2
    3bee54e HEAD@{21}: checkout: moving from brancheB to brancheA
    d867eff HEAD@{22}: checkout: moving from brancheA to brancheB
    3bee54e HEAD@{23}: commit: change_from_A_1
    d867eff HEAD@{24}: checkout: moving from d867eff to brancheA
    d867eff HEAD@{25}: checkout: moving from brancheB to another_branch
    d867eff HEAD@{26}: checkout: moving from another_branch to brancheB
    d867eff HEAD@{27}: checkout: moving from d867eff to another_branch
    d867eff HEAD@{28}: commit (merge): Merge branch 'master' of super_github
    01c7a5e HEAD@{29}: commit: change_from_B_4
    1dbc4e1 HEAD@{30}: commit: change_from_B_3
    52417fa HEAD@{31}: commit: change_from_B_2
    8e5d258 HEAD@{32}: commit: change_from_B_1
    8ef3368 HEAD@{33}: checkout: moving from master to brancheB

对于我来说,一切看起来正常,直到我开始引入分支A(d867eff HEAD@{24}:checkout: moving from d867eff to brancheA)。当时,我只是在编码,不太在意 git ... 犯了一个大错误。无论如何,我不确定是什么造成了混乱,是 cc17c2e HEAD@{18}:merge brancheA:Fast-forward 吗? 我不记得询问过那个...!其余的可能就是将混乱变成更糟糕的情况,我非常惭愧将它放在这里,但此时此刻,我感到非常无助。

我考虑过从头开始重新生成所有来自主分支的提交,但这样做会失去代码评审员在 GitHub 上的所有评论,这对我来说是一个很大的损失。

我想做的:

  • 删除分支B中的 change_from_A_1 / change_from_A_2
  • 将应该在主分支合并之前在分支B中的提交移回分支A

以达到以下效果:

A -- B -- C -- D -- master
     \               \  -- change_from_A_1+2 -- brancheA 
      \ change_from_B_1..4 -- merge_from_master -- brancheB

你有任何建议吗?谢谢!
1个回答

1

这种问题总是可以解决的。

  1. 在branchA和branchB上分别创建oldBranchA和oldBranchB。
  2. 将branchA重置为master,将branchB重置为B。
  3. 检出branchA。
  4. 挑选change_from_A_1+2。
  5. 检出branchB。
  6. 挑选change_from_B_1..4,然后合并merge_from_master。
  7. 删除oldBranchA和oldBranchB。
  8. 要推回到origin,请执行git push -f branchA:branchA。但在执行此操作之前,请三思而后行,因为您正在尝试覆盖已发布的历史记录!

谢谢!对于第8步,如何推送到远程?我尝试了git push origin branchA,但是出现了拒绝快进的问题。我应该强制推送还是这意味着我在步骤中犯了错误? - Enders
@Enders,我小心地补充了答案。 - Yasushi Shoji
谢谢!我完成了所有步骤,仓库看起来恢复正常了!唯一的缺点是我失去了在 GitHub 上审核代码的人们留下的所有评论(cherry-pick 似乎重新生成了新的哈希值)。不过我在邮件中有备份,所以没有太大损失。 - Enders
1
@Enders,恭喜!顺便说一下,如果您更改提交历史记录,则无法保留旧的哈希值。这是其设计如此。 - Yasushi Shoji

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接