使用git将一个变更与另一个变更隔离

使用git将一个变更与另一个变更隔离,git,version-control,github,Git,Version Control,Github,我一直在为我的本地主分支开发一个新功能,该功能还没有准备好投入生产。然而,我刚刚在我的live应用程序中发现了一个单独的bug,所以我很快在本地修复了它。然而,我想把这个bug修复推到我的远程主分支上,而不推这个我一直在开发的新功能。我该怎么做呢?您可以只将要提交的文件添加到暂存区域,然后在您的分支上提交它们。然后创建另一个分支并提交您不想提交的文件。然后你只需用螺丝钉推动树枝 提交时,它只会在暂存区域中添加文件,以便您可以提交分支上的一部分工作和其他分支上的另一部分工作 如果希望在有未提交文件

我一直在为我的本地主分支开发一个新功能,该功能还没有准备好投入生产。然而,我刚刚在我的live应用程序中发现了一个单独的bug,所以我很快在本地修复了它。然而,我想把这个bug修复推到我的远程主分支上,而不推这个我一直在开发的新功能。我该怎么做呢?

您可以只将要提交的文件添加到暂存区域,然后在您的分支上提交它们。然后创建另一个分支并提交您不想提交的文件。然后你只需用螺丝钉推动树枝

提交时,它只会在暂存区域中添加文件,以便您可以提交分支上的一部分工作和其他分支上的另一部分工作

如果希望在有未提交文件的情况下切换分支,可以将它们添加到暂存区域,签出另一个分支,然后将暂存区域提交到该另一个分支

