停止在git中使用一系列提交

以下是发生的事情:

  • 写了代码
  • 提交(提交:a)
  • 代码工作。 有很多欢乐。
  • 决定添加功能。
  • 编写了更多的代码,并创建了提交b,c,d,e和f。 这些被推到了主人的回购。
  • 意识到这不是最好的办法,我们需要恢复提交一个,所以,我们做了git checkout a并做了一些改变,这些改动都起作用。
  • 现在,我们需要提交代码来掌握,有效地删除,忽略或跳过提交bf。

    我怎么告诉git:“是的,我知道我回去提交一个,然后做了修改,我不想再提交任何提交b,c,d,e和f的东西了,只需要提交代码就可以了就像我现在拥有它。“?


    如果你把所有使用过你的推主​​的人都搞砸了,那么就使用Mureinik的建议,只是为了git push --force origin

    但是,如果您有其他使用主分支的人,并且希望他们不要在睡梦中谋杀你,那么:

    首先,创建一个新的分支。 我们称之为“temp_work”:

    git checkout -b temp_work
    

    这将保持您当前的提交。

    然后,结帐主人:

    git checkout master
    

    恢复提交b,c,d,e和f:

    git revert f e d c b
    

    (这是以相反的顺序来避免潜在的冲突。最先恢复最新的提交应该给你冲突的可能性最低。)

    您将得到一个编辑器屏幕,以便每次提交恢复。

    最后,将temp_work合并到master中:

    git merge temp_work
    

    您现在可以删除temp_work分支:

    git branch -d temp_work
    

    但是,下一次,避免检查旧的提交并在那里进行更改。 恢复您不希望的提交,然后继续正常,因为它可以节省一些工作量。 但否则,仍然没有大问题。


    有多种方式可以做到这一点。 你应该使用哪一个取决于(a)你希望历史的样子,以及可能(b)“历史重写”的成本是否合理;(c)你对(a)或(b)的回答是对你更重要。 所以让我们看看一些选项...

    无论你做了什么,你都可能想要开始提交新的更改。 这确保了不会有太多的摆弄会让你失去它们。

    git checkout -b temp
    git commit
    

    现在这些新的变化变成了G ,而你已经变成了G

    A -- B -- C -- D -- E -- F <--(master)(origin/master)
     
      G <--(temp)
    

    完成后,您将删除temp ,并且如果G不是实际解决方案状态的一部分,那么它最终会被清理干净,因此将第一步作为安全网络没有任何坏处。

    现在,如果你知道你永远也不会在乎B通过F一遍,然后用干净的结果,最简单的解决方案是简单移动masterG 。 这是历史重写,因为它从参考历史记录中删除提交。 在进行历史重写时,必须与使用回购的其他人协调/可能在“已删除”提交处于其历史记录中时提取了参考。 事情会让历史重写更加难以执行:

  • 其他工作已经完成“在F之上”
  • 很多开发人员使用回购
  • 一些使用回购的开发人员进行有限的交流,可能不会立即意识到发生了什么事情
  • 如果你有任何这些条件,你可能想要解决一个不同的解决方案。 历史重写的理想情况是,您可以协调所有回购用户

  • 推送所有更改
  • 丢弃所有本地回购
  • 执行重写
  • 每个人都重新克隆
  • 如果你决定重写历史是正确的事情:


    首先将指向F任何参考(例如上例中的master )移至G

    git checkout temp
    git branch -f master
    

    如果其他分支已经基于F ,则需要重新分配给G 例如,如果你有

    A -- B -- C -- D -- E -- F <--(origin/master)
                             
      G <--(temp)(master)      H <--(feature_b)
    

    那么你可以说

    git rebase --onto temp origin/master feature_b
    

    生产

    A -- B -- C -- D -- E -- F <--(origin/master)
     
      G <--(temp)(master)
       
        H' <--(feature_b)
    

    如果你有基于BDE (但不是F )的工作,那可能会更具挑战性,尽管重组也可能是好的。

    最后,你“推动”你移动或重新设计的任何分支。 例如

    git checkout master
    git push -f
    

    此时,所有其他用户需要重新同步。 如果像我上面提到的那样,每个人都扔掉了他们的本地回购,他们可以重新克隆,并且他们恢复同步。 否则,根据您更换的任何提交进行的任何本地更改都需要重新分配; 他们的参考文献必须更新。 有关更多详细信息,请参阅git rebase文档中的“从上游rebase”恢复。

    请注意,如果所有这些听起来都不错,除了要将原始提交BF “保留在旁边”以备将来参考,那么在移动上述过程中的master之前,您可以标记F

    git checkout master
    git tag old_master
    

    (事实上​​,你可以在移动master之后做到这一点,但是在那个时候找到F 。)


    如果历史重写对您的情况不利,那么BF必须留在历史中。 然后,您可以添加一个或多个提交以通过F “撤消” B并应用G 如果没有大量已经基于F的分支,这仍然是最简单的。 在最简单的情况下,你可以

    git checkout master
    git revert HEAD~4..HEAD
    git rebase master temp
    git checkout master
    git merge temp
    

    给你类似的东西

    A -- B -- C -- D -- E -- F -- ~F -- ~E -- ~D -- ~C -- ~B -- G' <--(master)
    

    如果你想直接从F跳转到G' (没有显式的提交来恢复更改),你可以改为将G重新保存到F (参见git filter-branch docs)。 或另一种方式来做同样的事情

    git checkout temp
    git reset --soft master
    git commit
    git checkout master
    git merge temp
    

    有了这些解决方案, BF仍然会出现在历史记录中(例如git log )。 在回购回购的基础上,如果开发人员想隐藏它,他们可以提供A作为G'之前的提交的“替代”(即G'^ )。 有关详细信息,请参阅git replace文档。

    另外一个选择是将G合并到master (大概在恢复提交之后)。 这产生类似的东西

    A -- B -- C -- D -- E -- F -- ~FEDCB -- M <--(master)
                                          /
      ---------------- G ------------------
    

    这是可以的,但更难以用替代品“覆盖”历史。 请注意,在这种情况下,您不应该将恢复提交(S)与合并提交结合起来,因为这会产生“恶意合并”并可能导致问题。

    链接地址: http://www.djcxy.com/p/49843.html

    上一篇: Stop using a series of commits in git

    下一篇: Best way to recover after creating branch from wrong branch and merging