如果我的措辞不对,请原谅我,但我有的是 master
和 master-variant
其中后者是我正在研究的通用产品的一个变体。它包含了额外的文件和一些修改过的文件。
问题是我是 "反向 "创建的,因为我从变种开始,现在需要这个新的通用 "根",因为我将在它的基础上添加其他新的变种。
所以我从最初的变体开始,在 master
并建立了一个分支 master-variant
的当前状态,而不做任何修改(即它指向与 master
).
然后我修改了 master
使之成为 "通用的",即删除所有与变量有关的东西,并将其提交到那里。在这种状态下。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
枝,但其 内容 是原来的变体,现在我想把它放在一个分支中。
我想把它改成这样。
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
但我不明白这怎么可能,因为它做的是重播提交,而我需要重播的是 反面 的反面,也就是说,在提交的过程中。m3
提交。
我想我可以把 m2
v1
删去 master-variant
枝,切换到 master
承诺 m3
),弹出stashed状态,并将其提交到一个新的 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 的所谓 水管命令 并使用命令创建一个新的提交,给它一个特定的保存的快照和父节点集。 新的提交就是你的 C4
. 然后,在复制了 C2
到 C4
你会把名字移到 v1
指向 C4
. 两个特定的Git命令是
hash=$(git commit-tree -p master v1^{tree} -F /tmp/message)
其中 /tmp/message
包含了您想使用的提交日志信息。 请注意,有些shell可能会将 ^
或 {
字符;如果是,请引用它们。 然后您可以运行 git log $hash
来验证提交是否正确。 然后,如果你现在是 "在 "分支上的 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
正是实现这一目标的工具。
...我真正想要的是创建一个包含历史提交状态的分支,但这个分支的根在HEAD(而不是历史提交)。