如何将主分支上的最近提交移动到新分支,并将主分支重置为这些提交之前的状态?例如,从以下状态:
master A - B - C - D - E
变成这样:
newbranch C - D - E
/
master A - B
移动到现有分支
如果你想将你的提交移动到一个现有分支,它看起来像这样:
git checkout existingbranch
git merge branchToMoveCommitFrom
git checkout branchToMoveCommitFrom
git reset --hard HEAD~3 # 回退3个提交。你*会*丢失未提交的工作。
git checkout existingbranch
在执行git reset --hard HEAD~3
之前,你可以使用git stash
存储未提交的编辑。完成后,你可以使用git stash pop
检索存储的未提交编辑。
移动到新分支
警告:这种方法有效,因为你使用第一个命令创建了一个新分支:git branch newbranch
。如果你想将提交移动到现有分支,你需要在执行git reset --hard HEAD~3
之前将更改合并到现有分支(请参阅上面的Moving to an existing branch)。 如果你不先合并更改,它们将会丢失。
除非有其他情况,否则这可以通过分支和回滚轻松完成。
# 注意:任何未提交的更改都将丢失。
git branch newbranch # 创建一个新分支,保存所需的提交
git checkout master # 检出master,这是你要返回的地方
git reset --hard HEAD~3 # 通过3个提交将master回退(确保你知道需要回退多少个提交)
git checkout newbranch # 转到仍然具有所需提交的新分支
但是一定要确定要回退多少个提交。或者,你可以直接提供要在master(/current)分支上“回退”到的提交的哈希值(或引用,如origin/master),例如:
git reset --hard a1b2c3d4
注意:你只会从master分支“丢失”提交,但不用担心,你会在新分支中拥有这些提交!在完成上述4个步骤的命令后,检查这一点的一个简单方法是查看git log -n4
,它将显示newbranch实际上保留了3个提交(原因是newbranch在那些更改已经被提交到master时已经创建!)。它们只是从master中删除了,因为git reset
只影响在执行其时检出的分支,即master(参见git reset的描述:将当前HEAD重置为指定状态)。但是git status
不会显示newbranch上的任何检出,这可能一开始会让人感到意外,但这实际上是预期的。
最后,你可能还需要将最新的更改强制推送到主仓库:
git push origin master --force
警告:使用Git版本2.0及更高版本,如果你稍后对新分支执行git rebase
原始(master
)分支,你可能需要在rebase期间使用显式的--no-fork-point
选项以避免丢失携带的提交。设置branch.autosetuprebase always
可以更容易地实现这一点。有关详细信息,请参阅John Mellor的回答。