使用 git 将一项更改与另一项更改隔离
我一直在本地主分支上开发一项新功能,该功能尚未准备好投入生产。然而,我刚刚在我的实时应用程序中发现了一个单独的错误,所以我很快在本地修复了它。但是,我想将此错误修复推送到我的远程主分支,而不推送我一直在开发的这个新功能。我该怎么做?
I've been working on my local master branch on a new feature that is not yet ready to be pushed live for production. However, I just discovered a separate bug in my live app, and so I quickly fixed it locally. However, I want to push this bug fix to my remote master branch without pushing this new feature I've been working on. How might I do this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
不太严肃的答案:
通过回到过去并为您的开发使用适当的分支模型。停止在生产分支上工作并开始使用功能分支。您所描述的情况正是您应该使用分支的原因:能够将您的开发工作放在一边,检查主版本,执行错误修复并返回到您的开发分支。如果忽略分支,你就忽略了 Git 的许多优点。
更严肃的答案:
更实际的是,您可以重新排序提交,将本地主控指向您想要推送的提交,推送,然后将您的开发提交作为新分支进行检查。
如果您的提交历史记录如下所示:
您可以使用 git rebase -i HEAD~2 重新排序最后两次提交,如下所示(只需切换编辑器中的行顺序即可) up):
记下
B
的 SHA1,您将暂时将其从 master 分支中删除。记录 SHA1 后,您可以使用git update-ref refs/heads/master [SHA1 of A]
,这会导致您现在可以
git push
进行合并A
到origin/master
并将结果发送到origin
。最后,要恢复您的开发工作(提交
B
),请创建一个新的开发分支(您应该首先完成),指向您的B
提交:< code>git 分支开发 [SHA1 of B]您的存储库现在将如下所示:
当您准备好将该开发工作合并到 master 中时,您可以:
Less serious answer:
By going back in time and using a proper branch model for your development. Stop working on your production branch and start using feature branches. The situation you describe is exactly why you should be using branches: The ability to set your development work aside, check out master, perform bug fixes and return to your development branch. By ignoring branching, you're ignoring a lot of what makes Git awesome.
More serious answer:
More practically, you can reorder the commits, point your local master to the one you want to push, push, and then check out your development commit as a new branch.
If your commit history looks like this:
You can use
git rebase -i HEAD~2
to re-order the last two commits to look like this (just switch the order of the lines in the editor that comes up):Make a note of the SHA1 of
B
, you're about to temporarily cut it out of your master branch. Once you've recorded the SHA1, you can usegit update-ref refs/heads/master [SHA1 of A]
, which results inYou can now
git push
to mergeA
intoorigin/master
and send the results toorigin
.Lastly, to get your development work (commit
B
) back, create a new development branch (which you should have done in the first place) pointing at yourB
commit:git branch development [SHA1 of B]
Your repository will now look like this:
When you're ready to have that development work merged into master, you can:
您得到了一些很好的答案,但有点复杂。我希望能稍微简化一下。以下假设您仅在一次提交中提交了修复,即本地
master
分支上的最后一次提交。这会将新功能的工作放在名为 new-feature 的自己的分支上,将错误修复放在名为 bugfix 的自己的单独分支上,重置 master 分支以匹配您上次推送的内容,然后重新调整以从您的分支中删除新功能工作。错误修复分支。
这就是您通常希望您的分支在这一点上的看法。我是如何得到它的还不是很重要,因为将来你只需在开始开发另一个新功能之前使用 git checkout -b another-new-feature master 创建一个新分支即可或错误修复。
现在,要仅推送错误修复,只需执行以下操作:
然后,要继续开发新功能,请执行:
如果您想将错误修复包含在新功能分支中,请执行:
否则,它将在您执行新功能之前合并到其中下一次推送。当您准备好推送新功能时,只需执行与
bugfix
分支相同的合并操作,但与new-feature
分支合并即可。You got some answers that are good, but a little complex. I'm hoping to simplify it a little. The following assumes you committed your fix in only one commit, the last one on your local
master
branch.This puts the work on your new feature on its own branch called new-feature, puts your bug fix on its own separate branch called bugfix, resets your master branch to match what you last pushed, then rebases to remove the new feature work from your bug fix branch.
This is how you normally would want your branches to look at this point. How I got it there isn't terribly important to understand yet, because in the future you just create a new branch with
git checkout -b another-new-feature master
before you start work on another new feature or bug fix.Now, to push your bugfix only, just do:
Then to continue working on your new feature, do:
If you want to include your bug fix in your new-feature branch, do:
Otherwise, it will be merged in before you do your next push. When you're ready to push your new feature, just do the same merge you did for the
bugfix
branch, but with thenew-feature
branch.那么,您可以仅将想要提交的文件添加到暂存区域并将它们提交到您的分支上。然后创建另一个分支并将您不想提交的文件提交到其中。然后你只需推送修复后的分支即可。
当您提交时,它只会将文件添加到暂存区域中,以便您可以在一个分支上提交一部分工作,在另一个分支上提交另一部分工作。
如果您想在有未提交文件的情况下切换分支,可以将它们添加到暂存区域,签出其他分支,然后将暂存区域提交到该其他分支。
如果您对同一个文件进行了一些想要推送的更改和一些不想推送的更改,那么情况会变得更加复杂。
Well you can add only the files you want to the commit to the staging area and commit them on your branch. Then create an other branch and commit the files you dont want to commit to it. Then you just push the branch with the fix.
When you commit, it only adds the files in your staging area so you can commit a part of your work on a branch and an other part of your work on an other branch.
If you want to switch branch while having non-commited files, you can add them to your staging area, checkout an other branch and then commit your staging area to that other branch.
If you have made some changes you want to push and some change you dont want to push on the same file then it get more complicated.
这里是一个完整的答案命令。我写了一个类似的问题。
它的基本原理是,将错误修复移动到单独的分支并将该分支与您的主分支和主题合并。不要修复步骤 4 中的更改,而是使用 gitcherry-pick bugFixSHA 从功能分支中删除提交。
Here is an answer that walks through the commands. I wrote it to a similar question.
The basics of it are, moving your bug fix to a separate branch and merging that branch in with your master and topic. Instead of fixing the changes in step 4, use
git cherry-pick bugFixSHA
than remove the commit from your feature branch.我今天没有正常的测试机器,所以语法来自记忆。如果可以的话,有人可以叫我出去。
不确定 ascii 艺术是否会起作用:
命令可能看起来像这样:
我假设我们正在使用分支新功能。
此时,您将获得提交列表:
您将重新排序您的提交:
如果您在此处遇到错误,那么您的错误修复取决于您的新功能更改。很难就此给出建议。通常在这种情况下我只是在 origin/master 中重新创建错误修复。
我们应该按正确的顺序,我通常打开 gitk 并目视验证它看起来是否符合我的预期。您希望在 origin/master 之后的下一次提交中看到错误修复。
最后的变基可能是多余的。
或者,
但这会复制本地分支中的代码,因此您需要将其从本地分支中删除并在 master 上重新建立基础。
我总是使用 gitk 来挑选,无法帮助你使用命令。
I don't have my normal test machine with me today, so syntax is from memory. Someone can call me out if so, please.
Not sure if the ascii art will work:
The commands might look something like this:
I'm going to assume we are on branch new feature.
At this point you'll get a list of commits:
You'll reorder your commits:
If you get errors here, then your bug fix depends on your new feature changes. Hard to give advice on that. Usually I just recreate the bug fix in origin/master in that case.
We should be in the correct order, I usually open up gitk and visually verify it looks how I expect. You expect to see your bug fix be the next commit after origin/master.
The last rebase is superfluous probably.
Alternatively,
This will duplicate the code in your local branch though, so you'd need to drop it from your local branch and rebase on master.
I always use gitk to cherry pick, can't help you with commands.
使用 Git 的“交互式添加”功能仅将错误修复添加到“暂存区域”。然后,您可以隐藏其余的更改,测试错误修复以确保其有效,然后自行提交。
下面是一个示例演练。乍一看,它可能看起来又长又复杂,但实际上很简单。一旦你这样做了几次,它就会成为你的第二天性,你可能会发现自己经常使用这种技术。
在此示例中,
bar.c
和foo.c
均发生了更改,但只有foo.c
发生了与错误修复相关的更改。首先,我使用 git add -i 以交互方式仅添加错误修复:我选择“p”选项来告诉 Git 我希望选择要添加到“暂存区域”的单个“补丁” :
接下来我输入
2
告诉它我想从foo.c
中选择单个补丁:因为
foo.c
是唯一一个文件现在有我想添加到“暂存区域”的补丁我已完成文件选择,因此只需在提示符下按 Enter 键即可:Next Git 会向我显示“foo.c”中的各个补丁,并询问我是否要将它们添加到索引中。在此示例中,只有一项更改,因此我将其暂存:
我现在已暂存属于错误修复一部分的所有内容。所以我退出了“交互式添加”模式:
记下状态。
foo.c
已将更改添加到“暂存区域”,但“bar.c”没有:接下来我告诉 Git 存储我的工作,但保留我添加到“暂存区域”的内容区域”(又名
“索引”):
现在请注意,我的工作树中唯一的内容是错误修复,并且已准备好在下一次提交中提交。现在我可以在提交之前对错误修复进行任何我想做的测试。
当我对更改感到满意时,我现在可以提交错误修复:
现在我弹出存储以将我在
bar.c
中所做的其他工作放回到我的工作树中:然后我'我完成了。我现在可以推送到远程存储库,它将获得错误修复,而我的其余工作仍在我的工作树中并且不会被推送。
Use Git's "interactive add" feature to add only the bugfix to the "staging area". You can then stash away the rest of your changes, test the bugfix to make sure it works, and then commit it by itself.
Below is an example walkthrough. At first it may seem long and complicated, but it's actually quite easy. Once you've done this a couple of times it will become second-nature and you're likely to find yourself using this technique quite often.
In this example there are changes to both
bar.c
andfoo.c
, but onlyfoo.c
has changes related to the bugfix. First, I usegit add -i
to interactively add just the bugfix:I select the "p" option to tell Git that I wish to select individual "patches" to be added to the "staging area":
Next I type
2
to tell it that I want to select individual patches fromfoo.c
:Since
foo.c
is the only file that has patches that I want to add to the "staging area", now I'm finished selecting files so I just press enter at the prompt:Next Git shows me the individual patches from "foo.c" and asks if I'd like to add them to the index. In this example, there is only one change so I stage it:
I've now staged everything that is part of the bugfix. So I quit the "interactive add" mode:
Note the status.
foo.c
has changes added to the "staging area", but "bar.c" does not:Next I tell Git to stash my work, but to keep what I've added to the "staging area" (a.k.a.
the "index"):
Now notice that the only thing in my work tree is the bugfix, and it's ready to be committed in the next commit. Now I can do whatever testing I'd like to do on the bugfix before I commit it.
When I'm satisfied with my changes, I can now commit the bugfix:
Now I pop the stash to get the other work that I was doing in
bar.c
back into my working tree:And I'm done. I can now push to the remote repository and it will get the bugfix, while the rest of my work is still in my work tree and does not get pushed.