使用 git 将一项更改与另一项更改隔离

发布于 2024-11-28 06:59:16 字数 123 浏览 0 评论 0原文

我一直在本地主分支上开发一项新功能,该功能尚未准备好投入生产。然而,我刚刚在我的实时应用程序中发现了一个单独的错误,所以我很快在本地修复了它。但是,我想将此错误修复推送到我的远程主分支,而不推送我一直在开发的这个新功能。我该怎么做?

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

探春 2024-12-05 06:59:16

不太严肃的答案:

通过回到过去并为您的开发使用适当的分支模型。停止在生产分支上工作并开始使用功能分支。您所描述的情况正是您应该使用分支的原因:能够将您的开发工作放在一边,检查主版本,执行错误修复并返回到您的开发分支。如果忽略分支,你就忽略了 Git 的许多优点。

更严肃的答案:

更实际的是,您可以重新排序提交,将本地主控指向您想要推送的提交,推送,然后将您的开发提交作为新分支进行检查。

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

A <-- (master) bug fix, you want to push this
B <-- you don't want to push this
C <-- (origin/master)

您可以使用 git rebase -i HEAD~2 重新排序最后两次提交,如下所示(只需切换编辑器中的行顺序即可) up):

B <-- (master) you don't want to push this
A <-- bug fix
C <-- (origin/master)

记下 B 的 SHA1,您将暂时将其从 master 分支中删除。记录 SHA1 后,您可以使用 git update-ref refs/heads/master [SHA1 of A],这会导致

A <-- (master) bug fix
C <-- (origin/master)

您现在可以 git push 进行合并Aorigin/master 并将结果发送到 origin

最后,要恢复您的开发工作(提交 B),请创建一个新的开发分支(您应该首先完成),指向您的 B 提交:< code>git 分支开发 [SHA1 of B]

您的存储库现在将如下所示:

B <-- (development) you don't want to push this
A <-- (master,origin/master) bug fix
C <-- where origin/master *was* before pushing

当您准备好将该开发工作合并到 master 中时,您可以:

git checkout master
git merge development

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:

A <-- (master) bug fix, you want to push this
B <-- you don't want to push this
C <-- (origin/master)

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):

B <-- (master) you don't want to push this
A <-- bug fix
C <-- (origin/master)

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 use git update-ref refs/heads/master [SHA1 of A], which results in

A <-- (master) bug fix
C <-- (origin/master)

You can now git push to merge A into origin/master and send the results to origin.

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 your B commit: git branch development [SHA1 of B]

Your repository will now look like this:

B <-- (development) you don't want to push this
A <-- (master,origin/master) bug fix
C <-- where origin/master *was* before pushing

When you're ready to have that development work merged into master, you can:

git checkout master
git merge development
许一世地老天荒 2024-12-05 06:59:16

您得到了一些很好的答案,但有点复杂。我希望能稍微简化一下。以下假设您仅在一次提交中提交了修复,即本地 master 分支上的最后一次提交。

git branch new-feature master~1
git checkout -b bugfix
git branch -f master origin/master
git rebase --onto master new-feature

这会将新功能的工作放在名为 new-feature 的自己的分支上,将错误修复放在名为 bugfix 的自己的单独分支上,重置 master 分支以匹配您上次推送的内容,然后重新调整以从您的分支中删除新功能工作。错误修复分支。

这就是您通常希望您的分支在这一点上的看法。我是如何得到它的还不是很重要,因为将来你只需在开始开发另一个新功能之前使用 git checkout -b another-new-feature master 创建一个新分支即可或错误修复。

现在,要仅推送错误修复,只需执行以下操作:

git checkout master
git merge bugfix
git push

然后,要继续开发新功能,请执行:

git checkout new-feature

如果您想将错误修复包含在新功能分支中,请执行:

git rebase 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.

git branch new-feature master~1
git checkout -b bugfix
git branch -f master origin/master
git rebase --onto master new-feature

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:

git checkout master
git merge bugfix
git push

Then to continue working on your new feature, do:

git checkout new-feature

If you want to include your bug fix in your new-feature branch, do:

git rebase master

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 the new-feature branch.

假装爱人 2024-12-05 06:59:16

那么,您可以仅将想要提交的文件添加到暂存区域并将它们提交到您的分支上。然后创建另一个分支并将您不想提交的文件提交到其中。然后你只需推送修复后的分支即可。

当您提交时,它只会将文件添加到暂存区域中,以便您可以在一个分支上提交一部分工作,在另一个分支上提交另一部分工作。

如果您想在有未提交文件的情况下切换分支,可以将它们添加到暂存区域,签出其他分支,然后将暂存区域提交到该其他分支。

如果您对同一个文件进行了一些想要推送的更改和一些不想推送的更改,那么情况会变得更加复杂。

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.

终止放荡 2024-12-05 06:59:16

