清除已删除文件的git历史记录,保留已重命名文件的历史记录

清除已删除文件的git历史记录,保留已重命名文件的历史记录,git,version-control,git-filter-branch,Git,Version Control,Git Filter Branch,我想将一些文件提取到一个新的repo,保留它们的历史,包括文件重命名 我能找到的最好和最接近的答案是,使用git filter branch--index filter。它成功地保留了现有文件的历史记录,但不保留重命名文件的历史记录 (我能找到的另一个答案是使用git filter branch--subdirectory filter。但它有两个问题:似乎不适用于整个repo(文件夹“.”),并且不保留重命名文件的历史记录。) (另一个答案是使用git子树。但它根本不保留历史。) 因此,我可能

我想将一些文件提取到一个新的repo,保留它们的历史,包括文件重命名

我能找到的最好和最接近的答案是,使用
git filter branch--index filter
。它成功地保留了现有文件的历史记录,但不保留重命名文件的历史记录

(我能找到的另一个答案是使用
git filter branch--subdirectory filter
。但它有两个问题:似乎不适用于整个repo(文件夹“.”),并且不保留重命名文件的历史记录。)

(另一个答案是使用
git子树
。但它根本不保留历史。)


因此,我可能正在寻找一种方法来改进
git ls files>将这些.txt
命令从最接近的答案保留到列出所有以前的文件名。可能是脚本?

Git不存储文件名更改

每个提交存储一个完整的树,例如,可能提交
1234567…
有文件
README
foo.txt
和提交fedcba9。。。有文件
readme.txt
foo
。如果让git将commit
1234567
与commit
fedcba9
进行比较,并且
README
README.txt
非常相似,git会说将一个提交转换为另一个提交的方法是重命名文件。(如果一个提交是另一个提交的父级,则子提交的
git show
将显示重命名,因为
git show
git show
时间计算此更改。)

另一方面,如果第二个
自述文件
差异太大,但
自述文件
foo
非常相似,git会说更改
1234567
以实现
fedcba9
的方法是将
自述文件
重命名为
foo

关键是git会在您请求比较时进行计算,而不是更早。在提交之间没有写“重命名某些文件”的内容。Git只是比较提交,然后决定文件是否足够相似

出于您的目的,这最终意味着对于要复制或部分复制的提交序列中的每个提交,您必须决定保留哪些路径名,以及放弃哪些路径名。如何做到这一点主要取决于你。
git log
命令确实有一个
--follow
标志,当它从子提交到其父提交向后工作时,会激活有限数量的重命名检测,并且
git bull
会自动尝试这样做;您可以使用这些(一次一个路径名)来生成表单的映射:

      in:   commits A..B    C..D             E..F
use path:   dir/file.ext    dir/frill.txt    lib/frill.next
比如说。但这并没有内在的东西,也不会特别容易。我首先将
git log--follow
--raw
--name status
输出相结合,并查看是否检测到任何有趣的重命名。如果存在,则这些是提交边界,在执行提交时,您需要更改保留和放弃的路径(无论是使用
过滤器分支
还是其他方法)

如果这不起作用,或者您需要更多的控制,请考虑在不同的提交对之间运行<代码> Git DIF-name状态< /代码>(提交代码信息来自<代码> GIT Rev List)。


1只要您要求进行重命名检测,“完全相同”就足够相似,任何低至“50%相似”的情况都一样。您可以使用提供给
git diff
-M
标志的可选值调整所需的相似性


编辑:这似乎可以正常工作。我在git自己的
builtin/var.c
上使用了它,根据这一点,它以前有两个名称:

$ git log --follow --raw --diff-filter=R --pretty=format:%H builtin/var.c
81b50f3ce40bfdd66e5d967bf82be001039a9a98
:100644 100644 2280518... 2280518... R100       builtin-var.c   builtin/var.c

55b6745d633b9501576eb02183da0b0fb1cee964
:100644 100644 d9892f8... 2280518... R096       var.c   builtin-var.c
--diff过滤器
会抑制除重命名输出之外的所有内容,以便查看哪个提交似乎会重命名文件。将其转化为更有用的功能需要做更多的工作,但这可能会让您走得更远:

git log --follow --raw --diff-filter=R --pretty=format:%H builtin/var.c |
while true; do
    if ! read hash; then break; fi
    IFS=$'\t' read mode_etc oldname newname
    read blankline
    echo in $hash, rename $oldname to $newname
done
产生了:

in 81b50f3ce40bfdd66e5d967bf82be001039a9a98, rename builtin-var.c to builtin/var.c
in 55b6745d633b9501576eb02183da0b0fb1cee964, rename var.c to builtin-var.c

你能提供一个脚本来列出以前的文件名吗?我不知道怎么做,而且我有数百个文件要处理,所以不能一次手动分析一个文件的日志。默认50%相似对我来说很好。多亏了你,我在read-r行中获得了带有
git ls files |的旧文件名列表;do(git log--follow--raw--diff filter=R--pretty=format:%H“$line”|为true;do if!读取哈希;然后break;fi;IFS=$'\t'读取模式\u等oldname newname;读取空行;echo$oldname;done);完成