如何将分支还原为提交并将前向提交提交到新分支?
How do I revert a branch to a commit and put the forward commits to a new branch?
我有一个 git 看起来像这样的远程和本地。
A---B---C---D master
现在我希望我的 master
在 B
提交时恢复,但我也不想丢失我的 C
和 D
提交。
有没有办法让我的 git 在远程和本地看起来都像这样?
C---D new branch
/
A---B master
我知道回溯到之前的点是不可能的,也许像这样的方法也可以解决问题:
C---D new branch
/
A---B---C---D---revertToB master
请多多指教
你可以得到这个:
C--D <-- new-branch
/
A--B <-- master
但要做到这一点,您必须强制 所有 Git 具有名为 master
分支的存储库指向现有提交 D
收回他们的 master
以指向现有的提交 B
。这可能很困难,因为 Git "likes" 到 add 提交,而不是 "remove" 他们。
要在本地获取此信息,假设您有:
A--B--C--D <-- master (HEAD)
运行:
git branch new-branch master
git reset --hard HEAD~2
您现在拥有:
C--D <-- new-branch
/
A--B <-- master (HEAD)
本地。不幸的是,位于 origin
的另一个 Git 存储库仍然有 其 master
指向提交 D
。从其他 Git 存储库制作的任何克隆也有 他们的 master
指向提交 D
。您必须让所有这些存储库执行相同类型的撤回。如果只有一个仓库,和你有权使用git push --force
收回它,你现在可以:
git push origin new-branch # to create new-branch on origin
git push -f origin master # to force them to retract their master
(您可能需要将 -u
添加到第一个 git push
。)
为了获得您正在寻找的更安全的东西——向 master
添加一个新的提交,将其重置为提交时的状态 B
——你可以使用:
git branch temp master
设置要读取的内容:
A--B--C--D <-- master (HEAD), temp
然后你可以 运行 git revert -n HEAD~2..HEAD; git commit
, 或 git read-tree -u HEAD~2; git commit
进行新提交 E
其快照与 B
:
A--B--C--D <-- temp
\
E <-- master (HEAD)
现有提交 C-D
卡在原处。如果您希望 new-branch
成为 master
的后代,您现在必须创建它。请注意,如果您同意 new-branch
指向现有提交 D
,您可以只使用名称 new-branch
而不是 temp
,您将获得想要的内容。但是如果你需要一个新的提交——我们称之为 F
——在 E
之后与提交 D
的内容相匹配,你现在可以创建新分支:
git checkout -b new-branch master
给予:
A--B--C--D <-- temp
\
E <-- master, new-branch (HEAD)
现在您可以:
- 还原还原提交
E
,或
git read-tree
提交 D
并提交,或者
git cherry-pick
提交 C
和 D
。
要执行第一个,运行 git revert master
或 git revert HEAD
(两者都足够)并且您有:
A--B--C--D <-- temp
\
E <-- master
\
F <-- new-branch (HEAD)
要执行第二个操作,运行 git read-tree -u temp; git commit
进行新提交 F
(您需要输入新的提交消息)。
做第三个,运行git cherry-pick temp~2..temp
;这将产生:
A--B--C--D <-- temp
\
E <-- master
\
C'-D' <-- new-branch (HEAD)
其中名称 C'
和 D'
表示它们分别是 C
和 D
的精心挑选的副本。 (当我们还原为 E
时,我们结合了两个撤消步骤,使用 git revert -n
,因此 E
不完全是 D
或 C
,而是同时撤消两者。)
现在删除名称 temp
是安全的,因为我们不再需要它来方便地查找 C
和 D
。 (我们一直不需要它,因为无论如何我们都可以找到它们,但是为提交 D
命名很方便,这样提交 C
和 B
是 temp~2
和 temp~1
分别。)
现在可以安全地(并且不需要 git push --force
)到 git push origin master new-branch
。
或者,您可以不创建 temp
,而是让名称 new-branch
始终指向提交 D
。也就是说,从:
开始
A--B--C--D <-- master (HEAD)
你可以这样做:
git branch new-branch master
给予:
A--B--C--D <-- master (HEAD), new-branch
然后你可以 "undo" C-D
像以前一样在 master
上提交,例如,生成:
A--B--C--D <-- new-branch
\
E <-- master (HEAD)
下一步,您可以 运行:
git checkout new-branch; git merge -s ours master
使 Git 创建一个新的 merge 提交 F
其快照与现有提交的快照相匹配 D
:
A--B--C--D---F <-- new-branch
\ /
E <-- master (HEAD)
提交 F
现在和以前一样 领先于 master
,但是当以直线向后读取时,跨第一父链接,它永远不会visits commit E
: Git 从 F
走回 D
再到 C
等等。同样,这是 提供的 当 git log
或 git rev-list
从 F
返回时使用 --first-parent
。默认情况下,从 F
返回的遍历访问 both 提交 E
and D
(并且自默认是按照提交者日期顺序,你会看到 E
,我们晚于 D
,然后看到 D
).
我有一个 git 看起来像这样的远程和本地。
A---B---C---D master
现在我希望我的 master
在 B
提交时恢复,但我也不想丢失我的 C
和 D
提交。
有没有办法让我的 git 在远程和本地看起来都像这样?
C---D new branch
/
A---B master
我知道回溯到之前的点是不可能的,也许像这样的方法也可以解决问题:
C---D new branch
/
A---B---C---D---revertToB master
请多多指教
你可以得到这个:
C--D <-- new-branch / A--B <-- master
但要做到这一点,您必须强制 所有 Git 具有名为 master
分支的存储库指向现有提交 D
收回他们的 master
以指向现有的提交 B
。这可能很困难,因为 Git "likes" 到 add 提交,而不是 "remove" 他们。
要在本地获取此信息,假设您有:
A--B--C--D <-- master (HEAD)
运行:
git branch new-branch master
git reset --hard HEAD~2
您现在拥有:
C--D <-- new-branch
/
A--B <-- master (HEAD)
本地。不幸的是,位于 origin
的另一个 Git 存储库仍然有 其 master
指向提交 D
。从其他 Git 存储库制作的任何克隆也有 他们的 master
指向提交 D
。您必须让所有这些存储库执行相同类型的撤回。如果只有一个仓库,和你有权使用git push --force
收回它,你现在可以:
git push origin new-branch # to create new-branch on origin
git push -f origin master # to force them to retract their master
(您可能需要将 -u
添加到第一个 git push
。)
为了获得您正在寻找的更安全的东西——向 master
添加一个新的提交,将其重置为提交时的状态 B
——你可以使用:
git branch temp master
设置要读取的内容:
A--B--C--D <-- master (HEAD), temp
然后你可以 运行 git revert -n HEAD~2..HEAD; git commit
, 或 git read-tree -u HEAD~2; git commit
进行新提交 E
其快照与 B
:
A--B--C--D <-- temp
\
E <-- master (HEAD)
现有提交 C-D
卡在原处。如果您希望 new-branch
成为 master
的后代,您现在必须创建它。请注意,如果您同意 new-branch
指向现有提交 D
,您可以只使用名称 new-branch
而不是 temp
,您将获得想要的内容。但是如果你需要一个新的提交——我们称之为 F
——在 E
之后与提交 D
的内容相匹配,你现在可以创建新分支:
git checkout -b new-branch master
给予:
A--B--C--D <-- temp
\
E <-- master, new-branch (HEAD)
现在您可以:
- 还原还原提交
E
,或 git read-tree
提交D
并提交,或者git cherry-pick
提交C
和D
。
要执行第一个,运行 git revert master
或 git revert HEAD
(两者都足够)并且您有:
A--B--C--D <-- temp
\
E <-- master
\
F <-- new-branch (HEAD)
要执行第二个操作,运行 git read-tree -u temp; git commit
进行新提交 F
(您需要输入新的提交消息)。
做第三个,运行git cherry-pick temp~2..temp
;这将产生:
A--B--C--D <-- temp
\
E <-- master
\
C'-D' <-- new-branch (HEAD)
其中名称 C'
和 D'
表示它们分别是 C
和 D
的精心挑选的副本。 (当我们还原为 E
时,我们结合了两个撤消步骤,使用 git revert -n
,因此 E
不完全是 D
或 C
,而是同时撤消两者。)
现在删除名称 temp
是安全的,因为我们不再需要它来方便地查找 C
和 D
。 (我们一直不需要它,因为无论如何我们都可以找到它们,但是为提交 D
命名很方便,这样提交 C
和 B
是 temp~2
和 temp~1
分别。)
现在可以安全地(并且不需要 git push --force
)到 git push origin master new-branch
。
或者,您可以不创建 temp
,而是让名称 new-branch
始终指向提交 D
。也就是说,从:
A--B--C--D <-- master (HEAD)
你可以这样做:
git branch new-branch master
给予:
A--B--C--D <-- master (HEAD), new-branch
然后你可以 "undo" C-D
像以前一样在 master
上提交,例如,生成:
A--B--C--D <-- new-branch
\
E <-- master (HEAD)
下一步,您可以 运行:
git checkout new-branch; git merge -s ours master
使 Git 创建一个新的 merge 提交 F
其快照与现有提交的快照相匹配 D
:
A--B--C--D---F <-- new-branch
\ /
E <-- master (HEAD)
提交 F
现在和以前一样 领先于 master
,但是当以直线向后读取时,跨第一父链接,它永远不会visits commit E
: Git 从 F
走回 D
再到 C
等等。同样,这是 提供的 当 git log
或 git rev-list
从 F
返回时使用 --first-parent
。默认情况下,从 F
返回的遍历访问 both 提交 E
and D
(并且自默认是按照提交者日期顺序,你会看到 E
,我们晚于 D
,然后看到 D
).