Git查找历史记录中的所有二进制文件

16

如果这是之前的问题的重复,对不起,但我找不到我正在寻找的东西。 我正在将大型cvs代码集(20多个存储库,具有15年的历史记录-10-15 GB大小)转换为git的过程中。 由于在过去提交了与代码一起的二进制文件,因此其中大部分大小都是由此造成的。 尽管某些二进制文件是可以完全删除的文件类型,但保留许多二进制文件及其历史记录是可取的。 然而,我们不希望仓库膨胀。

我们目前计划使用git-fat存储二进制文件,但我正在编写一个脚本来自动转换文件。 我的第一步只是尝试识别所有在存储库中的文件(包括已删除的文件),这些文件都是二进制文件。 是否有任何简单的方法来完成这个任务? 谢谢你的帮助。

编辑

实际上,我认为我找到了一个合理的方法,就是运行

git log --numstat <first commit hash> HEAD

这会打印出所有文件的列表,并在前面添加两列,第一列包含文件更改的次数(我不确定是以字节还是行为单位)。但对于二进制文件,则显示“-”。通过选择带有此标记的行并将它们“去重”,我相信可以获得完整的二进制文件列表。

这个策略有没有缺陷?


我们处于类似的位置,我们决定将项目历史记录保存在svn中,并将所有新工作作为一个新项目导入到git中,没有历史记录。如果有人想查看文件的历史记录,他们可以使用现有的工具进行查看,但是如果他们想要处理代码,那么他们必须从git中获取新的内容。我们认为历史记录很有价值,但是由于它已经在“某个地方”可用,我们不需要担心将其迁移并通过新系统提供(该系统很快就会有自己的历史记录)。 - Software Engineer
是的,我认为我们很可能会将cvs存储库保持在只读模式下。我希望能够完成完整的移植,但这可能不可行。不过,你说得对。 - NotsoDarkMatters
3个回答

14
太长不看;
git log --all --numstat \
    | grep '^-' \
    | cut -f3 \
    | sed -E 's|(.*)\{(.*) => (.*)\}(.*)|\1\2\4\n\1\3\4|g' \
    | sort -u

解释:

git-log选项--numstat

以十进制表示法显示添加和删除的行数,以及完整路径名而不是缩写,以使其更适合机器处理。对于二进制文件,输出两个 - 而不是 0 0

来源:https://git-scm.com/docs/git-log,强调是我的

这将产生以下类似的输出条目:

commit 0123456789012345678901234567890123456789
Author: Joe Example <jexample@domain.com>
Date:   Thu Mar 9 15:33:29 2017 +0000

    edit Dockerfile, add assets/foobar.jpg

1   1   Dockerfile
-   -   assets/foobar.jpg
grep '^-'匹配以连字符开头的行,cut -f3打印第三个以制表符分隔的字段,而
sed -E 's|(.*)\{(.*) => (.*)\}(.*)|\1\2\4\n\1\3\4|g'

检测已移动/重命名的文件并打印源文件和目标文件;例如,它会将以下内容更改为:
path/to/{foo => bar}/my-document.pdf

转换为:

path/to/foo/my-document.pdf
path/to/bar/my-document.pdf

最后,sort -u将累积、排序并去重路径列表。
编辑:此答案假设存在支持扩展正则表达式和捕获组的sed;例如,https://www.gnu.org/software/sed/

@DhruvaN,除非你费尽心思地让grepsedawkcut适用于该shell,否则我严重怀疑。 - rubicks
你对gsed -r ...的解释段落使用了sed -r(而不是GNU Sed)。我认为这是不正确的。 - Guildenstern
1
@Guildenstern 我已经更新,尽可能地与 sed 无关。 - rubicks

2

我是git-fat的一个贡献者之一。

如果您主要关心文件大小而不是特定类型,则git-fat具有find命令,允许您查找git存储库中大于给定大小的所有文件。

我目前为cyaninc的分支做出了贡献,但Jed和Cyan的版本都拥有find命令。

另外,请查看README中的“追溯导入”部分。两个版本也支持此功能。


1
一种解决方案是遍历所有修订版本,获取每个修订版本中的所有文件,获取每个文件的内容,然后获取每个文件的类型,以此来...。
以下是获取所有修订版本列表的方法:
$ git rev-list HEAD
32a9b9158d73dc80b355993a5a5f8fc49ae25334
9946574838bf5f984f5f4a19b2fc524f0a60378c
3f82a5dcecde0028da21fb266c1bbd7e9ec762ec
...

以下是如何获取特定版本中所有文件列表的方法:
$ git ls-tree -r 32a9b9158d73dc80b355993a5a5f8fc49ae25334
100644 blob dcf290b1a99a8d2535b8aa8f85702cd1b7fac6e8    .gitignore
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391    README

您可以通过提供每个版本中每个文件的 blob 来获取每个文件的内容。
git show:
$ git show dcf290b1a99a8d2535b8aa8f85702cd1b7fac6e8
.gitignore

*.pyc
rm_pyc.sh
aima/**/*.pyc
.idea

为了测试一个文件是二进制还是文本,您可以使用 /bin/file 命令:

git show dcf290b1a99a8d2535b8aa8f85702cd1b7fac6e8 > file
/bin/file file
file: ASCII text

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接