如何重基本地git分支链?

w8f9ii69  于 2023-08-01  发布在  Git
关注(0)|答案(6)|浏览(122)

假设我有一个本地git分支链,像这样:

master    branch1   branch2
          |         |         |
o----o----o----A----B----C----D

字符串
我将一个上游更改拉入主分支:

branch1   branch2
                 |         |
            A----B----C----D
           /
o----o----o----o
               |
            master


现在我重新设置branch 1的基,给我这个:

branch2
                           |
            A----B----C----D
           /          
o----o----o----o----A'---B'
               |         |
            master    branch1


请注意,由于branch 1的重基化,提交A和B已经被重写为A'和B'。
我的问题是现在我想重新设置branch 2的基。显而易见的语法是git rebase branch1 branch2,但这绝对不起作用。我想让它在分支1上重新应用C和D,但是它试图调和A和A',它认为它们是冲突的。
这确实有效:

git rebase --onto branch1 branch2^^ branch2


这假设我知道branch 2在前一个branch 1 ref之外有2个提交。
既然git rebase --onto可以工作,那么有没有一个1行的git命令可以在一个新的branch 1上重新设置branch 2,这样我就不需要知道branch 2中到底有多少提交?(我想为中间的参数指定一些magic ref,而不是branch 2 ^^。)
还是我忽略了其他方法?
我最感兴趣的是一个可以很好地扩展到极端情况的解决方案,而不仅仅是两个分支--假设我有更像是5个局部分支,所有分支都是相互链接的,我想把它们都重新建立在一起。

cbjzeqam

cbjzeqam1#

2022:我在去年8月的“Git interactive rebase: how to move other branches (refs) automatically?”中描述了一个新的rebase选项--update-refs(Git 2.38,Q3 2022):
自动强制更新任何指向正在被重定基的提交的分支。
在工作树中检出的任何分支都不会以这种方式更新。

branch1   branch2
                 |         |
            A----B----C----D
           /
o----o----o----o
               |
             main
git switch branch2
git rebase --update-refs main
branch1     branch2
                       |           |
                 A'----B'----C'----D'
                /
o----o----o----o
               |
             main

2013年:单线:

git rebase --onto branch1 branch1tmp branch2


假设在 * 重定branch1的基之前,在branch1 * 上生成branch1tmp

git checkout branch1
git branch branch1tmp
git rebase master
git rebase --onto branch1 branch1tmp branch2


也就是说,检查ORIG_HEAD引用了什么。
git rebase man page
ORIG_HEAD被设置为在复位之前指向分支的尖端。
所以检查一下这是否有效(并更好地扩展):

git checkout branch1
git rebase master
git rebase --onto branch1 ORIG_HEAD branch2
git rebase --onto branch2 ORIG_HEAD branch3
...

v2g6jxz6

v2g6jxz62#

git rebase master branch1
git rebase --onto HEAD ORIG_HEAD branch2
git rebase --onto HEAD ORIG_HEAD branch3
# ...
git rebase --onto HEAD ORIG_HEAD branchN

字符串
我有一个git alias脚本来做这件事:

rebase-chain = "!f() { \
  for i in ${@}; do \
    git rebase --onto HEAD ORIG_HEAD $i; \
  done; \
}; f"


这可以使工作流程如下:

git rebase master branch1 # start with a normal rebase
git rebase-chain branch2 branch3 branch4 ... branchN

奖金

假设你有bash-completiongit

__git_complete "git rebase-chain" _git_branch

v1l68za4

v1l68za43#

此问题是“修改基分支并同时对所有子分支重新定基”的子集
我最近开始使用git-chain,这是一个解决这个问题的工具.
基本上,您可以指定一个链

git chain setup -c myfeature master branch1 branch2

字符串
一旦建立了这个链,你就可以从master中提取提交,然后你就可以运行git chain rebase -c myfeature,这个工具会计算出所有的引用,并为你很好地重定所有内容的基。
作为一个额外的好处,它还可以计算和处理对branch1branch2的任何修改或新提交。

gajydyqb

gajydyqb4#

git-branchless工具套件可以巧妙地解决这个问题:

$ git move -s A -d master

字符串
免责声明:我是作者。
这将重定A的基,以及它的所有后代,以及指向任何这些提交的任何分支。参见documentation for git move

r1wp621o

r1wp621o5#

Git 2.38有一个新的标志--update-refs来解决这个问题。在您的示例中:

git rebase --update-refs master

字符串
范例:

$ git checkout branch2
$ git log --decorate --all --oneline --graph
* 5b08e54 (master) 4
* 6790fdc 3
| * ee84471 (HEAD -> branch2) branch commit 4
| * 9da7c93 branch commit 3
| * c250fc6 (branch1) branch commit 2
| * bd5f222 branch commit 1
|/
* 2ec36a0 2
* ecce5ff 1
* 8bb07ae (tag: root) root
$ git rebase --update-refs master
Successfully rebased and updated refs/heads/branch2.
Updated the following refs with --update-refs:
    refs/heads/branch1
$ git log --decorate --all --oneline --graph
* b37f0c7 (HEAD -> branch2) branch commit 4
* c20fc6f branch commit 3
* a231606 (branch1) branch commit 2
* 0e81768 branch commit 1
* 5b08e54 (master) 4
* 6790fdc 3
* 2ec36a0 2
* ecce5ff 1
* 8bb07ae (tag: root) root


注意:我只将链中的“最后一个”分支(branch2)重定基到新的基础(master)上,中间的分支(branch1)自动沿着。

tez616oj

tez616oj6#

我喜欢的是git checkout branch2 ; git rebase -i master直接在编辑器中显示branch1,然后当我保存编辑器时,branch 1得到相应的更新。所以我可以直接在git rebase -i中将一个提交从branch 2移动到branch 1,并有“坚持”。也许用一个'--rebase-branches'或什么的。
所以啊,我和你一样痛苦。
我所做的是模仿这个缺失功能的黑客。我经常发现,在创建长期分支的过程中,我一直在积累应该在“this”分支之前进入master的东西。修复违反编码标准的问题,发现并修复明显的错误,更新现有代码的文档等。这就是我用你的branch1的原因。然后提交实际上是我的新特性的一部分,放在branch2中。
因此,我所做的不是创建branch1分支,而是创建一个branch1伪分支“标记”--一个微小的提交,稍后我将在git rebase中丢弃它。我创建它就像:

touch marker.master
git add marker.branch1
git commit -m "*** BRANCH1 ***" marker.branch1

字符串
现在,当我创建提交时,我混合了应该在这个分支之前进入master的提交和这个实际分支的“新”提交。
当需要清理/变基时,I git rebase -i master。现在我的*** BRANCH1 ***提交在提交列表中是显而易见的,我可以将指向branch1的提交移动到该“行”之上。
因为我没有一个实际的branch1分支,git rebase master完全按照我的要求做,它将branch2和我的branch1伪分支标记作为一个单元移动。
当我完成rebase并准备推送时,我手动记下*** BRANCH1 ***的提交ID,比如abcdef1,然后:

git checkout -b branch1 abcdef1^


然后:

git checkout branch2
git rebase -i branch1


然后删除abcdef1提交。
这样,我就可以在git rebase -i期间轻松地在branch1branch2分支之间移动提交,并且只在最后创建一个真实的的git branch1分支。
但是,哦,我真的很想让git rebase -i为我做这件事!

相关问题