Подтвердить что ты не робот

Как получить историю файла?

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

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

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

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

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

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

4b9b3361

Ответ 1

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

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

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

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

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

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

Update

Запрос Pull # 963 добавляет эту особенность.

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

Ответ 2

Это в основном выполняется в issues/495 libgit2.
Даже если это реализовано в libgit2sharp (PR 963, для веха 22), она по-прежнему "забирается" в самом libgit2.

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

Ответ 3

При использовании С# эта функциональность была добавлена ​​в пакет 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 Extension (который является открытым исходным кодом, поэтому вы можете просмотреть код), мне нужно было получить файл предыдущей фиксации поэтому я могу видеть, какие изменения были внесены в файл в данной фиксации. Вот как я получил файл предыдущей фиксации:

/// <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;
}