Как получить историю файла? - PullRequest
22 голосов
/ 23 ноября 2011

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

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

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

Но для меня это выглядит неоптимально ...

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

Большое спасибо заранее!

Ответы [ 3 ]

15 голосов
/ 23 ноября 2011

Но для меня это выглядит неоптимально ...

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

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

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

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

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

Обновление

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

Он доступен с предварительной версии LibGit2Sharp.0.22.0-pre20150415174523 NuGet.

2 голосов
/ 17 июня 2015

Это в основном сопровождается выпусками / 495 libgit2.
Несмотря на то, что реализовано в libgit2sharp ( PR 963 , для веха 22 * ​​1009 *), оно все еще "готово к захвату" в самой libgit2.

Проблема задокументирована в

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

0 голосов
/ 09 июля 2016

При использовании C # эта функциональность была добавлена ​​в LibGit2Sharp 0.22.0 пакет NuGet ( Запрос на получение 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;
}
...