Получить изменения между коммитом и его родителем с помощью libgit2sharp
Я работаю с libgit2sharp (оболочкой C# для libgit2) и столкнулся с проблемами, потому что он не обладает достаточной функциональностью, на которую я надеюсь (надеюсь, я скоро смогу внести свой вклад в это; это похоже на действительно полезный проект)
Сейчас я пытаюсь получить список файлов, измененных из определенного коммита и его родителя. Я не буду пытаться выяснить, что изменилось между слиянием и двумя его родителями. Меня больше интересуют регулярные коммиты.
Эти ребята (https://github.com/libgit2/libgit2sharp/issues/89) работают над чем-то похожим. Я думаю, что их процедура - хорошая идея, но я немного слаб в моем понимании внутренних органов GIT (есть множество руководств для руководства конечного пользователя по GIT, но не так много по внутренней структуре)
Мне любопытно, как GIT сам выполняет команду "git diff". Предположительно, GIT на самом деле не хранит дельты, а скорее полную версию файла (если он не изменяется, он просто указывает на существующий SHA. Эту информацию можно найти из различных источников, таких как здесь http://xentac.net/2012/01/19/the-real-difference-between-git-and-mercurial.html). Похоже, это усложняет получение изменений между двумя коммитами (в моем случае - конкретным коммитом и его единственным родителем), потому что данные не сохраняются как часть коммита (что ясно, если вы изучите класс Commit в Commit.cs в libgit2sharp). файл).
То, к чему я могу получить доступ из коммита, это дерево. Имеет ли смысл сделать следующее, чтобы найти эту информацию:
1) Начните с нужного коммита и пройдитесь по дереву и сохраните все значения SHA в наборе.
2) Начните с родительского объекта для требуемого коммита и пройдитесь по его дереву, чтобы сохранить все значения SHA BLOB-объектов в другом наборе.
3) SHA для измененных файлов будут файлами, которые не находятся на пересечении двух наборов.
Проблема, которую я вижу с этим подходом, состоит в том, что он не выглядит так, как будто есть способ получить имя файла из значения SHA большого двоичного объекта (я не вижу ничего, что может сделать это в файле Blob.cs libgit2sharp).
Я знаю, что у этого вопроса есть много аспектов, но они являются частью этой большой цели - получить конкретный фрагмент данных из git.
Благодарю.
1 ответ
То, что вам нужно, функция разграничения деревьев, уже существует в libgit2, как определено в заголовке tree.h.
git_tree_diff()
функция сравнивает два Trees
и вызывает обратный вызов для каждой разницы (добавление, обновление и удаление). Функция обратного вызова передается git_tree_diff_data
структура с указанием пути к файлу рассматриваемого большого двоичного объекта, его статуса, прежнего и текущего файловых режимов и бывшего и текущего SHA.
С точки зрения LibGit2Sharp, было бы более разумным использовать существующую функцию libgit2, а не заново реализовывать их в C#. Тем не менее, даже если вы можете черпать вдохновение из существующих определений Interop, при попытке обуздать.Net/native Interop layer все становится очень сложно.
С вашей точки зрения (так как содействие LibGit2Sharp может и не быть вашей основной целью;)), другой вариант - перенести код C на C#, полагаясь на существующие функции LibGit2Sharp для перехода по деревьям. git_tree_diff()
(и его вспомогательные функции) - очень чистый кусок кода, и хотя он выполняет довольно сложную работу, комментарии очень ясны и полезны.
Рекомендации:
-
git_tree_diff()
функция реализована в src / tree.c - Тесты, использующие эту функцию, доступны здесь.
Примечание: для того, чтобы связать git_tree_diff()
, проблема должна быть открыта в трекере libgit2 с просьбой обновить определение метода, чтобы GIT_EXTERN
"D. В противном случае он не будет доступен из.Net.
ОБНОВИТЬ
В версии v0.9.0 LibGit2Sharp появилась функция разграничения дерева и дерева.
TreeChanges changes = repo.Diff.Compare(fromTree, newTree);
Выставленные свойства:
- Добавлены / изменены строки
- Наборы изменений TreeEntry для каждого вида изменений (например, Added, Modified, ...)
- Патч
Вы можете узнать больше об этой функции и о том, как использовать TreeChanges
посмотрев на модульные тесты в DiffTreeToTreeFixture.cs.