我正在分析修订历史,使用git-archive
获取特定修订的文件(请参阅https://stackoverflow.com/a/40811494/1168342)。
这种方法是可行的,但我正在努力为有许多修订的项目进行优化。许多处理都浪费在归档(通过tar)和返回到另一个目录中的文件(再次通过tar)上。
我正在寻找一种不涉及tar
的方法,类似于git cp $revision $dest/
。以下是我迄今为止探索的内容:
-
我可以使用带有文件副本的
git reset $revision --hard
方法,但它会导致分析的并行化无效,除非我创建多个repo副本(每个线程/进程一个)。 -
有一个使用JGit的Java项目名为Doris,它通过低级操作实现了这一点,但当出现奇怪的文件(例如,指向其他repo的链接)时,它就会中断。随着git的发展,有很多特殊情况,所以如果可能的话,我不想在低级别上这样做。
-
我知道Python有一个git API,但它的归档功能也使用tar。出于与上述相同的原因,我不想将其编码到太低的级别。
使用:
mkdir <path> &&
GIT_INDEX_FILE=<path>/.git git --work-tree=<path> checkout <revision> -- . &&
rm <path>/.git
git checkout
步骤将覆盖索引,因此为了使此并行化良好,我们可以将索引文件指向目标。有一个文件名是非常安全的:.git
!
(这就像git worktree add
的轻量级版本,它也避免了将新提取的树记录为活动工作树。)
编辑以添加旁注(我希望OP知道这一点,但供将来参考):注意git archive
应用了该技术不应用的某些.gitattributes
过滤器。特别地,git checkout
将不服从export-ignore
和export-subst
指令。
在JGit中,ArchiveCommand
实现了git archive
的功能,还提供了几种现成的归档文件格式。但是,ArchiveCommand
可以使用自定义存档格式进行扩展。
自定义格式需要实现Format
接口并将其注册到ArchiveCommand::registerFormat
。即使相应的API设计时似乎考虑到了单个输出文件,也应该可以将内容输出到目录中。