git: как мне найти общего предка двух веток, которые уже были объединены

Чтобы найти общего предка двух веток git, нужно сделать:

git merge-base branch another_branch

Хорошо. Но... что, если обе ветки уже объединены? Когда я использую merge-base в этом случае, коммит, который я получаю, является последним перед слиянием, и я хотел бы знать общего предка, из которого вышли обе ветки «до слияния».

Другими словами:

Z - A - B - C - D - E - F
     \          /
      G - H - I 

HEAD находится в F. Если я сделаю git merge-base здесь, коммит, который я получу, будет I, а тот, который я ищу, - это A или, возможно, Z. Есть ли инструкция git, чтобы найти его?


person PaulJ    schedule 30.04.2017    source источник


Ответы (2)


Если вы сделаете

git merge-base C I

вы получаете фиксацию A, которую хотите. Что такое Си и я? Они являются родительскими коммитами вашего коммита слияния D.

Эй, ты их получаешь?

git log --pretty=%P -n 1 D 

дает вам две строки. Эти две строки являются фиксацией C и I, которые вам нужны.

Если вы хотите сделать все это вместе, вы можете написать

git merge-base $(git log --pretty=%P -n 1 MERGE_COMMIT)

где вы должны заменить MERGE_COMMIT на хеш вашей фиксации слияния D

Изменить: как заявил @poke, с ним проще

git merge-base MERGE_COMMIT^ MERGE_COMMIT^2 
person Manuel Schmidt    schedule 30.04.2017
comment
Извините, а вы имеете в виду git log --pretty=%P -n 1 D вместо git log --pretty=%P -n 1 A? (В противном случае это выглядело бы немного круговым... Чтобы найти фиксацию A, мне нужно сначала ввести команду, включающую фиксацию A...) - person PaulJ; 01.05.2017
comment
Вы также можете обратиться к двум родителям коммита слияния D, используя D^ и D^^. Так что это сокращается до git merge-base D^ D^^. - person poke; 01.05.2017
comment
@poke, я так не думаю. D^ является одним из родителей, правильно, но D^^ является родителем D^, а не другим родителем D - person Manuel Schmidt; 01.05.2017
comment
@ManuelSchmidt Извините, вы правы. Я имел в виду D^ и D^2. - person poke; 01.05.2017
comment
Спасибо @poke. я этого не знал - person Manuel Schmidt; 01.05.2017

Обычно мне нужно найти предка между верхушкой моей ветки, HEAD, и удаленной основной веткой разработки, скажем, origin/dev. Вот что я использую:

git log --reverse --boundary --format=%h HEAD ^origin/dev | head -1

По сути, это говорит:

  • Возьмите всех предков, кроме общих с origin/dev
  • Включить границу (точку разветвления)
  • Измените порядок, чтобы точка разветвления была первой в списке.
  • Войдите в формат, в котором отображается только SHA
  • Возьмите первый в этом списке
person Radioreve    schedule 20.08.2019
comment
Хорошо, это находит фиксацию даже в том случае, если две ветки были объединены несколько раз (например, dev и master в типичном потоке git), что именно то, что мне нужно. Спасибо! - person Kostrahb; 17.06.2020