假设我在Git中有一个分支结构,看起来像master -> A -> B
。也就是说,A
包含在master
之上的提交,而B
包含在A
之上的提交。
我想重新格式化A
,而不会导致B
中发生大量冲突,需要手动解决。如果我没记错的话,可以使用git filter-branch进行此操作,除非我不想更改master
中的任何内容。 (即,我不想使项目中的所有公共Git提交ID失效。)
[git filter-branch
和A
上是否有通往B
的方法(或者正好出于我的目的,仓库中的所有分支except master
)?
编辑:尤其是,git filter-branch ... A B
是否足够?这样可以避免触摸master
并使A
和B
彼此保持一致(即,将A
和B
之间的公共提交重写为相同的提交ID,并且不允许它们重复)或类似这一点)。
git filter-branch ... A B
否,这会将分支A和B处理回根提交。我会这样:
A_behind_B=`git rev-list --count A..B`
git filter-branch ... master..B # or ^master B
git checkout A
git reset --hard B~$A_behind_B
计算A在B后面的提交数。对从filter-branch
到B的提交运行master
。将A重置为在新B后面的提交。
您在这里有关于如何使用过滤器分支的正确总体思路,但是语法错误。要使git filter-branch
复制(并过滤)名称A
和B
都可以到达的提交,但不复制并过滤从master
可以到达的提交,请使用以下语法:
git filter-branch <options> -- ^master A B
[我们在git rev-list
参数^master A B
处所做的操作正在告诉Git:查找从A
或B
可以到达的所有提交,不包括从master
可以到达的所有提交。因此,如果提交链转到:
...--o--o--o <-- master
\
o--o--o <-- A
\
o--o <-- B
例如,选择中间和底部行提交。与^master B
一样,甚至使用master..B
或phd's answer也可以,但这有两个原因。首先,它仍然会选择所有带有以下内容的中间行提交:
...--o--o--o <-- master
\
o--o--o <-- A
\
o--o <-- B
(尽管这可能不是您的结构)。其次,after复制(和过滤)指定的提交,以便最终使用:
o--o <-- [filtered copy of commit to which B points]
/
o--o--o [filtered copy of commit to which A points]
/
...--o--o--o <-- master
\
o--o--o <-- A
\
o--o <-- B
filter-branch命令将移动所有the documentation称为正引用的内容。正引用是在其前面没有取反的引用:在这种情况下,A
和B
而不是master
,因为master
被写为^master
,因此是负引用。
因此,它不会触及master
(无论如何也不会—它的提交不会被复制),但是will将名称A
和B
移到上方,以便它们指向复制的提交。