Определить коммиты, введенные в ветвь, путем слияния в git?

Я пытаюсь определить коммиты, введенные в родительскую ветку из-за слияния, используя идентификатор слияния.

3 ответа

TL;DR

Используйте ответ max630, если это настоящее слияние. Чтобы исключить само слияние, используйте его небольшой вариант: M^1..M^2,

Долго

Здесь вы просите найти коммиты, которые стали доступны в результате слияния. Эта идея достижимости является концепцией теории графов. Таким образом, если вы нарисуете результат слияния, ответ будет более понятным.

Найти базы слияния

Предположим, что график "до слияния" выглядит так, где * это фиксация базы слияния и L а также R левый и правый боковой кончик фиксирует:

...--*--...--L   <-- mainline
      \
       o--...--R   <-- sidebranch

Тогда график "после слияния" выглядит так:

...--*--...--L---M   <-- mainline
      \         /
       o--...--R   <-- sidebranch

Вновь введенные коммиты, теперь, очевидно,:-) те, которые находятся в нижнем ряду, то есть те, которые доступны из (и включая) R, но исключая фиксацию базы слияния. Мы достигаем их, начиная со второго родителя M, который R, затем работает по обратной связи от R его родителю, другому родителю и так далее. Это приводит к дну o узел, который подключается обратно для фиксации *,

Если у вас есть имя как sidebranch указывая на R Вам нужно только найти базу слияния:

mb=$(git merge-base $all mainline^1 sidebranch)

который использует синтаксис "первый родитель коммита" для идентификации коммита L от коммита M: ^1 суффикс. Если у вас больше нет имени sidebranch Вы можете определить совершить R используя синтаксис "второй родитель коммита":

mb=$(git merge-base $all mainline^1 mainline^2)

К сожалению, это не единственный возможный входной граф. Довольно типично иметь график "до слияния", который выглядит следующим образом:

...--*   <-- mainline
      \
       o--...--R   <-- sidebranch

Бег git merge без --no-ff выполнит операцию "ускоренной перемотки вперед", которая на самом деле не является слиянием: в результате вы получите линейный граф, а не слияние:

...--*--o--...--R   <-- mainline, sidebranch

Здесь, если у вас еще нет записи reflog для основной ветки, найти коммит буквально невозможно *, Если у вас есть запись reflog, она тривиальна: mainline@{number}, используя соответствующие number, (Нахождение подходящего number это вопрос просмотра рефлога, чтобы найти обновление от ускоренной перемотки вперед. Если вы только что сделали слияние, это просто 1 а также HEAD@{1}.)

mb=$(git rev-parse mainline@{1})   # for instance

Причину я поставил $all В приведенном выше примере команды для поиска базы слияния есть еще одна третья возможность, когда у вас есть несколько баз слияния:

...--o--*---o--...--L
         \ /
          X
         / \
...--o--*---o--...--R

Здесь вы хотите исключить все базы слияния. замещать $all с --all если необходимо.

Теперь у вас есть все необходимое

Теперь, когда вы знаете базу (ы) слияния, найдя их с git merge-base если слияние было реальным слиянием, коммиты, которые были сделаны достижимыми слиянием, являются просто теми, которые достижимы из R сам, но не из базы (ов) слияния:

git rev-list sidebranch --not $mb

использование git log скорее, чем git rev-list если вы хотите проверять коммиты, а не просто перечислять их.

Упрощая это

Все вышеперечисленное предназначено для нахождения базы (слияний) слияния и исключения их, чтобы мы получили коммит R и его достижимые предки без получения какого-либо коммита L, Но нам не нужно начинать это исключение конкретно с базы слияния. Мы можем просто начать это с L сам.

Называть L нам просто нужно назвать предыдущее значение mainline или первый родитель слияния M, Первый родитель M является M^1 или же M~1, так что пока мы знаем хэш-идентификатор M мы можем просто добавить суффикс и сказать "исключить это".

Для этого есть даже краткий синтаксис. Вместо:

git rev-list M^2 --not M^1

или немного короче:

git rev-list M^2 ^M^1

мы можем использовать синтаксис из двух точек:

git rev-list M^1..M^2

что у нас наверху.

Обратите внимание, что все это предполагает "реальное слияние": если слияние было ускоренным, вы должны вместо этого использовать reflog.

Команда git log <id>~1..<id> отобразит список всех слитых коммитов, а сам коммит слился.

Вы можете оформить ветку и использовать git log для просмотра коммитов и Id коммитов в ветке. git log -n10 --oneline даст вам историю предыдущих 10 коммитов в этой ветке.

Другие вопросы по тегам