Git交互式重定基底:如何自动移动其他分支(引用)?

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

有时我想做一个重新定基,并确保其他参考更新到新的结构,没有手动重置或多次重新定基。
有没有办法一次完成,这样git rebase会更新refs到新的提交,这些提交在rebase之前已经被拾取并且有引用了?
举个例子:
重定基准前的情况:

* abc3... commit3 (branch:a, HEAD) 
* abc2... commit2 
* abc1... commit1 (branch:b)
* abc0... base commmit (branch:master)

然后执行Rebase master -i:选择abc 3、abc 1、abc 2
结果如下所示:(分支:b停留在它自己的提交分支中)

* abc6... commit2 (branch:a, HEAD) 
* abc5... commit1   
* abc4... commit3
|
| * abc1... commit1 (branch:b)
|/
* abc0... base commmit (branch:master)

我希望的结果如下:(分支:b更新为新提交)

* abc6... commit2 (branch:a, HEAD) 
* abc5... commit1 (branch:b)
* abc4... commit3
* abc0... base commmit (branch:master)
ecbunoof

ecbunoof1#

下面是git 2.38新的update-refs特性如何帮助我的rebase流的一般情况。

在进行交互式重定基的时候,你现在可以很容易地用一个分支名称来标记任何一个提交。这个分支名称也不需要已经存在。这可以很容易地把一个大的提交序列分解成小的PR。
假设您运行git rebase -i <base sha from master>,在git-rebase-todo文件中:

pick 1688e8706 First
pick d8e19832e Second
pick b34be474e Third

你可以用一个新的分支名称“标记”每个提交,然后推送这些分支,如下所示:

pick 1688e8706 First
update-ref refs/heads/first

pick d8e19832e Second
update-ref refs/heads/second

pick b34be474e Third
update-ref refs/heads/third

注意:您可以忽略前缀refs/heads/,其后的所有内容都是 * 实际分支名称 *!。

如果你已经有了指向这些shas的分支,git会这样编辑文件。你只需要这样做一次[1],将分支名称绑定到提交。然后,如果你设置了git config rebase.updateRefs true,git-rebase会自动将这些update-ref refs/heads/branch-name行放到你的git-rebase-todo文件中。
然后,在每个重定基底成功完成后,您将看到:

Successfully rebased and updated refs/heads/third
Updated the following refs with --update-refs:
        refs/heads/first
        refs/heads/second
        refs/heads/third

然后,您可以像这样推动每个分支:

git push --force-with-lease origin first:refs/heads/first
git push --force-with-lease origin second:refs/heads/second
git push --force-with-lease origin third:refs/heads/third
git push --force-with-lease origin $(git branch --show-current):refs/heads/$(git branch --show-current)
给commits一个稳定的句柄本身并不激进,但这是一个手动的步骤,在userland中很容易出错。现在git已经实现了这一点,请关注更高级别的工具,它们会给你带来全新的特性!

[1]:如果你对git checkout second做了修改,git不会更新third。一般来说,你应该更喜欢在栈顶,在这里是third。如果你对second做了修改,最终想对third进行重定基,你应该运行:

git checkout third
git rebase --onto second d8e19832e

注意:d8e19832e实际上是正确的,根据我的例子,这是third历史记录中secondoriginal sha。Git rebase将获取d8e19832e和它下面的所有内容,并将其丢弃,然后尝试在新的second上应用提交“Third”,您可能需要在此过程中解决冲突。

i5desfxk

i5desfxk2#

