在推送到远程之前忘记创建一个新分支
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 将更改。)
一些想法:
您可能会在 cherry-pick 命令中遇到冲突。如果 D
之后的任何提交依赖于您从 master
中拉出的任何一个提交,就会发生这种情况。如果发生这种情况,您可能需要完全重新考虑此操作。
在 Git 中,通常有许多不同的方法可以做同一件事。请注意,您实际上可以换掉 reset
和 cherry-pick
命令,并用一个“花哨的”rebase --onto
一次性完成所有操作。但从概念上讲,我认为进行重置然后挑选一系列提交更容易明确理解。 rebase 只是在幕后做这两件事。
在 cherry-pick 命令中,我建议从提交 E
到 origin/master
而不是明显的 E
到 F
,仅仅是因为您提到:“更多提交已添加到远程 master 分支。”如果在本答案开头的初始 git fetch
命令之前添加了更多您不知道的内容,这样您也将保留任何新的未知提交。
我在本地开发一项功能,并在我的主分支上进行了几次提交(而不是创建一个单独的分支并在那里工作)。然后,我将这些提交推送到 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 将更改。)
一些想法:
您可能会在 cherry-pick 命令中遇到冲突。如果
D
之后的任何提交依赖于您从master
中拉出的任何一个提交,就会发生这种情况。如果发生这种情况,您可能需要完全重新考虑此操作。在 Git 中,通常有许多不同的方法可以做同一件事。请注意,您实际上可以换掉
reset
和cherry-pick
命令,并用一个“花哨的”rebase --onto
一次性完成所有操作。但从概念上讲,我认为进行重置然后挑选一系列提交更容易明确理解。 rebase 只是在幕后做这两件事。在 cherry-pick 命令中,我建议从提交
E
到origin/master
而不是明显的E
到F
,仅仅是因为您提到:“更多提交已添加到远程 master 分支。”如果在本答案开头的初始git fetch
命令之前添加了更多您不知道的内容,这样您也将保留任何新的未知提交。