这个代码库派生自哪个Git提交?

时间:2016-11-25 03:46:02

标签: git

作为一名顾问,我常常发现自己处于遗留一堆代码库的情况下,在未知的时间点从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哈希值。

1 个答案:

答案 0 :(得分:3)

很多想法都出现了,从天真开始(我将检查每个转速,运行diff -rUN,将其展开,将其浓缩为数字......)当您拥有数千个文件时,这是不可行的成千上万的提交要覆盖疯狂(我会在每个文件上运行Which commit has this blob?并提交,将它放在某个数据库中并根据链接的答案松散地写一些查询......)。

我们的想法是首先存储当前文件的哈希值,然后比较它以列出给定提交中每个blob的哈希值并对匹配进行评分。

  1. 评分程序只是grep,它可以读取字符串列表(模式甚至我们有字符串)并计算这些字符串在输入中出现的次数。
  2. git ls-tree -r在提交中转储blob哈希值(还有更多,但我们不关心)
  3. git hash-object为现有文件生成与git ls-tree相同的哈希值。
  4. 我使用了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"提交的数量非常相似但数量较少。