在推送到远程之前忘记创建一个新分支

Forgot to create a new branch before pushing to remote

我在本地开发一项功能,并在我的主分支上进行了几次提交(而不是创建一个单独的分支并在那里工作)。然后,我将这些提交推送到 GitHub 上的远程 master 分支(这实际上是另一个存储库的一个分支)。一段时间过去了,我才意识到这个错误,更多的提交被添加到远程 master 分支。现在,我想返回并为该初始功能创建一个单独的分支。我该怎么做?

为了说明我的问题,这是我的:


master A - B - C - D - E - F

这就是我想要的:


newbranch     C - D
             /     \
master A - B  ----  E - F

其中提交 C, D 是我忘记为其创建新分支的初始功能。

警告:重写 master 等共享分支通常被认为是不好的做法。您需要确保使用该存储库的每个人都知道您正在这样做。

话虽如此,正如所要求的那样,您可以这样做:

# NOTE - this assumes your remote is called "origin"

git fetch

# create a branch called "newbranch" that points to commit hash D
git branch newbranch D

# checkout master so you can fix it up
git switch master

# change master to point to B
git reset --hard B

# Replay E through F (or any new commits if they exist!) onto master
git cherry-pick E..origin/master

# replace the remote master (make sure everyone is OK with it!)
git push --force-with-lease

这些命令的结果将使您的两个分支看起来像:

newbranch: A-B-C-D
master: A-B-E'-F'

请注意 E'F' 符号表示这些提交将类似于 E 和 F,但具有不同的提交 ID(因为任何时候你重写一个提交,你实际上是在做一个 new 提交,因此 ID 将更改。)

一些想法:

  1. 您可能会在 cherry-pick 命令中遇到冲突。如果 D 之后的任何提交依赖于您从 master 中拉出的任何一个提交,就会发生这种情况。如果发生这种情况,您可能需要完全重新考虑此操作。

  2. 在 Git 中,通常有许多不同的方法可以做同一件事。请注意,您实际上可以换掉 resetcherry-pick 命令,并用一个“花哨的”rebase --onto 一次性完成所有操作。但从概念上讲,我认为进行重置然后挑选一系列提交更容易明确理解。 rebase 只是在幕后做这两件事。

  3. 在 cherry-pick 命令中,我建议从提交 Eorigin/master 而不是明显的 EF ,仅仅是因为您提到:“更多提交已添加到远程 master 分支。”如果在本答案开头的初始 git fetch 命令之前添加了更多您不知道的内容,这样您也将保留任何新的未知提交。