Как я могу определить, является ли кто-то одним из потомков другого коммита?

С Git, как я могу определить, является ли какой-либо фиксатор в моей ветке потомком другого коммита?

Ответ 1

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

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

Изменить: в современном Git есть явная поддержка этого запроса в виде git merge-base --is-ancestor.


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

Ответ 2

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

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

На странице man:

- это-предок

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

Например:

git merge-base --is-ancestor origin/master master; echo $?

Ответ 3

Этот вид операций основан на понятии диапазона ревизий, подробно описанном в вопросе SO: "Разница в 'git log origin/master vs' 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 отрицательной ссылкой.
Он начинается с B и идет назад по графику, пока не встретит ревизию, доступную из A.
Я бы сказал, что если A напрямую доступен из B, он встретится (и отобразится из-за опции --boundary) самого A.

Ответ 4

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

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

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

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

Ответ 5

fooobar.com/questions/68814/... упоминает об этом, теперь, чтобы сделать его более дружественным к человеку:

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'

Ответ 6

git show-branch branch-sha1 commit-sha1

Где:

  • branch-sha1: sha1 в вашей ветке, которую вы хотите проверить
  • commit-sha1: sha1 фиксации, которую вы хотите проверить,

Ответ 7

Настройте ответ на itub, если вам нужно сделать это для всех тегов в репозитории:

for i in `git tag` ; do echo -ne $i "\t" ; git log --pretty=format:%H $i | (grep <commit to find> || echo ""); done