作为一名顾问,我常常发现自己处于遗留一堆代码库的情况下,在未知的时间点从git clone
或dev tarball开始。如何找到它从哪个提交开始?
代码库不是精确的Git结帐,文件经过编辑,添加等等。
为了澄清,假设您继承的代码库包含一个名为bootstrap
的子目录。它显然包含Bootstrap项目,您想要更新它。你所知道的是,在某些时候,git clone git@github.com:twbs/bootstrap.git
或下载https://github.com/twbs/bootstrap/archive/v4-dev.zip下载了twbs / bootstrap。
在此初始操作之后,在此子目录中发生了一些不加选择的黑客攻击,其中文件被更改,删除和添加。我想将其更新到最新版本。为此,我想找出初始下载对应的Git哈希值。
答案 0 :(得分:3)
很多想法都出现了,从天真开始(我将检查每个转速,运行diff -rUN
,将其展开,将其浓缩为数字......)当您拥有数千个文件时,这是不可行的成千上万的提交要覆盖疯狂(我会在每个文件上运行Which commit has this blob?并提交,将它放在某个数据库中并根据链接的答案松散地写一些查询......)。
我们的想法是首先存储当前文件的哈希值,然后比较它以列出给定提交中每个blob的哈希值并对匹配进行评分。
grep
,它可以读取字符串列表(模式甚至我们有字符串)并计算这些字符串在输入中出现的次数。git ls-tree -r
在提交中转储blob哈希值(还有更多,但我们不关心)git hash-object
为现有文件生成与git ls-tree
相同的哈希值。我使用了tmpfs - 虽然过早的优化可能是所有邪恶的根源,但这种优化的成本很少,我发现它更容易。我在根目录中有这个脚本:
#!/bin/sh
echo "$(git ls-tree -r $1|grep -c -F -f ../hashes.txt) $1"
并将有问题的代码库置于mess
下,将原始git克隆置于base
下。
cd mess
find . -type f -print0| xargs -0 -P8 git hash-object >> ../hashes.txt
cd ../base
git log --all --format=%H |xargs -n1 -P8 ../script.sh |sort -n|tail
这在几分钟内完成(但我作弊了一点因为我在git log
上有一些日期限制但是考虑到用例,你很可能也会有这样的日期限制)。我的输出如下:
9548 0ceb441a75cd4cd11427da2b37efd49c99f9e562
9549 8f2c0537da72bb7ca866e6847bf887811ab3c72e
9550 5cd36afbe23310c17caf4075d29c70a4b2252295
9550 8da13e6c60255d2b8008d8de3d3e64de91d2bf7a
9551 2be39c73876f9d22f8cea40777d082e3fba4cbd4
显然2be39c7
有9551个匹配文件,并且它不是一些破坏的异常值,因为" neigbhouring"提交的数量非常相似但数量较少。