如何从git';在保留尽可能多的历史记录的同时,是否保留历史记录?
TL;DR:我们的git存储库中有一个短语必须从历史中删除,而不仅仅是分支机构的负责人。除了将其从开发和创建新存储库的负责人中删除之外,还有什么其他方法?我们希望尽可能多地保留历史 背景 出于令人讨厌的法律原因,我和我的团队必须从我们的代码库中删除一个单词的所有实例(我们称之为伏地魔只是为了好玩和相关性)。令人恼火的是,我们不仅需要从分支的顶端删除伏地魔,我们还需要从我们存储库中的每个提交中删除它(这场诉讼的意思是“没有开发人员能够合理地恢复到伏地魔在代码中的状态”) 我们不再使用伏地魔了,但是代码中有一些地方仍然像注释一样提到伏地魔。(是的,作为诉讼的一部分,我们必须从代码中删除侵权评论。) 最初的计划是清除不能提及的单词,然后创建一个新的存储库,并将当前状态作为初始提交。但我们不想失去所有的历史!所以我们想知道是否有办法避免这种情况 那么,问题是我们如何从历史中删除伏地魔这个不可提及的词,同时尽可能多地保留历史1?此外,我们可以做些什么来确保它不存在?我们想知道如何检查我们的工作,以确保它消失了 1:历史不是指具体的提交,我只是指能够查看文件的历史,知道谁做了什么,如果历史像git意义上的“重写历史”那样消失了,我觉得这是唯一的方法 回购协议状态信息如何从git';在保留尽可能多的历史记录的同时,是否保留历史记录?,git,Git,TL;DR:我们的git存储库中有一个短语必须从历史中删除,而不仅仅是分支机构的负责人。除了将其从开发和创建新存储库的负责人中删除之外,还有什么其他方法?我们希望尽可能多地保留历史 背景 出于令人讨厌的法律原因,我和我的团队必须从我们的代码库中删除一个单词的所有实例(我们称之为伏地魔只是为了好玩和相关性)。令人恼火的是,我们不仅需要从分支的顶端删除伏地魔,我们还需要从我们存储库中的每个提交中删除它(这场诉讼的意思是“没有开发人员能够合理地恢复到伏地魔在代码中的状态”) 我们不再使用伏地魔了,但是
- 目前developbranch没有伏地魔,但是在清除提交之前和之后我们都有“有意义的”提交
- 可能只有最初的提交有任何添加伏地魔行的内容(因为我们从SVN迁移到git,伏地魔是在很久以前添加的)
- 用伏地魔修改任何文件的唯一承诺可能是那些删除了它的人(就像我说的,这是很旧的东西)
似乎我们想做一些类似于git log的事情——补丁| grep‘Voldemort’来查找添加伏地魔的提交,然后对添加伏地魔的提交进行交互式重新基址编辑,以添加其他内容或什么都不添加。查看
git筛选器分支
使用,它比git filter branch更快更容易使用
要将所有文件中出现的伏地魔
替换为删除的*********
,您只需:
% echo 'Voldemort' > badwords.txt
% bfg --replace-text badwords.txt myrepo.git
我感谢伊万·梅勒为我指出了正确的方向,但答案很小,我认为这需要更多的细节
提醒 如果您在执行此操作之前重新克隆了repo,请确保您拥有所有远程设备的本地分支(例如,
git checkout master;git checkout develope;git checkout feature/some undone feature
等)
我们所做的
>git筛选器分支--树筛选器“~/purge.sh”\
--msg过滤器“sed-e's/voldemort//gI”\
--标签名称过滤器“cat”\
----全部
清除脚本(可能只有一行,但更简洁,如下所示):
#/bin/bash
文件=$(grep-rli“伏地魔”)
对于${files}中的文件;做
sed-i-e's/voldemort//gI'${file}
完成
下一步 完成后,您需要检查以下问题:
git filter branch
生成的备份解释
--树过滤器“~/purge.sh”
- 对于每个提交,针对工作树运行
脚本(~/purge.sh
)--tree filter…
- 列出包含伏地魔的文件列表(
)grep…“伏地魔”
- 从这里递归地列出名称(而不是内容),不考虑大小写(
)-rli
- 对于列表中的每个文件(
)对于${files}中的文件;do
- 在该文件(
)中将单词短语sed…-es/../../${file}
的每个实例替换为voldemort
) - 在没有备份的情况下就位(
)-i
- 在该文件(
- 列出包含伏地魔的文件列表(
- 对于每个提交,针对工作树运行
--msg过滤器“sed-e's/voldemort//gI'”
- 用
(sed-e
)替换单词短语s/../…/
的每个实例voldemort
- 即使一行有两个,也不考虑大小写(
)/gI
- 在提交消息中--msg filter…
- 用
--标签名过滤器“cat”
- 对于每个标记,在新提交时将其重命名为其旧名称(如果不存在此名称,标记将不会继续)
--all
- 对存储库中的每个提交执行此操作(是的,即两个破折号后跟一个空格,然后再加两个破折号)
关于性能的说明 你可能想知道,为什么我们不简单地对
--tree filter
中的每个文件执行sed-i-e's/voldemort//gI'
> git filter-branch --tree-filter "~/purge.sh" \
--msg-filter "sed -e 's/voldemort/<word removed due to lawsuit>/gI'" \
--tag-name-filter "cat" \
-- --all
#!/bin/bash
files=$(grep -rli 'voldemort')
for file in ${files}; do
sed -i -e 's/voldemort/<word removed due to lawsuit>/gI' ${file}
done