Учитывая идентификатор фиксации, как определить, содержит ли текущая ветвь фиксацию?

156

Я пытаюсь проверить версию. Я хочу, чтобы код оставался поверх минимальной версии. Поэтому мне нужен способ узнать, содержит ли текущая ветвь указанный коммит.

TieDad
источник
10
Смотрите предложенный дубликат, чтобы узнать, как найти все ветви, которые содержат указанный коммит. Чтобы узнать, содержит ли текущая ветвь коммит C , используйте команду «plumbing» git merge-base --is-ancestor. Текущая ветвь содержит C , если C является предком HEAD, так:if git merge-base --is-ancestor $hash HEAD; then echo I contain commit $hash; else echo I do not contain commit $hash; fi
Торек
1
Привет, пожалуйста, отправьте это как ответ, чтобы он мог быть выбран как правильный ответ =)
Бен
1
@Ben - я добавил это как ответ сообщества вики.
Цитракс
1
@Remover: в сценариях оболочки ноль равен true, ненулевой - false: обратная сторона соглашения C /bin/trueизначально был реализован как exit 0и /bin/falseкак exit 1. (Современные раковины затем встраивается.)
Торек

Ответы:

220

Есть несколько способов достижения этого результата. Первый наивный вариант заключается в использовании git logи поиске определенного коммита с использованием grep, но это не всегда точно

git log | grep <commit_id>

Вам лучше использовать git branchнапрямую, чтобы найти все ветви, содержащие данные, COMMIT_IDиспользуя

git branch --contains $COMMIT_ID

Следующим шагом является выяснение текущей ветви, которая может быть сделана, так как git 1.8.1 использования

git symbolic-ref --short HEAD

И объединены как

git branch $(git symbolic-ref --short HEAD) --contains $COMMIT_ID

Но приведенная выше команда не возвращает true или false, и существует более короткая версия, которая возвращает код выхода 0, если commit находится в текущей ветви ИЛИ код выхода 1, если нет

git merge-base --is-ancestor $COMMIT_ID HEAD

Выходной код это хорошо, но если вам нужна строка trueили falseответ, вам нужно добавить немного больше, а затем в сочетании с ifbash, вы получите

if [ 0 -eq $(git merge-base --is-ancestor $COMMIT_ID HEAD) ]; then echo "true"; else echo "false"; fi
JiriS
источник
9
Это не правильно; Это grepможет привести к ложным срабатываниям, если git logупомянуть SHA о коммите по другим причинам, например, это упоминается в сообщении о коммите как результат порта из другой ветви.
Адам
1
Исправлено (точнее добавлена ​​еще одна опция).
JiriS
3
Пожалуйста, смотрите комментарий к вопросу, который использует встроенный набор инструментов git. stackoverflow.com/questions/43535132/…
Бен
2
Мне нравится первый вариант, но чтобы исключить возражения Адама, я бы добавил этот вариант --format=format:%Hк git log.
ПАОПеленд
71

Получить список ветвей, которые содержат конкретный коммит.

# get all the branches where the commit exists
$ git branch --contains <commit-id>

Проверьте, есть ли у ветки определенный коммит.

# output the branch-name if the commit exists in that branch
$ git branch --contains <commit-id> | grep <branch-name>

Искать ветку (скажем, feature) с точным соответствием .

$ git branch --contains <commit-id> | grep -E '(^|\s)feature$'

например , если у вас есть 3 -х местные ветви называются feature, feature1, feature2то

$ git branch --contains <commit-id> | grep 'feature'

# output
feature
feature1
feature2

$ git branch --contains <commit-id> | grep -E '(^|\s)feature$'

# output
feature     

Вы также можете искать в обоих localи remoteветвей (использование -a) или только в remoteветви (использование -r).

# search in both 'local' & 'remote' branches  
$ git branch -a --contains <commit-id> | grep -E '(^|\s)feature$'

# search in 'remote' branches  
$ git branch -r --contains <commit-id> | grep -E '(^|\s)feature$'
Саджиб Хан
источник
1
grepЗдесь также может привести к ложным срабатываниям , если есть другие ветви , содержащие коммит , чьи имена содержат в <branch-name>качестве подстроки.
Адам
1
Да @AdamSpiers, Обновлен ответ с точным соответствием имени ветвиgrep -E '(^|\s)branchname$'
Саджиб Хан
1
В соответствии с этим комментарием к связанному вопросу может быть полезно добавить опцию -r(«удаленный») или -a(«все») git branchдля поиска ветвей, которые не могут быть реплицированы в клоне локального репо.
sxc731
Это не сработало для меня, мне нужно было git branch --all --contains <commit-id>
Артур Такка
7

Извлеченный комментарий @torek в качестве ответа:

Смотрите предложенный дубликат, чтобы узнать, как найти все ветви, которые содержат указанный коммит.

Чтобы узнать, содержит ли текущая ветвь коммит C, используйте команду «plumbing» git merge-base --is-ancestor. Текущая ветвь содержит C, если C является предком HEAD, поэтому:

if git merge-base --is-ancestor $hash HEAD; then
    echo I contain commit $hash
else
    echo I do not contain commit $hash
fi

(Примечание: в сценариях оболочки команда, которая выходит из нуля, имеет значение «истина», а команда, которая выходит из нуля, - «ложь».)

torek
источник
4

Для просмотра локальных веток, содержащих коммит

git branch --contains <commit-id>

и перечислить все ветви, включая только удаленные, содержащие коммит:

git branch -a --contains <commit-id>

Аналогично, чтобы проверить, есть ли коммит в конкретной ветке:

git log <branch> | grep <commit_id>

и если ветвь не существует, локально префикс имени ветки с origin/

hgrey
источник
Проголосовал за замечание -a. Спасибо за этот совет!
Торкил Вурге
3

Да, другая альтернатива:

git rev-list <branch name> | grep `git rev-parse <commit>`

Это работает лучше всего для меня, так как это также будет работать на локально кэшированных удаленных ветвях, таких как remotes/origin/master, на которых git branch --containsне будет работать.

Это охватывает больше, чем вопрос OP о «текущей ветке», но я нахожу глупым задавать вариант «любой ветви» этого вопроса, поэтому я все равно решил разместить здесь.

Логическое ИЛИ
источник
1
git branch --contains <commit-id> --points-at <target branch name>

Он вернет имя целевой ветви, если в этой ветви существует идентификатор фиксации. В противном случае команда потерпит неудачу.

DreamUth
источник
Нету ...error: malformed object name 'branch-name'
bbodenmiller
1
Вы можете получить эту ошибку в 2 случаях: 1. Когда указанное <имя ветви> не содержит указанного <идентификатора фиксации> 2. Оформление <имя ветви> не является указанным <имя ветви>
DreamUth
0

Поскольку на этот вопрос есть несколько хороших ответов, я добавляю в избранное.

Этот покажет вам, для последних $nкоммитов, в $brкоторых каждый содержит ветки:

br=mybranch
n=10
git log --oneline -n$n $br | awk '{print; system("git branch --contains "$1)}'

Этот похож, но делает то же самое для списка филиалов:

br="mybranch yourbranch herbranch"
n=4
for br in $brs; do git log --oneline -n$n $br | awk '{print; system("git branch --contains "$1)}'; done
Бруно Броноски
источник