我们需要在一个repo上的一个特定的过去提交中添加一些文件,我们准备重写历史,这样它就可以影响到从那个提交的孩子分支出来的所有分支。我们尝试使用git filter-branch,使用add,因为一旦我们将文件添加到提交中,它就不会被添加到子提交中,但是我们找不到合适的参数来阻止它影响一些并发的发散提交。见图片了解。
我们使用这个命令来处理红色提交,但是文件却出现在紫色提交上-为什么?- 它也出现在绿色提交中,我们不希望它影响代码路径,只是出现在红色提交中,然后通过所有子提交和合并继承。git filter-branch --index-filter "cp C:/Users/asdf/Documents/IdeaProj ects/git-crypt-tests/.gitattributes . && git add .gitattributes" 72c7e292ddd134c04285f3530afc829fd38de4 28..HEAD
我理解错了什么?
谢谢你。
2条答案
按热度按时间ua4mk5z41#
看起来你认为当你写一个提交范围为
A..B
时,它会包括边界。但事实并非如此。这个符号是B ^A
的缩写,即所有导致B
的内容,但不包括所有直到A
的内容。这将从范围中删除“下限”A
。解决方案是写A~
,意思是“A
的祖先”:A~..B
。此外,由于您确切地知道您想要添加文件到哪些提交以及您不想添加它们,因此您可以限制修订步行者仅列出想要的提交:
也就是说,你说你希望所有的提交都指向
HEAD
,但不希望在72c7e29~
之前,也不希望在消息以Fix Prestapp
开头的提交之前。3duebb1j2#
这只是另一种通用的方式来重写任何提交树中的单个提交,而无需构建一个棘手的rev-list。
1.如果不存在,则在提交时创建标记-
my-tag
。1.说
或者使用简写代替
my-tag --not my-tag^@
:my-tag^!
1.如果在步骤(1)中添加了标记,则删除该标记。
它更快,因为不需要知道提交树结构。
如果你想重写一个提交和它的子提交,那么你可以使用git replace(
git replace --graft <commit> [<parent>…]
)和git filter-repo脚本来将更改传播到子提交中:更新所有子分支
提交修改和清理
,其中:
<commit-child-*>
-重写提交的子对象。<commit-child-*-parents>
-包含重写提交的提交列表。所以,在一个简单的单子节点的情况下,它将只是一个带有一个提交的单个调用:
注:
如果你试图替换一个文件,并且它在下一个子提交中有更改,例如
changelog.txt
文件,那么你必须在每个下一个子提交中重写它,否则下一个提交将保留旧文件。在这种情况下,实际上使用git filter-repo
与文件文本搜索和替换,而不是文件添加/替换或手动重写每个下一个子提交之前,调用git replace --graft ...
。