git 将提交从一个父级重定到另一个父级

kokeuurv  于 2022-11-27  发布在  Git
关注(0)|答案(2)|浏览(167)

我有一个现成的仓库正在开发,但最近我学到了很多关于好的实践和git本身的知识。我想根据自己的喜好改变我的历史,特别是一些早期提交。
下面是当前历史的片段。我想将e5 cb 9 b8提交重定基到1a 92 e84上,这样我就可以在历史图中只拥有一/两个级别的深度(从视觉上看,改变了e5 cb 9 b8的父级)。我已经尝试过重定基了

git rebase -p --onto 1a92e84 e5cb9b8 master

和cherrypicking到从9 ecbe 00创建的新分支中。Cherrypicking得到的是平面历史记录,重定基失败,并显示以下消息
错误:提交ca 230 d8 c 048 d22 de 6 f219 da 8a 22 e70 a773827 c38是一个合并,但未指定-m选项。
致命错误:选择失败
无法选取ca 230 d8 c 048 d22 de 6 f219 da 8a 22 e70 a773827 c38

* | 45a0a21 - (7 weeks ago) #17 Updates README.md - Kamil Pacanek
|/
*   ca230d8 - (8 weeks ago) Merge pull request #2 from KamilPacanek/feat/rmb-support-removing-parts - Kamil Pacanek
|\
| * e5cb9b8 - (8 weeks ago) Adds support for removing parts on ReactorCells - KamilPacanek
* |   1a92e84 - (8 weeks ago) Merge pull request #1 from KamilPacanek/enable-gh-pages - Kamil Pacanek
|\ \
| |/
| * 81761ff - (8 weeks ago) Adds GH Pages support - KamilPacanek
|/
* 9ecbe00 - (8 weeks ago) Initial commit - KamilPacanek

预期值:

* | 45a0a21' - (7 weeks ago) #17 Updates README.md - Kamil Pacanek
|/
*   ca230d8' - (8 weeks ago) Merge pull request #2 from KamilPacanek/feat/rmb-support-removing-parts - Kamil Pacanek
|\
| * e5cb9b8' - (8 weeks ago) Adds support for removing parts on ReactorCells - KamilPacanek
|/
*    1a92e84 - (8 weeks ago) Merge pull request #1 from KamilPacanek/enable-gh-pages - Kamil Pacanek
|\ 
| |
| * 81761ff - (8 weeks ago) Adds GH Pages support - KamilPacanek
|/
* 9ecbe00 - (8 weeks ago) Initial commit - KamilPacanek

我在StackOverflow上搜索过类似的问题,似乎没有人在历史上如此深入地描述过这样的修改。

溶液

好的,为了将来的读者和我自己,我写下了我的问题的解决方案。@alfunx answer是解决它的关键--我在其他主题中找到了git rebasegit rebase --onto的解释,并开始在我的仓库上进行实验。通过反复试验,我通过执行

git rebase -ir --onto 1a92e84 81761ff develop

并替换todo-list的以下片段

label onto

# Branch KamilPacanek/feat/rmb-support-removing-parts
reset onto
pick e5cb9b8 Adds support for removing parts on ReactorCells
label KamilPacanek/feat/rmb-support-removing-parts

# Branch enh/add-uranium-cells
reset 9ecbe00 # Initial commit
merge -C 1a92e84 onto # Merge pull request #1 from KamilPacanek/enable-gh-pages
merge -C ca230d8 KamilPacanek/feat/rmb-support-removing-parts # Merge pull request #2 from KamilPacanek/feat/rmb-support-removing-parts
label branch-point

具有以下内容(更改了重置位置并删除了一个冗余合并提交):

label onto

# Branch KamilPacanek/feat/rmb-support-removing-parts
reset onto
pick e5cb9b8 Adds support for removing parts on ReactorCells
label KamilPacanek/feat/rmb-support-removing-parts

# Branch enh/add-uranium-cells
reset onto
merge -C ca230d8 KamilPacanek/feat/rmb-support-removing-parts # Merge pull request #2 from KamilPacanek/feat/rmb-support-removing-parts
label branch-point
  • )实际上,要达到这种状态还有很多工作要做,但我不想用次要问题来混淆解决方案。

错误:拒绝更新具有错误名称“refs/rewrited/Implement-durability-loss”的引用。
提示:无法执行todo命令
提示:标记为“实现-持久性-损失”。
正如你所看到的,我在提交消息的末尾有一个句点。在我解决了这个问题之后(用reword命令的另一个rebase),我就可以继续前进了。
而且,看起来像git rebase --abortdoesn't clear的引用是在git rebase -r期间创建的..所以我在历史上有一个烂摊子。通过rm -rf .git/refs/rewritten解决了这个问题。另一件事,我有一个剩余的.git/sequencer文件夹,可以通过git revert --quit删除。

