Git 来自旧提交的分支
Git branch from old commits
我已经在 SO 和其他文档中对此进行了研究。我试过变基、合并、挑选樱桃和分离头。
经过 6 个小时的尝试,现在是时候提出问题了!
这是我的开头:
A-B-C-D-E-F-G master
这是我想将其更改为:
A-B F-G master
\ /
C-D-E dev
我最接近的是:
A-B C-D-E-F-G-H Main
\ /
C-D-E dev
\
F-G master
我必须添加另一个分支名称和一个虚拟提交才能让分支正常工作。
但这比没有改变更糟糕。
请帮忙!
回复后更新
感谢您的回复。
是的,我的"what I want"不是很清楚。希望这可以澄清它:
A-B - F-G master
\ /
C-D-E dev
也就是说F处的"master"是B加上分支"dev"合并进去的结果
仍然无法正常工作
感谢@frasertweedale 尝试回答。
我已仔细按照您的说明进行操作,结果如下:
A-B - "merge branch 'dev'"-G master
\ /
C-D-E dev
\
F-G-"merge branch 'dev'"-F-G
我很高兴这很难:现在我花了 7 个小时在这上面,我感觉没那么糟糕了!
最终结果
正如@frasertweedale 所说,这正是我想要的,除了悬空的提交。
所以,我只需要摆脱悬垂物。
为清楚起见,我在下面重绘了:
A-B - "merge branch 'dev'"-G2 master
\ /
C-D-E dev
\
F1-G1-"merge branch 'dev'"-F2-G2
此命令进行清理:
git rebase -p --onto F1^ F1
结果:
A-B - "merge branch 'dev'"-G2 master
\ /
C-D-E dev
"merge branch 'dev'" 包含原始的 F 提交,当然可以这样重新注释。
假设您将 A
、B
等扩展到它们相应的提交哈希中,并且 master
在 G
,第一步是分支 dev
在 E
:
git branch dev E
然后将 master
重置为 B
。
git reset --hard B
接下来,将 dev
合并到 master
,明确要求合并提交(否则它将执行 快进,因为 dev
没有偏离 master
):
git merge --no-ff dev
master
现在包含最多 E
的提交。现在你可以 cherry-pick 原来的 F
和 G
提交。
git cherry-pick F
git cherry-pick G
现在你已经得到了非常接近你想要的东西;唯一的区别是添加了合并提交 (B+E)
:
A-B - (B+E)-F-G master
\ /
C-D-E dev
如果您现在想在合并提交 (B+E)
中包含 F
的内容,您可以执行 interactive rebase 并压缩两个提交一起。 --preserve-merges
(别名 -p
)选项必不可少。
git rebase --interactive --preserve-merges B
这将调用一个编辑器,其内容类似于以下内容(提交哈希和摘要会有所不同):
pick d4057bd c
pick 9419ef8 d
pick ad9e208 e
pick 120a90a Merge branch 'dev'
pick 61552ad f
pick c947153 g
将F
提交行开头的pick
指令替换为squash
指令(在上面的例子中:squash 61552ad f
),然后保存并退出.系统将提示您从合并提交和 F
的提交消息中形成一个新的提交消息,然后 rebase 操作将在没有进一步交互的情况下完成。变基后,您将完全您要求的存储库历史记录(在您更新的问题中)。
缩写脚本
以下脚本创建一个具有线性历史记录的新存储库,然后使用(大部分)与上述相同的步骤自动编辑历史记录。避免了交互式变基,因此不需要用户干预。
mkdir foo ; cd foo
git init
for C in A B C D E F G; do
echo $C > $C
git add $C
git commit -m $C
git tag $C
done
git branch dev E
git reset --hard B --
git merge --no-ff dev
git cherry-pick F
git reset --soft HEAD~
git commit --amend -m F
git cherry-pick G
for C in A B C D E F G; do
git tag -d $C
done
我已经在 SO 和其他文档中对此进行了研究。我试过变基、合并、挑选樱桃和分离头。
经过 6 个小时的尝试,现在是时候提出问题了!
这是我的开头:
A-B-C-D-E-F-G master
这是我想将其更改为:
A-B F-G master
\ /
C-D-E dev
我最接近的是:
A-B C-D-E-F-G-H Main
\ /
C-D-E dev
\
F-G master
我必须添加另一个分支名称和一个虚拟提交才能让分支正常工作。
但这比没有改变更糟糕。
请帮忙!
回复后更新
感谢您的回复。
是的,我的"what I want"不是很清楚。希望这可以澄清它:
A-B - F-G master
\ /
C-D-E dev
也就是说F处的"master"是B加上分支"dev"合并进去的结果
仍然无法正常工作
感谢@frasertweedale 尝试回答。
我已仔细按照您的说明进行操作,结果如下:
A-B - "merge branch 'dev'"-G master
\ /
C-D-E dev
\
F-G-"merge branch 'dev'"-F-G
我很高兴这很难:现在我花了 7 个小时在这上面,我感觉没那么糟糕了!
最终结果 正如@frasertweedale 所说,这正是我想要的,除了悬空的提交。
所以,我只需要摆脱悬垂物。
为清楚起见,我在下面重绘了:
A-B - "merge branch 'dev'"-G2 master
\ /
C-D-E dev
\
F1-G1-"merge branch 'dev'"-F2-G2
此命令进行清理:
git rebase -p --onto F1^ F1
结果:
A-B - "merge branch 'dev'"-G2 master
\ /
C-D-E dev
"merge branch 'dev'" 包含原始的 F 提交,当然可以这样重新注释。
假设您将 A
、B
等扩展到它们相应的提交哈希中,并且 master
在 G
,第一步是分支 dev
在 E
:
git branch dev E
然后将 master
重置为 B
。
git reset --hard B
接下来,将 dev
合并到 master
,明确要求合并提交(否则它将执行 快进,因为 dev
没有偏离 master
):
git merge --no-ff dev
master
现在包含最多 E
的提交。现在你可以 cherry-pick 原来的 F
和 G
提交。
git cherry-pick F
git cherry-pick G
现在你已经得到了非常接近你想要的东西;唯一的区别是添加了合并提交 (B+E)
:
A-B - (B+E)-F-G master
\ /
C-D-E dev
如果您现在想在合并提交 (B+E)
中包含 F
的内容,您可以执行 interactive rebase 并压缩两个提交一起。 --preserve-merges
(别名 -p
)选项必不可少。
git rebase --interactive --preserve-merges B
这将调用一个编辑器,其内容类似于以下内容(提交哈希和摘要会有所不同):
pick d4057bd c
pick 9419ef8 d
pick ad9e208 e
pick 120a90a Merge branch 'dev'
pick 61552ad f
pick c947153 g
将F
提交行开头的pick
指令替换为squash
指令(在上面的例子中:squash 61552ad f
),然后保存并退出.系统将提示您从合并提交和 F
的提交消息中形成一个新的提交消息,然后 rebase 操作将在没有进一步交互的情况下完成。变基后,您将完全您要求的存储库历史记录(在您更新的问题中)。
缩写脚本
以下脚本创建一个具有线性历史记录的新存储库,然后使用(大部分)与上述相同的步骤自动编辑历史记录。避免了交互式变基,因此不需要用户干预。
mkdir foo ; cd foo
git init
for C in A B C D E F G; do
echo $C > $C
git add $C
git commit -m $C
git tag $C
done
git branch dev E
git reset --hard B --
git merge --no-ff dev
git cherry-pick F
git reset --soft HEAD~
git commit --amend -m F
git cherry-pick G
for C in A B C D E F G; do
git tag -d $C
done