如何在git repo的特定目录中还原所有已删除的文件?

时间:2019-07-26 16:44:24

标签: git

我们想在git repo的特定目录及其所有子目录中恢复已删除的文件。

该目录包含我们的数据库迁移。名称和内容可以更改(重命名,删除,添加),并且在过去5年或5年内都可以更改。

我们现在意识到我们还没有所有迁移的完整列表,因此想从存储库中恢复它们。

我们想要实现的是在删除之前将所有文件还原为它们的最后一种格式。

据我了解,这对所有重命名的文件可能并不特别有效,但我们可以手动对其进行整理。

每个文件的名称都有2个部分,一个时间戳和一个迁移名称-名称保持不变,但是时间戳部分在重命名过程中会更改。

例如: 20150101010101_inital_migration.sql可能已重命名为20150101010102_inital_migration.sql。

内容可能略有变化,但名称的“ initial_migration”部分不会更改。不知道这是否有任何用处,但是如果在git本身内没有办法进行重命名,那将是我们如何检测重命名。

如果文件更改是如此不同,以致于记录为实际删除和新文件,则删除之前的文件将生效。一旦文件的所有最终形式都存在,我们便可以浏览文件。

1 个答案:

答案 0 :(得分:0)

与很多事情一样,总是有其他方法来思考问题。

因此,git log命令可以向我显示从特定目录中删除文件的提交哈希。

git log --diff-filter=D --summary --oneline migrations/

处理此输出需要读取2种不同类型的线并使用两条线中的值。

第一行包含哈希,另一行包含文件名。

因此,使用基于PHP的过滤器将日志输出转换为命令列表以还原文件非常简单。

<?php

$lastHash = null;

while (false !== ($line = fgets(STDIN))) {
    // Is the line a hash?
    if (preg_match('`(?P<hash>[a-f0-9]{10}) `', $line, $matches)){
        $lastHash = $matches['hash'];
    } else {
        preg_match('`(?P<file>migrations/.*$)`', $line, $matches);
        echo sprintf('git checkout %s~1 "%s"', $lastHash, $matches['file']), PHP_EOL;
    }
}

这将生成类似

的输出
git checkout a653b7f95a~1 "migrations/20140514122900_populate_dimensions.php"
git checkout 75a2989b5b~1 "migrations/20140116173610_drop_xusers_copy.php"
git checkout b0de683071~1 "migrations/20140114163419_initial_migration.php"

然后,通过bash运行此输出将恢复所有已删除的文件。