Как git выбирает коммиты, связанные с файлом? - PullRequest
2 голосов
/ 16 мая 2010

Я пишу простой парсер файлов .git / *. Я покрыл почти все, как объекты, ссылки, файлы упаковки и т. Д. Но у меня есть проблема. Допустим, у меня есть большой 300M репозиторий (в файле пакета), и я хочу узнать все коммиты, которые изменили / some / deep / inside / file file. То, что я делаю сейчас:

  • выборка последнего коммита
  • найти файл в нем:
    • извлечение родительского дерева
    • обнаружение дерева внутри
    • рекурсивно повторять, пока я не попаду в файл
    • дополнительно я проверяю хэши каждой подпапки на пути к файлу. Если один из них такой же, как в коммите ранее, я предполагаю, что файл не был изменен (поскольку его родительский каталог не изменился)
  • затем я сохраняю хеш файла и извлекаю родительский коммит
  • найти файл еще раз и проверить, происходит ли изменение хеша
    • если да, то исходный коммит (то есть один перед родителем) изменял файл

И я повторяю это снова и снова, пока не достигну самого первого коммита.

Это решение работает, но оно отстой. В худшем случае первый поиск может занять даже 3 минуты (для пакета 300 МБ).

Есть ли способ ускорить его? Я старался не помещать в память такие большие объекты, но сейчас я не вижу другого пути. И даже при этом начальная загрузка памяти будет длиться вечно: (

Привет и спасибо за любую помощь!

1 Ответ

1 голос
/ 16 мая 2010

Это основной алгоритм, который git использует для отслеживания изменений в конкретном файле. Вот почему «git log - some / path / to / file.txt» является сравнительно медленной операцией по сравнению со многими другими системами SCM, где это было бы просто (например, в CVS, P4 и др. Каждый файл репо является файлом сервера с история файла).

Это не займет много времени, чтобы оценить, хотя: количество, которое вы когда-либо должны хранить в памяти, довольно мало. Вы уже упомянули основной момент: помните, что идентификаторы дерева, идущие вниз по пути, быстро устраняют коммиты, которые даже не затрагивают это поддерево. Древовидные объекты редко бывают такими большими, как каталоги в файловой системе (что неудивительно).

Используете ли вы индекс пакета? Если нет, то вам нужно распаковать весь пакет, чтобы выяснить это, поскольку деревья могут находиться в конце длинной цепочки дельта. Если у вас есть индекс, вам все равно придется применять дельты для получения объектов дерева, но, по крайней мере, вы сможете быстро их найти. Сохраняйте кэш примененных дельт, поскольку деревья, очевидно, часто используют одни и те же или похожие базы - большинство изменений объекта дерева просто изменяют 20 байтов от предыдущего объекта дерева. Так что если для получения дерева T1 вам нужно начать с объекта T8 и применить Td7, чтобы получить T7, T6 ... и т. Д., Вполне вероятно, что на эти другие деревья T2-8 снова будут ссылаться.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...