在git或git svn中,如何修改历史记录以仅包含当前头部上存在的文件?

在git或git svn中,如何修改历史记录以仅包含当前头部上存在的文件?,git,git-svn,git-rewrite-history,Git,Git Svn,Git Rewrite History,五年前有人问——我会用不同的措辞再试一次 我想将一个现有的Subversion存储库迁移到git,并利用这个机会清除所有不会影响我当前的trunk/master头部的历史记录,然后再与同事共享(当然,所有其他历史记录都应该保持完整) 我的想法是首先git svn克隆repository(故意不使用分支): 。。然后,使用如下魔法删除所有我不再需要的文件: for f in $(all_deleted_files) do git filter-branch --tree-filter '

五年前有人问——我会用不同的措辞再试一次

我想将一个现有的Subversion存储库迁移到git,并利用这个机会清除所有不会影响我当前的
trunk
/
master
头部的历史记录,然后再与同事共享(当然,所有其他历史记录都应该保持完整)

我的想法是首先
git svn克隆
repository(故意不使用分支):

。。然后,使用如下魔法删除所有我不再需要的文件:

for f in $(all_deleted_files) 
do
    git filter-branch --tree-filter 'rm -f ${f}' HEAD
done 
当然,现在的大问题是:如何获取所有已删除的文件

我可以编写一个漂亮的Python脚本,收集所有提交中的所有文件,并减去头部仍然存在的文件。但这是唯一可能的办法吗

以前有没有人这样做过,想用他的剧本给我留下深刻印象

使用不同的(特定于Subversion的)方法-是否可以不克隆后来被删除的文件?

我认为以前没有人(或许多人)这样做过,因为这对大多数repo来说没有太多意义。通常,同一回购协议中的不同文件形成一个单元,因此忽略后来删除的文件的历史会破坏大多数回购协议的整个历史。如果某个文件被重命名,您也会在重命名之前丢失历史记录

如果您真的想这样做,应该执行以下操作:

git filter-branch --prune-empty --tag-filter cat --tree-filter 'files="$(git diff master --no-renames --diff-filter ACMRTUXB --name-only)" && if [ -n "$files" ]; then rm -f $files; fi' master
我认为以前没有人(或许多人)这样做过,因为这对大多数回购协议来说没有太多意义。通常,同一回购协议中的不同文件形成一个单元,因此忽略后来删除的文件的历史会破坏大多数回购协议的整个历史。如果某个文件被重命名,您也会在重命名之前丢失历史记录

如果您真的想这样做,应该执行以下操作:

git filter-branch --prune-empty --tag-filter cat --tree-filter 'files="$(git diff master --no-renames --diff-filter ACMRTUXB --name-only)" && if [ -n "$files" ]; then rm -f $files; fi' master

如果你得到答案,我想说你的代码会运行很长时间。循环每个文件的整个提交历史记录。最好把你的循环放在树形过滤器里。实际上它运行得很快。您不必检查所有历史记录,只需从
HEAD
开始迭代每次提交,获取
对象并收集文件名(和重命名)。我以前也做过类似的事情,但目的不同,所以我想我要花很长时间才能实现这一点..参见5年前类似问题中的另一个相关问题。将
--all
替换为只过滤
HEAD
即可执行当前分支,当然也可以替换为要保留的适当文件列表中的文件。附录一:我看到您提到了重命名的文件。记住Git不跟踪文件名;它试图在比较任何两个提交(相邻或不相邻)时动态检测“相似内容”。我不确定SVN是如何识别隐藏的文件的,但是如果你想检测Git中的重命名,你需要一些新奇的东西。如果你得到答案,我想说你的代码会运行很长时间。循环每个文件的整个提交历史记录。最好把你的循环放在树形过滤器里。实际上它运行得很快。您不必检查所有历史记录,只需从
HEAD
开始迭代每次提交,获取
对象并收集文件名(和重命名)。我以前也做过类似的事情,但目的不同,所以我想我要花很长时间才能实现这一点..参见5年前类似问题中的另一个相关问题。将
--all
替换为只过滤
HEAD
即可执行当前分支,当然也可以替换为要保留的适当文件列表中的文件。附录一:我看到您提到了重命名的文件。记住Git不跟踪文件名;它试图在比较任何两个提交(相邻或不相邻)时动态检测“相似内容”。我不确定SVN是如何识别隐藏在引擎盖下的文件的,但如果您试图检测Git中的重命名,则需要一些新奇的东西。