git rebase会将引用更新到新提交,这些新提交是在 * rebase之前被拾取并有引用的。
以前,没有。
但在你重建基地的时候?也许吧。
在Git 2.38(Q3 2022)中,“git rebase -i”(man)学会了使用--update-refs选项来更新其尖端出现在重定基范围内的分支。
参见Junio C Hamano ( gitster )(2022年7月12日)。
请参见2022年7月19日至2022年7月14日期间发布的第1 e2f1x、第1 e3f1x、第1 e4f1x、第1 e5f1x、第1 e6f1x、第1 e7f1x、第1 e8f1x、第1 e9f1x、第1 e10f1x、第1 e11f1x、第1 e12f1x和第1 e13f1x(2022年7月19日)。
(由Junio C Hamano -- gitster --合并至commit 3d8e3dc,2022年8月1日)
我的天啊!add --update-refs选项
签署人:井架吊杆
在处理大型特征时,将该特征分解为多个按顺序查看的较小部分会很有帮助。
在开发或评审过程中,对功能的一个部分进行更改可能会影响多个部分。
交互式重定基可以帮助调整分支的多部分“故事”。
然而,如果有分支跟踪特性的不同部分,那么重定整个提交列表的基础可以创建从那些“子分支”不可到达的提交。
它可以采取手动步骤来更新这些分支。
在'git rebase -i'(man)中添加一个新的--update-refs选项,每当用'update-ref '修饰一个正在重定基的提交时,它就会将该步骤添加到待办事项文件中。
最后,变基过程将所有列出的引用更新为变基操作期间存储的值。
请确保在放置任何压缩或修复后进行迭代。
仅在这些压缩和修复完成后更新分支。
这允许在特性顶端的--fixup提交正确地应用到子分支,即使它正在修复该部分中最近的提交。
此变更更新了文档和内置程序以接受--update-refs选项,并使用“update-ref”命令更新了待办事项文件。
添加测试是为了确保将这些todo命令添加到正确的位置。
此更改 * 不 * 包括跟踪更新的引用和在重定基过程结束时写入新引用值的实际行为。
这是推迟到以后的变化。
git rebase现在在其手册页中包括:

--update-refs的第一个字符

--no-update-refs

自动强制更新指向正在重定基础的提交的任何分支。
在工作树中检出的任何分支都不会以这种方式更新。
还有:
第1001章:从“update-ref”命令更新引用
签署人:井架吊杆
之前的变更引入了“git rebase --update-refs”(man)选项,该选项将“update-ref <ref>”命令添加到交互式变基的todo列表中。
教Git在到达这些'update-ref'命令时记录HEAD位置。
ref/before/after三元组存储在$GIT_DIR/rebase-merge/update-refs文件中。
以前的更改解析了此文件,以避免在进行变基时其他进程更新该文件中的引用。
我们不仅在序列器到达这些'update-ref'命令时更新文件,而且在rebase序列结束时更新引用本身。
如果在此最后一步之前中止重定基,则不更新参考。
'before'值用于确保我们不会意外删除同时更新的ref(比如,被旧版本的Git或第三方工具更新)。
结果:
第1001章:通知用户--update-refs活动
报告人:伊莱贾·纽伦
签署人:井架吊杆
当用户运行'git rebase -i --update-refs'(man)时,结束消息仍然只显示

Successfully rebased and updated <HEAD-ref>.

更新序列器以收集由于--update-refs选项而导致的成功(和不成功)ref更新,因此结束消息现在显示

Successfully rebased and updated <HEAD-ref>.
Updated the following refs with --update-refs:
efs/heads/first
efs/heads/third
Failed to update the following refs with --update-refs:
efs/heads/second

当序列器中的所有update-ref命令被移除时,git rebase --update-refs(man)会删除引用,这一点已在Git 2.39(Q4 2022)中得到修正。
参见commit 44da9e0(2022年11月7日),作者:Victoria Dye ( vdye )
(2022年11月18日由Taylor Blau -- ttaylorr --合并至commit 35dc2cf
第1001章:避免无意引用删除
报告人:herr.kaste
帮助人:菲利普伍德
协助人:Derrick Stolee
签署人:维多利亚染料
签署人:泰勒·布劳
b3b1a21(“sequencer:rewrite update-refs as user edites todo list”,2022-07-19,Git v2.38.0-rc 0--merge列在batch #8中),添加了“todo_list_filter_update_refs()”步骤来处理从“rebase-todo”中删除“update-ref”行。
具体地说,如果ref没有相应的“update-ref”行,它将从“update refs state“中删除潜在的ref更新。
但是,由于如果"refs_to_oids“列表为空,则" write_update_refs_state()”将不更新状态,因此删除 * 所有 *“update-ref”行将导致状态保持与初始化时的状态相同(所有引用“after”OID为空)。
然后,当应用引用更新时,所有引用将被更新为空,并因此被删除。
要解决此问题,请在“refs_to_oids”为空时删除“update-refs”状态文件。
此外,添加涵盖“已删除所有update-ref行”情况的测试。

相关问题