Как восстановить историю файла?

У меня есть еще одна проблема с libgit2, и я буду очень благодарен за вашу помощь.

Я пытаюсь получить историю файлов, то есть список коммитов, в которых этот файл был изменен. И это выглядит довольно нестандартно... Насколько я понимаю, для этого нет никакой функции.

Единственный подход, который я могу придумать, - это использовать API обхода ревизий для перебора ревизий, проверки объекта дерева, прикрепленного к фиксации, и поиска заданного файла там, если он найден, добавить фиксацию в мой список, в противном случае перейти к следующей фиксации.

Но мне он кажется не оптимальным...

Может быть, есть какой-то другой подход, например, заглянуть прямо в папку .git и получить там нужную информацию?

Спасибо заранее!


person shytikov    schedule 23.11.2011    source источник


Ответы (3)


Но мне он кажется не оптимальным...

Ваш подход правильный. Остерегайтесь, что вам придется бороться с:

  • Простое переименование (тот же хэш объекта, другое имя записи в дереве)
  • Переименование и обновление контента происходят в одном и том же коммите (другой хэш, другое имя записи в дереве. Потребуется функция анализа содержимого файла и сравнения, которая недоступна в libgit2)
  • История нескольких родителей (две ветки, которые были объединены и в которых один и тот же файл был изменен по-разному)

Может быть, есть какой-то другой подход, например, заглянуть прямо в папку .git и получить там нужную информацию?

Несмотря на то, что понимание макета папки .git всегда требует потраченного времени, я боюсь, что это не поможет вам с этой конкретной проблемой истории файлов.

Примечание. этот вопрос очень близок к этой проблеме libgit2sharp: Как получить последний коммит, затронувший данный файл?

Обновлять

Запрос на вытягивание #963 добавляет именно эту функцию.

Он доступен начиная с LibGit2Sharp.0.22.0-pre20150415174523 предварительного выпуска пакета NuGet.

person nulltoken    schedule 23.11.2011
comment
На самом деле это точно такая же проблема :) - person shytikov; 23.11.2011

Это в основном используется в issues/495 libgit2.
Несмотря на то, что реализовано в libgit2sharp (PR 963, для вехи 22), он по-прежнему доступен в самой libgit2.

Проблема задокументирована в issues/3041: Предоставить функции журнала, обертывающие revwalk.
Подход, упомянутый в вопросе, использовался в этот libgit2sharp example и может быть адаптирован к C с помощью libgit2. Это остается текущим обходным решением до принятия резолюции 3041.

person VonC    schedule 17.06.2015
comment
спасибо, но это не намного больше, чем сказал нулевой токен. он также предоставил одну ссылку. + Я тоже использовал google .. Я надеялся на суть, о которой говорил shyitok. - Я реализовал его, но он не следует переименованию - он основан на примере кода git log - person Daij-Djan; 17.06.2015
comment
Согласен, это скорее обновление, спустя 4 года. Реализация, как уже упоминалось, остается загадкой. - person VonC; 17.06.2015
comment
@Daij-Djan nulltoken упоминает тот же PR, который я только что упомянул: LibGit2Sharp.0.22.0-pre20150415174523 имеет эту функцию. - person VonC; 23.06.2015
comment
Я также хотел бы получить историю файлов определенного файла. Я уже пробовал следующий код, но в истории IEnumerable нет коммитов. Не могли бы вы предоставить некоторую информацию, как решить эту проблему. Репозиторий репо = новый репозиторий (repoPath); IEnumerable‹LogEntry› history = repo.Commits.QueryBy(filePath, new FollowFilter { SortBy = CommitSortStrategies.Topological }); - person Odrai; 16.04.2016
comment
@Одрай, я понимаю. Похоже, что github.com/libgit2/rugged/pull/531 все еще выполняется. - person VonC; 16.04.2016
comment
@ Одрай, о котором я пока не знаю. - person VonC; 16.04.2016

При использовании C# эта функция была добавлена ​​в LibGit2Sharp 0.22.0 пакет NuGet (Pull Request 963). Вы можете сделать следующее:

var fileHistory = repository.Commits.QueryBy(filePathRelativeToRepository);
foreach (var version in fileHistory)
{
    // Get further details by inspecting version.Commit
}

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

/// <summary>
/// Gets the previous commit of the file.
/// </summary>
/// <param name="repository">The repository.</param>
/// <param name="filePathRelativeToRepository">The file path relative to repository.</param>
/// <param name="commitSha">The commit sha to start the search for the previous version from. If null, the latest commit of the file will be returned.</param>
/// <returns></returns>
private static Commit GetPreviousCommitOfFile(Repository repository, string filePathRelativeToRepository, string commitSha = null)
{
    bool versionMatchesGivenVersion = false;
    var fileHistory = repository.Commits.QueryBy(filePathRelativeToRepository);
    foreach (var version in fileHistory)
    {
        // If they want the latest commit or we have found the "previous" commit that they were after, return it.
        if (string.IsNullOrWhiteSpace(commitSha) || versionMatchesGivenVersion)
            return version.Commit;

        // If this commit version matches the version specified, we want to return the next commit in the list, as it will be the previous commit.
        if (version.Commit.Sha.Equals(commitSha))
            versionMatchesGivenVersion = true;
    }

    return null;
}
person deadlydog    schedule 09.07.2016