Как я могу определить, является ли один коммит потомком другого? - PullRequest
121 голосов
/ 09 июня 2010

С помощью Git, как я могу узнать, является ли один коммит в моей ветке потомком другого коммита?

Ответы [ 7 ]

224 голосов
/ 23 ноября 2012

В Git 1.8.0 это поддерживается как опция до merge-base:

git merge-base --is-ancestor <maybe-ancestor-commit> <descendant-commit>

со страницы руководства:

- это-предок

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

Например:

git merge-base --is-ancestor origin/master master; echo $?
46 голосов
/ 09 июня 2010

Если вы хотите проверить это программно (например, в скрипте), вы можете проверить, равен ли git merge-base A B git rev-parse --verify A (тогда A достижим из B), или если git rev-parse --verify B (тогда B доступениз).git rev-parse здесь необходимо для преобразования из имени коммита в SHA-1 / идентификатор фиксации.

Использование git rev-list, как в Ответ VonC также возможен.


Если один из коммитов, о котором вы спрашиваете, является tip tip , тогда git branch --contains <commit> или git branch --merged <commit> может быть лучшим непрограммным решением.

13 голосов
/ 09 июня 2010

Этот тип операций основан на понятии диапазона ревизий , подробно изложенном в вопросе SO: " Разница в 'git log origin / master' против 'git log origin / master ..' ».

git rev-list должен иметь возможность вернуться от коммита, до другого, если он будет достигнут.

Итак, я бы попробовал:

git rev-list --boundary 85e54e2408..0815fcf18a
0815fcf18a19441c1c26fc3495c4047cf59a06b9
8a1658147a460a0230fb1990f0bc61130ab624b2
-85e54e240836e6efb46978e4a1780f0b45516b20

(Граничные коммиты начинаются с -)

Если последний отображаемый коммит совпадает с первым коммитом в команде git rev-list, то это коммит, достижимый при втором коммите.

Если первый коммит недоступен со второго, git rev-list ничего не должен возвращать.

git rev-list --boundary A..B

закончится к A, если A достижимо с B.
Это так же, как:

git rev-list --boundary B --not A

, с B a положительной ссылкой и A a отрицательной ссылкой .
Он начинается с B и идет по графику, пока не встретит ревизию, доступную с A.
Я бы сказал, что если A напрямую доступен из B, он встретится (и отобразится из-за опции --boundary) A.

10 голосов
/ 22 сентября 2011

Другой способ - использовать git log и grep.

git log --pretty=format:%H abc123 | grep def456

Это выдаст одну строку вывода, если commit def456 является предком коммита abc123 или не выдаст иначе.

Обычно вы можете обойтись без пропуска аргумента "--pretty", но это необходимо, если вы хотите убедиться, что вы осуществляете поиск только по фактическим хэшам коммитов, а не по комментариям журналов и т.

3 голосов

https://stackoverflow.com/a/13526591/895245 упоминает об этом, теперь, чтобы сделать его более дружелюбным к человеку:

git-is-ancestor() (
  if git merge-base --is-ancestor "$1" "$2"; then
      echo 'ancestor'
  elif git merge-base --is-ancestor "$2" "$1"; then
      echo 'descendant'
  else
      echo 'unrelated'
  fi
)
alias giia='git-is-ancestor'
1 голос
/ 11 ноября 2015

git show-branch branch-sha1 commit-sha1

Где:

  • branch-sha1: sha1 в вашей ветке, которую вы хотите проверить
  • commit-sha1: sha1 коммита, с которым вы хотите проверить
0 голосов
/ 19 января 2015

Построение ответа itub, если вам нужно сделать это для всех тегов в хранилище:

for i in `git tag` ; do echo -ne $i "\t" ; git log --pretty=format:%H $i | (grep <commit to find> || echo ""); done
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...