更改 git 分支的根,将旧提交保留为分支 HEAD?
Change git branch's root, retainig older commit as branch HEAD?
请原谅我措辞不当,但我有 master
和 master-variant
,后者是我正在开发的通用产品的变体。它包含其他文件和一些更改的文件。
问题是我正在创建这个 "in reverse",因为我从变体开始,现在需要这个新的通用 "root",因为我将添加其他分支的新变体它。
所以我从 master
中的原始变体开始,并为当前状态创建了一个分支 master-variant
,没有任何更改(即它指向与 master
相同的提交).
然后我修改了 master
的内容使其成为 "generic",即删除所有特定于变体的内容并将其提交到那里。在这种状态下,master
与 master-variant
指向的提交相比有一个新的提交。
但我希望它看起来好像我从通用 master
(那里的最后一次提交)开始,然后分支 master-variant
,并添加了特定于变体的内容,即master
.
中上一次提交的状态
我会尝试说明。我有的是这个 (m = master
, v = master-variant
):
m0---m1---m2---m3 (changes to create generic variant)
\
v1 (just a new ref to m2)
注意 m0
..m2
在 master
分支中,但是它们的 contents 是我现在想要的原始变体而是在一个分支中。
我想更改它,使其看起来像这样:
m0---m1---m2---m3 (same as above, the generic variant)
\
v1 (same content as "v1" above, which is also the same content as "m2" in both illustrations)
我怎样才能做到这一点?
我的第一个想法是使用 git rebase
,但我看不出这怎么可能,因为它所做的是重播提交,而我需要重播 reverse 提交,即 m3
提交的反向。
我想我可以隐藏 m2
/v1
状态,删除 master-variant
分支,切换到 master
(即提交 m3
),弹出隐藏状态并将其提交到新的 master-variant
分支。
但是有更直接的方法吗?
简而言之,我想我真正想要的是创建一个包含历史提交状态的分支,但该分支以 HEAD 为根(而不是历史提交)。
提醒:提交 是文件状态的 快照。提交本身形成提交图,而 分支名称 只是标识(指向)特定提交的标签。
您说在您的图表中,v1
实际上是 对 提交 m2
的引用。也就是说,它还不是自己的单独提交。所以你真正拥有的是:
C0--C1--C2 <-- v1
\
C3 <-- master
其中 v1
和 master
是指向由提交本身形成的图形的标签(名称),它们是 C0
到 C3
。您将自己描述为想要的图表添加了一个新提交 C4
,其内容与 C2
的内容匹配,但其父项(历史提交就在其后面)是 C3:
C0--C1--C2 C4 <-- v1
\ /
C3 <-- master
鉴于这种情况,您有两个相对容易的选择。一种是进入 Git 所谓的 plumbing 命令 并使用一个命令进行新的提交,给它一个特定的保存快照和父集。新提交是您的 C4
。然后,将 C2
复制到 C4
,您可以将名称 v1
移动到指向 C4
。两个特定的 Git 命令是:
hash=$(git commit-tree -p master v1^{tree} -F /tmp/message)
其中 /tmp/message
包含您要使用的提交日志消息。另请注意,某些 shell 可能会解释 ^
或 {
字符;如果是这样,请引用它们。然后您可以 运行 git log $hash
来验证提交看起来是否正确。然后,如果您当前 "on" 分支 v1
:
git reset $hash
将调整 v1
标签。 (确保您的索引和工作树是干净的,即没有未提交的东西要保存。)如果不是:
git branch -v v1 $hash
将调整 v1
标签。
或者,考虑还原 提交 C3
会取消其更改并为您留下匹配 C2
的新提交。所以你可以:
git checkout v1
git merge --ff-only master
这将产生:
C0--C1--C2
\
C3 <-- v1 (HEAD), master
那么你只需 运行:
git revert HEAD
做一个新的提交来回避 C2
和 C3
之间的区别,给你一个新的提交 C4
:
C0--C1--C2 C4 <-- v1 (HEAD)
\ /
C3 <-- master
再次完成。
如果您有许多要还原的提交——即,如果您想要:
C0--C1--C2 <- v1
\
C3--C4--C5 <-- master
成为:
C0--C1--C2 C6 <- v1
\ /
C3--C4--C5 <-- master
那么 git commit-tree
方法就没那么有用了(尽管你仍然可以使用 git revert
,在这种情况下你只需要 -n
,同时还原 C5
,C4
,和 C3
,或随后的 git rebase -i
,您将所有新提交压缩在一起)。换句话说,git commit-tree
正是实现以下目标的工具:
... what I really want is to create a branch that contains the state of a historic commit, but have that branch rooted at HEAD (not at the historic commit).
请原谅我措辞不当,但我有 master
和 master-variant
,后者是我正在开发的通用产品的变体。它包含其他文件和一些更改的文件。
问题是我正在创建这个 "in reverse",因为我从变体开始,现在需要这个新的通用 "root",因为我将添加其他分支的新变体它。
所以我从 master
中的原始变体开始,并为当前状态创建了一个分支 master-variant
,没有任何更改(即它指向与 master
相同的提交).
然后我修改了 master
的内容使其成为 "generic",即删除所有特定于变体的内容并将其提交到那里。在这种状态下,master
与 master-variant
指向的提交相比有一个新的提交。
但我希望它看起来好像我从通用 master
(那里的最后一次提交)开始,然后分支 master-variant
,并添加了特定于变体的内容,即master
.
我会尝试说明。我有的是这个 (m = master
, v = master-variant
):
m0---m1---m2---m3 (changes to create generic variant)
\
v1 (just a new ref to m2)
注意 m0
..m2
在 master
分支中,但是它们的 contents 是我现在想要的原始变体而是在一个分支中。
我想更改它,使其看起来像这样:
m0---m1---m2---m3 (same as above, the generic variant)
\
v1 (same content as "v1" above, which is also the same content as "m2" in both illustrations)
我怎样才能做到这一点?
我的第一个想法是使用 git rebase
,但我看不出这怎么可能,因为它所做的是重播提交,而我需要重播 reverse 提交,即 m3
提交的反向。
我想我可以隐藏 m2
/v1
状态,删除 master-variant
分支,切换到 master
(即提交 m3
),弹出隐藏状态并将其提交到新的 master-variant
分支。
但是有更直接的方法吗?
简而言之,我想我真正想要的是创建一个包含历史提交状态的分支,但该分支以 HEAD 为根(而不是历史提交)。
提醒:提交 是文件状态的 快照。提交本身形成提交图,而 分支名称 只是标识(指向)特定提交的标签。
您说在您的图表中,v1
实际上是 对 提交 m2
的引用。也就是说,它还不是自己的单独提交。所以你真正拥有的是:
C0--C1--C2 <-- v1
\
C3 <-- master
其中 v1
和 master
是指向由提交本身形成的图形的标签(名称),它们是 C0
到 C3
。您将自己描述为想要的图表添加了一个新提交 C4
,其内容与 C2
的内容匹配,但其父项(历史提交就在其后面)是 C3:
C0--C1--C2 C4 <-- v1
\ /
C3 <-- master
鉴于这种情况,您有两个相对容易的选择。一种是进入 Git 所谓的 plumbing 命令 并使用一个命令进行新的提交,给它一个特定的保存快照和父集。新提交是您的 C4
。然后,将 C2
复制到 C4
,您可以将名称 v1
移动到指向 C4
。两个特定的 Git 命令是:
hash=$(git commit-tree -p master v1^{tree} -F /tmp/message)
其中 /tmp/message
包含您要使用的提交日志消息。另请注意,某些 shell 可能会解释 ^
或 {
字符;如果是这样,请引用它们。然后您可以 运行 git log $hash
来验证提交看起来是否正确。然后,如果您当前 "on" 分支 v1
:
git reset $hash
将调整 v1
标签。 (确保您的索引和工作树是干净的,即没有未提交的东西要保存。)如果不是:
git branch -v v1 $hash
将调整 v1
标签。
或者,考虑还原 提交 C3
会取消其更改并为您留下匹配 C2
的新提交。所以你可以:
git checkout v1
git merge --ff-only master
这将产生:
C0--C1--C2
\
C3 <-- v1 (HEAD), master
那么你只需 运行:
git revert HEAD
做一个新的提交来回避 C2
和 C3
之间的区别,给你一个新的提交 C4
:
C0--C1--C2 C4 <-- v1 (HEAD)
\ /
C3 <-- master
再次完成。
如果您有许多要还原的提交——即,如果您想要:
C0--C1--C2 <- v1
\
C3--C4--C5 <-- master
成为:
C0--C1--C2 C6 <- v1
\ /
C3--C4--C5 <-- master
那么 git commit-tree
方法就没那么有用了(尽管你仍然可以使用 git revert
,在这种情况下你只需要 -n
,同时还原 C5
,C4
,和 C3
,或随后的 git rebase -i
,您将所有新提交压缩在一起)。换句话说,git commit-tree
正是实现以下目标的工具:
... what I really want is to create a branch that contains the state of a historic commit, but have that branch rooted at HEAD (not at the historic commit).