这里是一个完整的答案命令。我写了一个类似的问题。

它的基本原理是,将错误修复移动到单独的分支并将该分支与您的主分支和主题合并。不要修复步骤 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.

油焖大侠 2024-12-05 06:59:16
  1. 交互式变基并将错误修复提交移动到变更集的第一个提交
  2. 创建一个指向错误修复提交的新分支
  3. 将新的错误修复分支推送到远程主控

我今天没有正常的测试机器,所以语法来自记忆。如果可以的话,有人可以叫我出去。

不确定 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

命令可能看起来像这样:

我假设我们正在使用分支新功能。

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 中重新创建错误修复。

  [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 之后的下一次提交中看到错误修复。

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?

或者,

  1. 检查远程
  2. Cherry pick 的错误修复提交。

但这会复制本地分支中的代码,因此您需要将其从本地分支中删除并在 master 上重新建立基础。

我总是使用 gitk 来挑选,无法帮助你使用命令。

  1. Interactive rebase and move the bug fix commit to the be the first commit of the changeset
  2. Create a new branch pointing at the bug fix commit
  3. Push the new bug fix branch to remote master

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:

  [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

The commands might look something like this:

I'm going to assume we are on branch new feature.

git rebase -i origin/master

At this point you'll get a list of commits:

hash_1 feature progress: more widgets!
hash_2 feature progress: less widgets, what was I thinking?
hash_3 bug fix: fixed memory management

You'll reorder your commits:

hash_3 bug fix: fixed memory management
hash_1 feature progress: more widgets!
hash_2 feature progress: less widgets, what was I thinking?

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.

  [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?

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.

git checkout hash_3
git branch some_bug_fix
git push origin some_bug_fix:master
git checkout new_feature
git rebase origin/master

The last rebase is superfluous probably.

  [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?

Alternatively,

  1. Checkout the remote
  2. Cherry pick the bug fix commit.

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.

筱果果 2024-12-05 06:59:16

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

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


在此示例中,bar.cfoo.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

我选择“p”选项来告诉 Git 我希望选择要添加到“暂存区域”的单个“补丁” :

What now> p
           staged     unstaged path
  1:    unchanged        +1/-0 bar.c
  2:    unchanged        +1/-1 foo.c

接下来我输入 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>>

Next 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

我现在已暂存属于错误修复一部分的所有内容。所以我退出了“交互式添加”模式:

*** Commands ***
  1: status       2: update       3: revert       4: add untracked
  5: patch        6: diff         7: quit         8: help
What now> q
Bye.

记下状态。 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
#

接下来我告诉 Git 存储我的工作,但保留我添加到“暂存区域”的内容区域”(又名
“索引”):

test(master *+)$ git stash --keep-index
Saved working directory and index state WIP on master: ba84dec Adding bar.c with new "bar feature"
HEAD is now at ba84dec Adding bar.c with new "bar feature"
test(master +$)$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       modified:   foo.c
#

现在请注意,我的工作树中唯一的内容是错误修复,并且已准备好在下一次提交中提交。现在我可以在提交之前对错误修复进行任何我想做的测试。

当我对更改感到满意时,我现在可以提交错误修复:

test(master +$)$ git commit
[master 79acd00] Commit bugfix for foo.c
 1 files changed, 1 insertions(+), 1 deletions(-)

现在我弹出存储以将我在 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)

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

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 and foo.c, but only foo.c has changes related to the bugfix. First, I use git add -i to interactively add just the bugfix:

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

I select the "p" option to tell Git that I wish to select individual "patches" to be added to the "staging area":

What now> p
           staged     unstaged path
  1:    unchanged        +1/-0 bar.c
  2:    unchanged        +1/-1 foo.c

Next I type 2 to tell it that I want to select individual patches from foo.c:

Patch update>> 2
           staged     unstaged path
  1:    unchanged        +1/-0 bar.c
* 2:    unchanged        +1/-1 foo.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:

Patch update>>

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:

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

I've now staged everything that is part of the bugfix. So I quit the "interactive add" mode:

*** Commands ***
  1: status       2: update       3: revert       4: add untracked
  5: patch        6: diff         7: quit         8: help
What now> q
Bye.

Note the status. foo.c has changes added to the "staging area", but "bar.c" does not:

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
#

Next I tell Git to stash my work, but to keep what I've added to the "staging area" (a.k.a.
the "index"):

test(master *+)$ git stash --keep-index
Saved working directory and index state WIP on master: ba84dec Adding bar.c with new "bar feature"
HEAD is now at ba84dec Adding bar.c with new "bar feature"
test(master +$)$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       modified:   foo.c
#

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:

test(master +$)$ git commit
[master 79acd00] Commit bugfix for foo.c
 1 files changed, 1 insertions(+), 1 deletions(-)

Now I pop the stash to get the other work that I was doing in bar.c back into my working tree:

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)

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文