Как найти ветку, на которой находится коммит git? (Используя libgit2sharp)

Для исследовательского проекта я пытался воспроизвести графическое представление, присутствующее в программном обеспечении для контроля версий, таком как SourceTree или TortoiseGit.

Графическое представление, которое я пытаюсь реализовать Графическое представление, которое я пытаюсь реализовать

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

Просматривая другие решения на StackOverflow, я обнаружил, что можно получить список ветвей, содержащих фиксацию, но мне нужен метод выделения одной из них для отображения на моем графике. Точно так же SourceTree или TortoiseGit как-то умудряются это делать.

Моя проблема также идентична этой, Узнайте ветка, которой принадлежит коммит в LibGit2Sharp?

Похоже, они нашли реальное решение в закрытой комнате для дискуссий. Однако у меня нет репутации, чтобы комментировать и спрашивать, что они нашли.

Есть ли у кого-нибудь идеи о том, как я могу это сделать?

Или, @nulltoken, если вы случайно видите это и помните, вы знаете, что вы, ребята, обнаружили в той комнате для дискуссий?


person Jade White    schedule 14.11.2017    source источник


Ответы (3)


Не уверен, насколько полезным этот ответ окажется для вас. Эквивалентный вызов LibGit2Sharp для «git branch --contains $SHA1» является запрошенной функцией на GitHub, открытой !

Давным-давно я использовал запрос по всем ссылкам, подобным этому, но для вашего варианта использования это может быть чрезмерно медленным.

Я пытался думать о возможных способах смягчения этой проблемы, но не мог придумать какой-либо путеводной звезды. :( А потом я обнаружил этот комментарий, в котором утверждается, что вам нужно пройти через DAG и проверить фактическую ветку, в которой есть фиксация Все это намекает на то, что вам нужно будет использовать метод медленного обхода всех ссылок.

person vishwarajanand    schedule 14.11.2017
comment
Я думаю, что ОП не запрашивает обход или эмуляцию branch --contains. ОП спрашивает, как узнать текущие советы всех рефов, чтобы украсить их. - person Edward Thomson; 14.11.2017
comment
(Но, перечитав это несколько раз, я не могу сказать, если честно.) - person Edward Thomson; 14.11.2017
comment
@ Эдвард-Томсон, точно! :) после вашего комментария [человека с такой высокой репутацией] я прочитал вопрос около 8 раз, но я также не мог понять, как вы пришли к такому выводу или я пришел к своему! Только это дало мне повод для сомнений: The biggest problem ... и I need a method of isolating... - person vishwarajanand; 14.11.2017
comment
Я полагаю, чтобы уточнить, мне удалось воспроизвести git branch --contains. Подвох в том, что несколько веток могут содержать один и тот же коммит. Это затрудняет выбор того, кто будет отображаться как владелец этого коммита на моем графике (например, принадлежит ли он NewBranch2 или master). например Если бы я создал ветку A из мастера, немного поработал над A, а затем объединил бы A с мастером, git branch --contains $(any sha from A) вернул бы A, master. - person Jade White; 15.11.2017
comment
В этом случае, очевидно, это будет лучший результат — A. Но если я позже разветвлю B от A, git branch --contains $(any sha from A) вернет "B, A, master. В этом случае B является лучшим результатом, но фиксация изначально была на A, поэтому я не всегда могу отображать верхнюю ветвь как владеющую фиксацией на моем графике... - person Jade White; 15.11.2017
comment
Спасибо за разъяснение @jade-white. Вы можете оценить ветку, которая является exact владельцем коммита, reflog. Мне не нужно было часто использовать эту функцию, и при быстром поиске я наткнулся на эту тему, которая может вам помочь: stackoverflow.com/ а/18505238/3991696. Обратите внимание, что история поиска с помощью reflog ограничена. Надеюсь, это поможет. - person vishwarajanand; 15.11.2017

Получается, чтобы сгенерировать граф, SourceTree не нужно знать, на какой ветке коммит.

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

person Jade White    schedule 10.05.2018

Это может быть полезно для того, как это сделать, когда вы хотите показать больше, чем просто историю HEAD (что достигается путем перечисления repository.Commits):

repository.Commits
    .QueryBy(new CommitFilter 
    {
        IncludeReachableFrom = repository.Refs.ToList(), // or adjust to your needs
        SortBy = CommitSortStrategies.Time
    })
    .Distinct<Commit>(EqualityComparer<GitObject>.Default)
    .ToList();

скопировано из/вдохновлено: https://stackoverflow.com/a/68564141/2240196

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

ILookup<GitObject, string> refsByCommit = repo.Refs.ToLookup(@ref => @ref.ResolveToDirectReference().Target, @ref => @ref.CanonicalName);
// ( ... )
foreach (var commit in commits)
{
    // ( ... )
    var refNames = refsByCommit[commit];
    // ( ... )
}
person Remco    schedule 04.08.2021