简体   繁体   English

将提交从一个分支移动到另一个分支作为更改的步骤

[英]Steps to move a commit from one branch to another as changes

Normally if I make changes in a branch and realize I meant to do it in a different branch, then I can simply stash the changes and then checkout the branch I want.通常,如果我在分支中进行更改并意识到我打算在不同的分支中进行更改,那么我可以简单地存储更改,然后签出我想要的分支。

How do I effectively accomplish the same thing if I've already committed locally (but not pushed to remote)?如果我已经在本地提交(但没有推送到远程),我如何有效地完成同样的事情?

I want my local branch to be as though I never made any changes... in particular I don't want to have to push two commits (one with the changes, and one that reverts the changes).我希望我的本地分支就像我从未做过任何更改一样......特别是我不想推送两个提交(一个包含更改,一个恢复更改)。 I just want the commit to go away as if it never happened.我只希望对 go 的提交消失,就好像它从未发生过一样。 And when I checkout the branch I want, I want my changes to be there... or I want to be able to restore them (as changes, but not as a commit, obviously).当我签出我想要的分支时,我希望我的更改在那里......或者我希望能够恢复它们(作为更改,但不是作为提交,显然)。

I've done some searching and the answers I've found primarily focus on the first case I mentioned where changes weren't committed.我进行了一些搜索,我发现的答案主要集中在我提到的第一个没有提交更改的案例上。 It's very possible I've run across the exact answer I need, but didn't realize it because I wasn't 100% if the scenario was the same as mine.我很可能已经遇到了我需要的确切答案,但没有意识到,因为如果场景与我的情况相同,我就不是 100%。 So obviously I'm a bit new to git and I'm sure this has got to be a duplicate question, but maybe I am just having trouble identifying which existing questions are the duplicates with confidence.所以显然我对 git 有点陌生,我确信这一定是一个重复的问题,但也许我只是无法确定哪些现有问题是重复的问题。

Also I tagged vs 2017 and 2019 because I use both and welcome any answers that explain how to do this through the IDE in either of those versions in additions to how to accomplish this in a shell.我还标记了 vs 2017 和 2019,因为我同时使用并欢迎任何解释如何通过 IDE 在这两个版本中执行此操作的答案,以及如何在 shell 中完成此操作。

EDIT: Just thought I should add that this particular commit is the only one.编辑:只是想我应该补充一点,这个特定的提交是唯一的。 Though I am interested to hear solutions for both scenarios (this one, and one where I had other valid commits).虽然我很想听听这两种情况的解决方案(这个,还有一个我有其他有效提交的地方)。

Things to keep in mind:要记住的事情:

  • Git traffics in commits. Git 提交中的流量。 Not changes.不改变。 Not files.不是文件。 Commits.提交。

  • A branch is just a label for one commit.一个分支只是一个提交的 label。

  • You can move a branch, attaching it to any commit you like, with git reset .您可以使用git reset移动分支,将其附加到您喜欢的任何提交。

Let's start with a two-branch situation:让我们从两个分支的情况开始:

% git log --oneline --all --graph
* 102fa13 (br) z
| * 7e0ddf5 (HEAD -> master) d
| * 3a460a5 c
|/  
* e7547cb b
* 0bcb421 a

So I regret that c and d were made on master ;所以我很遗憾cd是在master上制作的; I wish they had been on some other branch.我希望他们在其他分支上。 So I can think of two main scenarios here.所以我可以在这里想到两个主要场景。 Does that other branch already exist or not?那个其他分支是否已经存在?

If not, then simply make the new branch here (where master is now) and slide master back down to before c :如果没有,那么只需在此处创建新分支(现在master所在的位置)并将master滑回c之前:

% git branch newbranch
% git reset --hard e7547cb

Result:结果:

% git log --oneline --all --graph              
* 102fa13 (br) z
| * 7e0ddf5 (newbranch) d
| * 3a460a5 c
|/  
* e7547cb (HEAD -> master) b
* 0bcb421 a

That's the easy case.这是简单的情况。 The harder case is that the other branch already exists: let's say it's br in the first graph above.更难的情况是另一个分支已经存在:假设它在上面的第一张图中是br Then rebase the c and d commits onto br .然后cd提交到br上。 After that, reset br up to where master is now, and then slide master back down to where it was before c :之后,将br重置到master现在的位置,然后将master滑回c之前的位置:

% git rebase --onto br e7547cb master
% git switch br
% git reset --hard master
% git switch master
% git reset --hard e7547cb

Result:结果:

% git log --oneline --all --graph
* f9ff4a0 (br) d
* 5c43690 c
* 102fa13 z
* e7547cb (HEAD -> master) b
* 0bcb421 a

Note that the d and c commits here are copies (they have new unique ids);请注意,此处的dc提交是副本(它们具有新的唯一 ID); that's inevitable when you move commits around, as commits themselves are immutable.当您移动提交时,这是不可避免的,因为提交本身是不可变的。

You may cherry-pick your commit on the current branch to the other branch, then nuke the commit on the current branch.您可以将当前分支上的提交挑选到另一个分支,然后核对当前分支上的提交。

# from current branch, get SHA-1 of latest commit (e.g. ABCD1234)
git log
git checkout other_branch
git cherry-pick ABCD1234

# now return to original branch and nuke commit
git checkout current_branch
git reset --hard HEAD~1

Notr that this answer strongly relies on that you haven't yet pushed the current branch with the mistaken commit.请注意,此答案强烈依赖于您尚未使用错误提交推送当前分支。 If you have done this already, the answer would need to change.如果你已经这样做了,答案需要改变。

You can reduce the second case (where have made the commit) to the first case (where you have not yet made a commit):您可以将第二种情况(已提交)减少到第一种情况(您尚未提交):

Undo the commit, but keep the changes:撤消提交,但保留更改:

git reset HEAD^

At this point, you have removed the unwanted commit and restored the current branch to the state without the commit.此时,您已删除不需要的提交并将当前分支恢复到没有提交的 state。

Also, you have now uncommitted changes, and you are on the "wrong" branch, ie, you have now "the first case".此外,您现在有未提交的更改,并且您在“错误”分支上,即您现在有“第一个案例”。

Then transfer the changes to the other branch:然后将更改转移到另一个分支:

git checkout -m other-branch

The option -m does the magic.选项-m具有魔力。 At this point, you have uncommitted changes that you can commit.此时,您有可以提交的未提交更改。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM