Git 如何在不覆盖历史记录的情况下将更改从主分支分离到另一个分支?

Git 如何在不覆盖历史记录的情况下将更改从主分支分离到另一个分支?,git,branching-and-merging,Git,Branching And Merging,最近,我开始为我的项目实现新的实验特性。不幸的是,我在启动之前忘记了分支,并将共享存储库服务器上的几个提交推送到了主分支中。由于其他人可能已经签出了我的提交,我希望避免覆盖服务器上的历史记录 由于我的变化,目前的主人是不稳定的,这也是不好的。因此,我想还原对master所做的更改,创建一个单独的分支,该分支将包含这些更改,并且在它们足够稳定后仍然能够将它们重新引入(合并)到master。我在编写问题时已经找到了问题的解决方案。我描述这个解决方案是希望它对将来的人有用。对于所有的更改,我使用的是g

最近,我开始为我的项目实现新的实验特性。不幸的是,我在启动之前忘记了分支,并将共享存储库服务器上的几个提交推送到了主分支中。由于其他人可能已经签出了我的提交,我希望避免覆盖服务器上的历史记录


由于我的变化,目前的主人是不稳定的,这也是不好的。因此,我想还原对master所做的更改,创建一个单独的分支,该分支将包含这些更改,并且在它们足够稳定后仍然能够将它们重新引入(合并)到master。

我在编写问题时已经找到了问题的解决方案。我描述这个解决方案是希望它对将来的人有用。对于所有的更改,我使用的是gitk和GitGUI。我建议您也这样做,因为这比使用命令行容易得多,您将对正在发生的事情有一个直观的了解。以下是我采取的步骤:

  • 执行硬重置到最后一次稳定提交。这将从索引和工作目录中删除所有不稳定的更改
  • 对共享服务器上的最后一次提交执行混合重置。这会将索引重置为共享服务器上的当前提交,但会使工作目录保持稳定状态
  • 提交工作目录中的所有更改。然后,您将拥有commit,它将取消主机上所有不稳定的更改
  • 在此提交时创建实验分支并将其签出。此时,实验分支将没有实验代码,所以让我们解决这个问题
  • Cherry挑选所有应该进入实验分支的提交。这样,您将在实验分支上重新引入这些更改。确保不要挑剔我们刚刚做出的最后一个承诺。如果使用gitk,它将显示一条警告,表明您正在尝试挑选已经在分支中的提交-忽略这些警告并继续
  • 中提琴。你完了

  • 为了安全起见,我建议您在本地进行所有更改,只有在完成并确保所有更改都正确后才推送它们。然后,如果出现错误,您可以始终删除存储库并从共享服务器中再次克隆它。

    此答案使用命令行工具,并采用不同的方法来管理分支。它可能比使用不同口味的多次重置更容易混淆

    Git 1.7.2及更高版本中的
    revert
    命令可以在一个命令中还原多个提交:

    git revert last-stable..
    
    这将在
    上次稳定
    之前(包括当前头部提交)为每个提交创建还原提交(按相反顺序)。如果您正在处理许多不需要的提交,那么您可能希望在一次提交中恢复所有这些提交:

    git revert -n last-stable..
    git commit # edit the message to explain that you are reverting multiple commits
    

    下面是如何将其与一些其他命令结合起来,在revert commit之上重新建立您的实验分支:
    (假设共享分支名为
    主分支


    我很困惑:你的问题明确地说你想避免覆盖服务器上的历史记录,然后你从硬重置开始,继续写不同的历史记录…@Jefromi:第二步(混合重置)防止它实际重写任何历史记录(它指向最后一次共享提交,因此下一步的提交将建立在共享历史的基础上)。另一种方法是双重签出:
    git checkout master&&git checkout last stable--.
    (第一个位置开始构建共享历史,第二个位置将索引和工作树恢复到
    last stable
    的内容)。另请参见和优秀答案。
    # Make sure we have the latest shared master
    git checkout master
    git pull
    
    # Mark the last experimental commit
    git branch experimental
    
    # Revert the experimental commits
    git revert last-stable.. # optionally use -n and manually commit batched reverts
    
    # Replay the experimental commits on top of the reverted commits
    git checkout -B experimental master
    git cherry-pick last-stable..experimental@{1}