我如何将分支还原为提交并将转发的提交放入新分支?

问题描述 投票:0回答:1

对于远程和本地,我都具有这样的git外观。

A---B---C---D master

现在,我希望在提交master时恢复我的B,但是我也不想丢失我的CD提交。

是否有办法使我的git在远程和本地都看起来像这样?

      C---D new branch
     /
A---B master

我知道不可能回溯到上一点,也许类似的事情也可以解决这个问题:

                          C---D new branch
                         /
A---B---C---D---revertToB master

请给我一些建议。

git github revert
1个回答
1
投票

可以得到这个:

     C--D   <-- new-branch
    /
A--B   <-- master

但是要做到这一点,您必须强制all具有名为master的分支指向现有提交D的Git存储库,以收回其master指向现有提交B。这可能很困难,因为Git“喜欢” add提交,而不是“删除”它们。

要在本地获取,如果您有:

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存储库仍然具有its master指向提交D。从该其他Git存储库创建的任何克隆也具有指向提交mastertheir 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 commitgit 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提交CD

首先,运行git revert mastergit 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'分别表示它们分别是CD的精选副本。 (当我们还原为E时,我们使用git revert -n合并了两个撤消步骤,因此E并不完全是D C的撤消,而是两者的撤消。一次。)

现在可以安全删除名称temp,因为我们不再需要它来方便地查找CD。 (我们一直不需要它,因为无论如何我们都可以找到它们,但是为提交D命名很方便,因此,提交CB分别为temp~2temp~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

然后您可以像以前一样“撤消” C-Dmaster上的提交,例如,产生:

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)
Commit F现在是

ahead of

master一样,但是当以直线形式向后读取时,在第一个父级链接中,它永远不会访问commit E:Git从F走回到DC等。同样,当--first-parentgit loggit rev-list移回时,这是[[提供您使用F。默认情况下,从F返回的遍历访问both提交E and D(并且由于默认按提交者日期顺序进行,因此您会看到E,我们在看到D之前比D做得晚。]
© www.soinside.com 2019 - 2024. All rights reserved.