如何修复提交到错误的Git分支?

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

202559 次浏览

如果你有一个干净的(未修改的)工作副本

要回滚一个提交(确保您注意到下一步的提交哈希):

git reset --hard HEAD^

要将该提交拉入不同的分支:

git checkout other-branch
git cherry-pick COMMIT-HASH

如果您有修改或未跟踪的更改

另请注意,git reset --hard删除任何未跟踪和修改的更改你可能有,所以如果你有那些你可能更喜欢:

git reset HEAD^
git checkout .

如果您还没有推送更改,您也可以执行软重置:

git reset --soft HEAD^

这将恢复提交,但将提交的更改放回你的索引中。假设分支彼此相对最新,git将让你对另一个分支进行签出,然后你可以简单地提交:

git checkout branch
git commit -c ORIG_HEAD

-c ORIG_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

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

因此,如果您的场景是您已提交master但打算提交another-branch(可能存在也可能不存在),但您还没有推送,这很容易解决。

// if your branch doesn't exist, then add the -b argument
git checkout -b another-branch
git branch --force master origin/master

现在您对master的所有提交都将在another-branch上。

爱的来源:http://haacked.com/archive/2015/06/29/git-migrate/

如果您想要应用更改的分支已经存在(例如分支开发),请按照下面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

显然,如果您愿意,您可以使用坦普兰或任何其他分支名称而不是my_feature

此外,如果适用,请将存储弹出(应用)延迟到您在目标分支处合并之后。

如果您遇到此问题并且您有Visual Studio,您可以执行以下操作:

右键单击您的分支并选择View History

在此处输入图片描述

右键单击要返回的提交。并根据需要恢复或重置。

在此处输入图片描述

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

如果您只是提交到错误的分支,并且从那以后没有更改任何内容,并且没有推送到repo,那么您可以执行以下操作:

// 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重置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/

为了详细说明这个答案,如果您有多个提交要移动,例如developnew_branch

git checkout develop # You're probably there already
git reflog # Find LAST_GOOD, FIRST_NEW, LAST_NEW hashes
git checkout new_branch
git cherry-pick FIRST_NEW^..LAST_NEW # ^.. includes FIRST_NEW
git reflog # Confirm that your commits are safely home in their new branch!
git checkout develop
git reset --hard LAST_GOOD # develop is now back where it started

错误分支上的多次提交

如果对你来说,它只是大约1次提交,那么还有很多其他更容易的重置解决方案可用。对我来说,我在master分支上意外创建了大约10次提交,而不是,让我们称之为target,我不想丢失提交历史记录。

你能做的,救了我的是使用这个答案作为参考,使用4步过程,这是-

  1. master创建一个新的临时分支temp
  2. temp合并到最初用于提交的分支中,即target
  3. 撤销提交master
  4. 删除临时分支temp

以下是以上步骤的细节——

  1. master创建一个新分支(我不小心提交了很多更改)

    git checkout -b temp
    

    注意:-b标志用于创建新分支
    只是为了验证我们是否正确,我会快速执行git branch以确保我们在temp分支上,并执行git log以检查我们是否正确提交。

  2. 将临时分支合并到最初用于提交的分支中,即target
    首先,切换到原始分支,即target(如果没有,您可能需要git fetch

    git checkout target
    

    注意:不使用-b标志
    现在,让我们将临时分支合并到我们当前签出的分支target

    git merge temp
    

    如果有冲突,你可能必须处理这里的一些冲突。成功合并后,你可以推送(我会)或继续下一步。

  3. 使用这个答案作为参考撤消master上的意外提交,首先切换到master

    git checkout master
    

    然后使用下面的命令撤消它以匹配远程(或者使用适当的命令进行特定的提交,如果您愿意)

    git reset --hard origin/master
    

    同样,我会在之前和之后执行git log,以确保预期的更改生效。

  4. 删除证据,即删除临时分支。为此,首先您需要签出temp合并到的分支,即target(如果您留在master并执行以下命令,您可能会得到error: The branch 'temp' is not fully merged),所以让我们

    git checkout target
    

    然后删除这次事故的证据

    git branch -d temp
    

这就对了。

对我来说,这是通过恢复我已经推送的提交来解决的,然后选择那个提交到另一个分支。

git checkout branch_that_had_the_commit_originally
git revert COMMIT-HASH
git checkout branch_that_was_supposed_to_have_the_commit
git cherry pick COMMIT-HASH

您可以使用git log找到正确的哈希,并且可以随时推送这些更改!

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

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

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

这个想法是在当前提交上重新创建feature分支并切换到它。然后让master分支指向与origin/master相同的提交。

一般情况

在一般情况下,您想在feature分支上重播在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

然后使用以下命令选择您在feature分支上的master上所做的提交。在您进行更改之前,将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取消存储它们。

不改写历史

而不是重置master分支到过去,你需要git revert的变化,除了樱桃采摘feature分支上的变化。

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

确保不要将git merge提交到feature中。如果您尝试将feature分支合并回master,这些更改将被忽略,因为我们刚刚恢复了它们。

这是结果的样子,rGrHrI分别是GHI的恢复提交:

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