如果您在同一个文件上做了一些您想推送的更改和一些您不想推送的更改,那么它会变得更复杂

  • 交互式重新基化并将错误修复提交移动到更改集,使之成为更改集的第一个提交
  • 创建指向bug修复提交的新分支
  • 将新的bug修复分支推送到远程主机
  • 我今天没有带我的普通测试机,所以语法来自内存。如果有的话,请有人给我打电话

    不确定ascii艺术是否有效:

      [origin/master]  hash_0 blah
      [new_feature  ]  hash_1 feature progress: more widgets!
                       hash_2 feature progress: less widgets, what was I thinking?
                       hash_3 bug fix: fixed memory management
    
    这些命令可能如下所示:

    A <-- (master) bug fix, you want to push this
    B <-- you don't want to push this
    C <-- (origin/master)
    
    B <-- (development) you don't want to push this
    A <-- (master,origin/master) bug fix
    C <-- where origin/master *was* before pushing
    
    我假设我们正在开发新功能

    git rebase -i origin/master
    
    此时,您将获得一个提交列表:

    hash_1 feature progress: more widgets!
    hash_2 feature progress: less widgets, what was I thinking?
    hash_3 bug fix: fixed memory management
    
    您将重新排序您的提交:

    hash_3 bug fix: fixed memory management
    hash_1 feature progress: more widgets!
    hash_2 feature progress: less widgets, what was I thinking?
    
    如果您在这里遇到错误,那么您的错误修复取决于您的新功能更改。很难就此给出建议。在这种情况下,我通常只是在origin/master中重新创建bug修复

      [origin/master]  hash_0 blah
      [new_feature  ]  hash_3 bug fix: fixed memory management
                       hash_1 feature progress: more widgets!
                       hash_2 feature progress: less widgets, what was I thinking?
    
    我们应该按照正确的顺序,我通常会打开gitk并直观地验证它的外观是否符合我的预期。您希望在origin/master之后的下一次提交中看到bug修复

    git checkout hash_3
    git branch some_bug_fix
    git push origin some_bug_fix:master
    git checkout new_feature
    git rebase origin/master
    
    最后一次再基准可能是多余的

      [origin/master]  hash_0 blah
                       hash_3 bug fix: fixed memory management
      [new_feature  ]  hash_1 feature progress: more widgets!
                       hash_2 feature progress: less widgets, what was I thinking?
    
    或者

  • 签出遥控器
  • Cherry选择bug修复提交
  • 这将在本地分支中复制代码,因此您需要将其从本地分支中删除,并在master上重新设置基址

    我总是用gitk来挑选,不能帮你做命令。

    不太严肃的回答: 通过回到过去,并为您的开发使用适当的分支模型。停止在生产分支上工作,并开始使用功能分支。您描述的情况正是您应该使用分支的原因:将开发工作放在一边、签出master、执行错误修复并返回到您的开发分支的能力。通过忽略分支,你就忽略了很多让Git很棒的东西

    更严肃的回答: 更实际地说,您可以对提交重新排序,将本地主机指向要推送的主机,然后将开发提交作为一个新分支签出

    如果您的提交历史记录如下所示:

    A <-- (master) bug fix, you want to push this
    B <-- you don't want to push this
    C <-- (origin/master)
    
    B <-- (development) you don't want to push this
    A <-- (master,origin/master) bug fix
    C <-- where origin/master *was* before pushing
    
    记下
    B
    的SHA1,您将临时将其从主分支中删除。一旦记录了SHA1,就可以使用git update ref refs/heads/master[SHA1 of A],这会导致

    A <-- (master) bug fix
    C <-- (origin/master)
    
    当您准备将开发工作合并到master中时,您可以:

    git checkout master
    git merge development
    
    是一个贯穿命令的答案。我写这封信是为了回答一个类似的问题

    它的基础是,将bug修复移到一个单独的分支,并将该分支与主分支和主题合并。不要在步骤4中修复更改,而是使用git cherry pick BugFixsa从功能分支中删除提交。

    使用git的“交互式添加”功能仅将错误修复添加到“暂存区域”。然后,您可以隐藏其余的更改,测试错误修复以确保其工作,然后自行提交

    下面是一个示例演练。一开始它可能看起来很长很复杂,但实际上很简单。一旦你这样做了几次,它将成为你的第二天性,你可能会发现自己经常使用这种技巧


    在本例中,
    bar.c
    foo.c
    都有更改,但只有
    foo.c
    有与错误修复相关的更改。首先,我使用
    git add-I
    以交互方式添加错误修复:

    test(master *)$ git add -i
               staged     unstaged path
      1:    unchanged        +1/-0 bar.c
      2:    unchanged        +1/-1 foo.c
    
    *** Commands ***
      1: status       2: update       3: revert       4: add untracked
      5: patch        6: diff         7: quit         8: help
    
    test(master +$)$ git commit
    [master 79acd00] Commit bugfix for foo.c
     1 files changed, 1 insertions(+), 1 deletions(-)
    
    我选择“p”选项,告诉Git我希望选择要添加到“暂存区”的单个“补丁”:

    接下来,我键入
    2
    ,告诉它我想从
    foo.c
    中选择单个补丁:

    Patch update>> 2
               staged     unstaged path
      1:    unchanged        +1/-0 bar.c
    * 2:    unchanged        +1/-1 foo.c
    
    由于
    foo.c
    是唯一一个包含我要添加到“暂存区域”的修补程序的文件,现在我已完成文件选择,因此我只需在提示下按enter键:

    Patch update>>
    
    接下来Git向我展示了“foo.c”中的各个补丁,并询问我是否愿意将它们添加到索引中。在本例中,只有一个更改,因此我将其分阶段进行:

    diff --git a/foo.c b/foo.c
    index 7bc741e..ec7ddfc 100644
    --- a/foo.c
    +++ b/foo.c
    @@ -1 +1 @@
    -Here is foo.c; it has a bug.
    +Here is foo.c.
    Stage this hunk [y,n,q,a,d,/,e,?]? y
    
    我现在已经准备好了所有的bug修复。因此,我退出了“交互式添加”模式:

    注意状态<代码>foo.c已将更改添加到“暂存区”,但“bar.c”没有:

    test(master *+)$ git status
    # On branch master
    # Changes to be committed:
    #   (use "git reset HEAD <file>..." to unstage)
    #
    #       modified:   foo.c
    #
    # Changes not staged for commit:
    #   (use "git add <file>..." to update what will be committed)
    #   (use "git checkout -- <file>..." to discard changes in working directory)
    #
    #       modified:   bar.c
    #
    
    现在,我弹出隐藏,将我在
    bar.c
    中所做的其他工作返回到我的工作树中:

    test(master $)$ git stash pop
    # On branch master
    # Changes not staged for commit:
    #   (use "git add <file>..." to update what will be committed)
    #   (use "git checkout -- <file>..." to discard changes in working directory)
    #
    #       modified:   bar.c
    #
    no changes added to commit (use "git add" and/or "git commit -a")
    Dropped refs/stash@{0} (d306d098a272335ed31c14f07cf57e62ffc13151)
    
    test(master$)$git stash pop
    #论分行行长
    #未为提交而暂存的更改:
    #(使用“git add…”更新将提交的内容)
    #(使用“git签出--…”放弃工作目录中的更改)
    #
    #修改:bar.c
    #
    未向提交添加任何更改(使用“git add”和/或“git commit-a”)
    丢弃的引用/隐藏{0}(d306d098a272335ed31c14f07cf57e62ffc13151)
    

    我做完了。我现在可以推送到远程存储库,它将得到错误修复,而我的其余工作仍在我的工作树中,不会被推送。

    您得到了一些不错的答案,但有点复杂。我希望能简化我的工作
    test(master +$)$ git commit
    [master 79acd00] Commit bugfix for foo.c
     1 files changed, 1 insertions(+), 1 deletions(-)
    
    test(master $)$ git stash pop
    # On branch master
    # Changes not staged for commit:
    #   (use "git add <file>..." to update what will be committed)
    #   (use "git checkout -- <file>..." to discard changes in working directory)
    #
    #       modified:   bar.c
    #
    no changes added to commit (use "git add" and/or "git commit -a")
    Dropped refs/stash@{0} (d306d098a272335ed31c14f07cf57e62ffc13151)
    
    git branch new-feature master~1
    git checkout -b bugfix
    git branch -f master origin/master
    git rebase --onto master new-feature
    
    git checkout master
    git merge bugfix
    git push
    
    git checkout new-feature
    
    git rebase master