我刚刚向错误的分支做出了完美的承诺。 我如何撤消在我的主分支中的最后一次提交,然后采取这些相同的更改,并将它们放入我的升级分支?


当前回答

如果你想要应用你的更改的分支已经存在(例如分支开发),遵循下面fotanus提供的说明,那么:

git checkout develop
git rebase develop my_feature # applies changes to correct branch
git checkout develop # 'cuz rebasing will leave you on my_feature
git merge develop my_feature # will be a fast-forward
git branch -d my_feature

显然,如果你愿意,你可以使用tempbranch或任何其他分支名称来代替my_feature。

同样,如果适用的话,将stash弹出(apply)延迟到合并目标分支之后。

其他回答

如果你想要应用你的更改的分支已经存在(例如分支开发),遵循下面fotanus提供的说明,那么:

git checkout develop
git rebase develop my_feature # applies changes to correct branch
git checkout develop # 'cuz rebasing will leave you on my_feature
git merge develop my_feature # will be a fast-forward
git branch -d my_feature

显然,如果你愿意,你可以使用tempbranch或任何其他分支名称来代替my_feature。

同样,如果适用的话,将stash弹出(apply)延迟到合并目标分支之后。

我最近做了同样的事情,当我应该提交给其他分支时,我不小心提交了一个更改给master。但我没有推动任何东西。

如果你只是提交了错误的分支,并且从那以后没有改变任何东西,也没有推送到回购,那么你可以执行以下操作:

// rewind master to point to the commit just before your most recent commit.
// this takes all changes in your most recent commit, and turns them into unstaged changes. 
git reset HEAD~1 

// temporarily save your unstaged changes as a commit that's not attached to any branch using git stash
// all temporary commits created with git stash are put into a stack of temporary commits.
git stash

// create other-branch (if the other branch doesn't already exist)
git branch other-branch

// checkout the other branch you should have committed to.
git checkout other-branch

// take the temporary commit you created, and apply all of those changes to the new branch. 
//This also deletes the temporary commit from the stack of temp commits.
git stash pop

// add the changes you want with git add...

// re-commit your changes onto other-branch
git commit -m "some message..."

注意:在上面的例子中,我用git重置HEAD~1来重卷1提交。但如果你想倒带n次提交,你可以做git reset HEAD~n。

同样,如果你最终提交了错误的分支,并且在意识到你提交了错误的分支之前写了更多的代码,那么你可以使用git stash来保存你正在进行的工作:

// save the not-ready-to-commit work you're in the middle of
git stash 

// rewind n commits
git reset HEAD~n 

// stash the committed changes as a single temp commit onto the stack. 
git stash 

// create other-branch (if it doesn't already exist)
git branch other-branch

// checkout the other branch you should have committed to.
git checkout other-branch

// apply all the committed changes to the new branch
git stash pop

// add the changes you want with git add...

// re-commit your changes onto the new branch as a single commit.
git commit -m "some message..."

// pop the changes you were in the middle of and continue coding
git stash pop

注意:我使用这个网站作为参考 https://www.clearvision-cm.com/blog/what-to-do-when-you-commit-to-the-wrong-git-branch/

在常见的情况下,你在提交之前忘记从master切换到你的特性分支:

git checkout -B feature
git branch -f master origin/master

将origin/master替换为您希望主分支指向的提交。例如,如果您希望它指向HEAD后面的3个提交,则使用HEAD~3,如果您希望它指向带有该哈希的提交,则使用a1b2c3d。

其思想是在当前提交上重新创建特性分支并切换到它。然后使master分支指向与origin/master相同的提交。

一般情况下

在一般情况下,你想在你的特性分支上重放在master上完成的提交,如下图所示:

A---B---C---D  $old_master                   A---B---C---D  master
    |        \                                   |        \
    |         G---H---I  master <- HEAD  =>      |         G---H---I
    |                                            | 
    `-E---F  feature                             `-E---F---G'--H'--I' feature <- HEAD

然后使用下面的命令在你的特性分支上选择你在master上做的提交。将$old_master替换为提交主机在进行更改之前所指向的哈希值。

git checkout feature
git cherry-pick $old_master..master
git branch -f master $old_master

如果需要,使用git stash -include-untracked隐藏你的本地更改,然后使用git stash pop取消隐藏。

不重写历史

除了选择特性分支上的更改之外,您还需要git恢复这些更改,而不是将主分支重置到过去。

git checkout feature
git cherry-pick $old_master..master
git checkout master
git revert $old_master..
git checkout feature

确保git不会将你的提交合并到特性中。如果你试图将你的特征分支合并回主分支,这些变化将被忽略,因为我们刚刚恢复了它们。

下面是结果的样子,rG, rH和rI分别是G, H和I的还原提交:

A---B---C---D             rG--rH--rI  master
    |        \           /
    |         G---H---I-`
    | 
    `-E---F---G'--H'--I' feature <- HEAD

如果您已经执行了更改,则需要在重置HEAD后强制执行下一次推送。

git reset --hard HEAD^
git merge COMMIT_SHA1
git push --force

警告:硬重置将撤销工作副本中任何未提交的修改,而强制推将完全覆盖远程分支的状态与本地分支的当前状态。

以防万一,在Windows上(使用Windows命令行,而不是Bash),它实际上是四个^^^^而不是一个,所以它是

git reset --hard HEAD^^^^

这个话题晚了4年,但这可能对某些人有帮助。

如果你忘记在提交之前创建一个新的分支,并在master上提交所有的分支,无论你做了多少次提交,下面的方法都更容易:

git stash                       # skip if all changes are committed
git branch my_feature
git reset --hard origin/master
git checkout my_feature
git stash pop                   # skip if all changes were committed

现在你的主分支等于origin/master,所有的新提交都在my_feature上。注意,my_feature是一个本地分支,而不是远程分支。