С помощью Git, как я могу определить, является ли один коммит в моей ветке потомком другого коммита?
--is-ancestorрешение.
С помощью Git, как я могу определить, является ли один коммит в моей ветке потомком другого коммита?
--is-ancestorрешение.
Ответы:
Если вы хотите проверить это программно (например, в скрипте), вы можете проверить, git merge-base A Bравно ли оно git rev-parse --verify A(тогда A достижимо из B), или если это так git rev-parse --verify B(тогда B достижимо из A). git rev-parseЗдесь необходимо преобразовать имя коммита в коммит SHA-1 / commit id.
Использование ответаgit rev-list как в VonC также возможно.
Изменить: в современном Git есть явная поддержка этого запроса в виде git merge-base --is-ancestor.
Если один из коммитов, о котором вы спрашиваете, является подсказкой ветки , тогда git branch --contains <commit>или git branch --merged <commit>может быть лучшим непрограммным решением.
git checkout -b quickcheck <more-recent-commit-ID>тогда и тогда git branch --contains <older-commit-ID>(а затем git branch -D quickcheckизбавиться от временной ветки).
git merge-base --is-ancestor2 годам.
git branch --contains <commit>и git merge-base --is-ancestor ...: 3m40s против 0,14s
В Git 1.8.0 это поддерживается как опция для merge-base:
git merge-base --is-ancestor <maybe-ancestor-commit> <descendant-commit>
Со страницы руководства:
--is-предок
Проверьте, является ли первый предком второго, и выйдите со статусом 0, если истина, или со статусом 1, если нет. Ошибки сигнализируются ненулевым статусом, отличным от 1.
Например:
git merge-base --is-ancestor origin/master master; echo $?
git merge-base THING --is-ancestor OF_THING && echo yes || echo noнапример:git merge-base my-feature-branch --is-ancestor master && echo yes || echo no
git merge-base --is-ancestor -- commit commitработает для хэшей на моей стороне с git2.1.4 (Debian / Devuan 7.10 jessie) и 1.9.1 (Ubuntu 14.04 trusty), которые сейчас довольно древние. Это работает даже для Debian Wheezy, если вы делаете sudo apt-get install git/wheezy-backports.
Этот вид операций опирается на понятие диапазона ревизий, подробно описанное в вопросе 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в отрицательном значении задания .
Он начинается с Bи идет назад по графику, пока не встретит ревизию, из которой можно добраться A.
Я бы сказал, что если к нему Aможно напрямую добраться B, он сам столкнется (и покажет, из-за --boundaryопции) A.
-85e54e2...во фрагменте есть минус? Также возможна опечатка: "... это то же самое, что первый коммит ..."
-означает, что это граничный коммит. Я отредактировал ответ, чтобы сделать его более понятным, а также обновить ссылки на документы и исправить опечатку для этого 5-летнего ответа.
Другим способом было бы использовать git logи grep.
git log --pretty=format:%H abc123 | grep def456
Это выдаст одну строку вывода, если commit def456 является предком коммита abc123, или не выводит иначе.
Обычно вы можете обойтись без пропуска --prettyаргумента, но это необходимо, если вы хотите убедиться, что вы осуществляете поиск только по реальным хэшам коммитов, а не по комментариям журналов и так далее.
--prettyиспользовать --oneline: git log --oneline ce2ee3d | grep ec219ccпрекрасно работает
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'
git show-branch branch-sha1 commit-sha1
Куда:
Если вы используете git merge-base --is-ancestor, обязательно используйте Git 2.28 (3 квартал 2020 г.)
В Git 2.28 (Q3 2020) несколько полей в « struct commit», которые не обязательно должны присутствовать, были перемещены для фиксации плит.
См. Коммит c752ad0 , коммит c49c82a , коммит 4844812 , коммит 6da43d9 (17 июня 2020 г.) от Abhishek Kumar ( abhishekkumar2718) .
(Слиты Junio C Hamano - gitster- в фиксации d80bea4 , 6 июля 2020)
commit-graph: вводитьcommit_graph_data_slabПодписано: Абхишек Кумар
Структура commit используется во многих контекстах. Однако члены
generationиgraph_posиспользуются только для операций, связанных с графом фиксации, и в противном случае тратят память.Эта потеря была бы более заметной, когда мы перейдем к поколению номер v2, которое использует 64-разрядный номер поколения вместо текущих 32-разрядных.
Поскольку к ним часто обращаются вместе, давайте представим struct
commit_graph_dataи переместим их вcommit_graph_dataslab.Хотя весь набор тестов работает так же быстро, как
master(серии: 26 м48 сmaster: 27 м34 с, более быстрым на 2,87%), некоторые команды вродеgit merge-base --is-ancestorбыли замедлены на 40%, как обнаружил Седер Габор .
После минимизации доступа на уровне коммитов замедление сохраняется, но оно приближается к 20%.Деррик Столи считает, что замедление связано с базовым алгоритмом, а не с медленным доступом к коммит-блокам, и мы продолжим это в следующих статьях .
Основываясь на ответе itub, на случай, если вам нужно будет сделать это для всех тегов в хранилище:
for i in `git tag` ; do echo -ne $i "\t" ; git log --pretty=format:%H $i | (grep <commit to find> || echo ""); done