tf7tbtn2

tf7tbtn21#

您为rebase选择的基是错误的,应该是81761ff而不是e5cb9b8。我建议您进行交互式rebase,并使用--rebase-merges而不是--preserve-merges。因此命令应该是:

git rebase -ir --onto 1a92e84 81761ff master

现在,Git可能会产生一个额外的合并提交。为了避免这种情况,并产生你想要的结果,你应该调整todo-list如下:

label onto
pick e5cb9b8 Adds support for removing parts on ReactorCells
label new
reset onto
merge -C ca230d8 new
pick 45a0a21 #17 Updates README.md
# Remaining commits...

在todo-list中,label可以用来标记当前提交(HEAD),而reset可以用来将HEAD设置为某个提交/标签。merge显然是用来产生合并提交,-C使合并使用与原始合并提交相同的提交消息。
这是相当高级的,* 真的 * 对于大多数用户和用例来说并不需要,所以请考虑man git-rebase,部分 Rebase Merges(或此处的在线版本)以获得更深入的信息。

kadbb459

kadbb4592#

如果你用git rebase -ir,那么就用Git 2.25(Q1 2020)。
由“git rebase --rebase-merges“生成的todo列表中使用的标签用作refname的一部分;制定标签的逻辑已经被收紧以避免不能这样使用的名称。
参见Matthew Rogers ( soniqua )(2019年11月17日)。
参见Johannes Schindelin ( dscho )commit 867bc1d(2019年11月17日)。
(由Junio C Hamano -- gitster --合并至commit 917d0d6,2019年12月5日)
第1011章:让label生成更安全的标签
签署人:马修·罗杰斯
签署人:约翰内斯·申德林
交互式重定基中的label todo命令在refs/rewritten/命名空间中创建临时引用。这些引用被存储为松散引用,即.git/refs/rewritten/中的文件,因此它们必须符合当前文件系统上的文件名限制以及可接受的引用格式。
这在NTFS/FAT上尤其造成问题,例如冒号、双引号和管道字符不允许作为文件名的一部分。
让我们不仅用破折号替换空白字符,而且用所有非字母数字字符来防止这种情况。
然而,我们将非ASCII UTF-8字符排除在外,因为它很可能会在引用/文件名中反映分支名称,如↯↯↯
还有:
在Git 2.25(Q1 2020)中,避免由“git rebase --rebase-merges“生成的重复标签名称的逻辑忘记了机器本身使用“onto“作为标签名称,这必须通过自动生成的标签来避免,这一点已经得到纠正。
参见Doan Tran Cong Danh ( congdanhqx-zz )commit e02058a(2019年11月18日)。
(2019年12月5日,由Junio C Hamano -- gitster --合并至commit 995b1b1
第1001章:处理“onto”消息重基合并
签署人:多安陈公丹
确认人:Johannes Schindelin
为了正确工作,git rebase --rebase-merges需要创建带有唯一标签的初始待办事项列表。
通过使用散列表并在发现任何重复时附加唯一编号来处理这些唯一标签。
但是,我们忘记了,除了那些用于侧枝的标签之外,我们还有一个特殊的标签onto,用于我们所谓的新基。
在一个特殊的情况下,其中任何一个标注为'onto'的分支,git都会遇到麻烦。
更正它。
另一个可能的问题:Git 2.39(Q4 2022)修正了git rebaseman)在缺少重定基标签时错误地使用了名为“refs/rewritten/xyz“的分支或标签的错误。
请参见commit 688d82fcommit 82766b2(2022年11月10日),作者为Phillip Wood ( phillipwood )
(2022年11月23日由Junio C Hamano -- gitster --合并至commit 3b041ea
第1001章:紧缩标签查找
签署人:菲利普伍德
签署人:泰勒·布劳
label命令创建一个ref refs/rewritten/<label>resetmerge命令通过调用lookup_label()来解析该ref。
它使用lookup_commit_reference_by_name()查找标签ref。
由于lookup_commit_reference_by_name()在查找标签时使用dwim规则,它将查找名为refs/heads/refs/rewritten/<label>的分支,如果分支存在而标签不存在,则返回该分支而不是错误。
在查找标签时,通过使用read_ref()后跟lookup_commit_object()来修复此问题。
注意:DWIM is short for Do What I Mean,系统试图预测用户的意图,自动纠正微小的错误,而不是盲目地执行用户明确但可能不正确的输入。

相关问题