使用Git将最近的提交移动到新分支

6465

我如何将在主分支上的最近提交移到一个新的分支,并将主分支重置为这些提交之前的状态?例如,从这个状态:

master A - B - C - D - E

转化为:

newbranch     C - D - E
             /
master A - B 

163
注意:我在这里提出了相反的问题 [https://dev59.com/X3A75IYBdhLWcg3wDUq2]。 - Benjol
7
这个链接是关于如何将最新的git提交移动到一个新的或已经存在的分支中。 - Sagar Naliyapara
23
这里的评论被清理了吗?我这么问是因为每两个月我都会来看这个问题,但我总是在滚动中错过那条评论。 - Tejas Kale
7
旁注:这个问题非常简单。阅读答案时,所有的“不要这样做,因为……”、“更好的解决方案是……”和“警告版本n+……”都出现了(可能是因为太晚了),我觉得即使是非常简单的操作在git中也没有直接的解决方案。一个图形化的版本管理器,在不处理我看起来比较模糊和过时的语法的情况下,只需为新分支添加一个标签,将会如此令人宽慰。我的王国和金徽章将授予第一个“forks” git并开始新方法的人;-)这是紧急的。 - mins
3
请务必阅读前十个答案(左右),因为最好的答案不一定是得票最高的。 - chb
显示剩余3条评论
22个回答

14

刚刚遇到了这种情况:

Branch one: A B C D E F     J   L M  
                       \ (Merge)
Branch two:             G I   K     N

我执行了:

git branch newbranch 
git reset --hard HEAD~8 
git checkout newbranch

我原本预期提交I会成为HEAD,但现在是提交L...

为了确保能够准确地定位到历史中的某个位置,最好使用提交的哈希值进行操作。

git branch newbranch 
git reset --hard #########
git checkout newbranch

11

简而言之

git checkout branch_to_remove_commits
git reset --hard ${hash_of_new_tip}
git checkout -b branch_to_store_commits
# Move commits (single hash, list of hashes or range ffaa..ffoo) 
git cherry-pick ${commit_hash}
git push --set-upstream origin branch_to_store_commits
# Switch back to last branch
git checkout -
git push -f

对我来说

git log --pretty=oneline -n ${NUMBER}

最好的方法是识别需要的提交哈希值。


10
如果您只需要将所有未推送的提交移动到一个新分支中,那么您需要:
  1. 从当前分支创建一个新的分支:git branch 新分支名称

  2. 推送您的新分支git push origin 新分支名称

  3. 还原您的旧(当前)分支到最后一个推送/稳定状态:git reset --hard origin/旧分支名称

一些人除了origin之外还有其他的upstream,他们应该使用适当的upstream

6
您只需按照我使用的三个简单步骤即可完成此操作。
1)新建一个分支,将最近的更新提交到该分支。 git branch <branch name> 2)查找新分支上提交的最新提交ID。 git log 3)复制该提交ID。请注意,最近的提交列表位于顶部。因此,您可以通过消息找到您的提交。您还可以通过提供一些提交ID范围来查找。 git cherry-pick d34bcef232f6c... 现在,您的任务已完成。如果您选择了正确的ID和正确的分支,则会成功。因此,在执行此操作之前,请小心。否则,可能会出现其他问题。
现在,您可以推送您的代码。 git push

5

我很惊讶没有人推荐以下方法:

git checkout master
git checkout <commit hash from which you want to split>
git checkout -b new_branch
git rebase master
git checkout master
git reset --hard <commit hash you splitted>

解释:

  1. 我们先检查我们想要分离的提交(commit)
  2. 然后从这个提交创建一个新分支
  3. 进行rebase操作将同步新分支(new_branch)和主分支(master),现在我们有了两个相同的分支,它们有着相同的提交记录(commits)
  4. 使用master上的reset操作,来清除分离之后的最后一次提交(commits)
  5. 列表项

这种方式只会创建一个分支,其中包含第一个从主分支/主干更改的提交,但会忽略其余的提交。 - Eamon Bohan

5

1)创建一个新分支,将所有更改移至new_branch。

git checkout -b new_branch

2) 然后回到旧分支。

git checkout master

3) 执行 git rebase

git rebase -i <short-hash-of-B-commit>

4) 然后打开的编辑器包含最近的3个提交信息。

...
pick <C's hash> C
pick <D's hash> D
pick <E's hash> E
...

5)在所有这3个提交中将pick更改为drop。然后保存并关闭编辑器。

...
drop <C's hash> C
drop <D's hash> D
drop <E's hash> E
...

6) 现在当前分支(master)中最后的三个提交已被移除。现在需要使用强制推送的方式,将分支推送到远程仓库,需要在分支名前加上+ 符号。

git push origin +master

4

这里的大多数解决方案都是计算您想回退的提交数量。我认为这是一种容易出错的方法。计数需要重新计算。

您可以通过传递您想要作为HEAD或者换句话说,您想要作为最后一个提交的提交哈希来简单地设置。

(注意查看提交哈希)

为了避免这种情况:

1) git checkout master

2) git branch <feature branch> master

3) git reset --hard <commit hash>

4) git push -f origin master

4
使用Emacs的git porcelain Magit,您只需按下b s(magit-branch-spinoff)即可完成此操作。您将被要求输入新分支的名称,一旦输入并回车,就完成了。
Magit文档中得到以下信息:
该命令创建并检出一个新分支,并跟踪当前分支。而当前分支则会重置为它与其上游所共享的最后一次提交。如果当前分支没有上游或没有未推送的提交,则仍会创建新分支且不会对之前的当前分支进行任何更改。
这对于在旧分支上已经开始工作(通常是但不一定是“master”分支)并想要创建一个特性分支非常有用。

3

您可以将受到这3个提交影响的文件放回到暂存区,然后将代码重新提交到一个新分支。假设您在master分支上,并且想要将恰好3个提交移动到new-branch分支:

git reset --soft HEAD~3
git checkout -b new-branch
git commit -m "message"

代码现在已经提交到一个新的哈希值中,位于new-branch分支,避免了一些其他答案所强调的未来变基问题。为了避免任何合并冲突,请推送master分支:

git checkout master
git push -ff

这个解决方案还提供了完全重新创建提交的灵活性。在上面的示例中,我用一个提交替换了3个提交。但是,您当然可以通过将上面的commit步骤替换为以下内容来取消暂存已暂存的文件:

git reset                        # unstage all files
git add path/file_1
git commit -m "first-commit"
git add path/file_2
git commit -m "second-commit"
...

1
我需要将七次提交从旧分支移动到新分支。
git checkout old-branch     # in the example, master
git reset --hard h4sh       # h4sh is the hash for the commit 
git checkout -b new-branch  
git push origin new-branch

之后,这两个分支都与我进行的7次提交相关。在执行 git checkout new-branch 之后,我的 git log git status 都很好,但是,当访问旧分支( git checkout old-branch )时,我收到了“git落后于7个提交,可以快进”的消息。对我有用的是以下内容:

git checkout old-branch
git status 
> git is behind by 7 commits and can be fast-forwarded
git push origin old-branch -f

在这一步之后,Bitbucket树中的最后7个提交仅与新分支相关,并且之前的提交被标记为旧分支和新分支。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接