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