Dado um ID de confirmação, como determinar se a ramificação atual contém a confirmação?

156

O que estou tentando fazer é uma verificação de versão. Quero garantir que o código fique no topo de uma versão mínima. Então, eu preciso de uma maneira de saber se o ramo atual contém um commit especificado.

TieDad
fonte
10
Consulte a duplicata proposta para saber como encontrar todas as ramificações que contêm uma confirmação especificada. Para descobrir se a ramificação atual contém confirmação C , use o comando "encanamento" git merge-base --is-ancestor. O ramo de corrente contém C , se C é um antepassado de HEAD, assim:if git merge-base --is-ancestor $hash HEAD; then echo I contain commit $hash; else echo I do not contain commit $hash; fi
Torek
1
Olá, envie isso como uma resposta para que ele possa ser selecionado como a resposta correta =) #
212 Ben Ben
1
@ Ben - eu adicionei como uma resposta wiki da comunidade.
Zitrax
1
@Remover: em scripts de shell, zero é verdadeiro, diferente de zero é falso: o inverso da convenção C. /bin/truefoi originalmente implementado como exit 0e /bin/falsecomo exit 1. (Conchas modernos têm, em seguida, construído em.)
Torek

Respostas:

220

Existem várias maneiras de alcançar esse resultado. A primeira opção ingênua é usar git loge procurar um commit específico usando grep, mas isso nem sempre é preciso

git log | grep <commit_id>

É melhor usar git branchdiretamente para encontrar todos os ramos que contêm dados COMMIT_IDusando

git branch --contains $COMMIT_ID

O próximo passo é descobrir o ramo atual que pode ser feito desde o git 1.8.1uso

git symbolic-ref --short HEAD

E combinados juntos como

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

Mas o comando acima não retorna verdadeiro ou falso e existe uma versão mais curta que retorna o código de saída 0 se a confirmação estiver na ramificação atual OU o código de saída 1 se não houver

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

O código de saída é bom, mas como você deseja string trueou falseresposta, você precisa adicionar um pouco mais e, em seguida, combinado com o ifbash, obtém

if [ 0 -eq $(git merge-base --is-ancestor $COMMIT_ID HEAD) ]; then echo "true"; else echo "false"; fi
JiriS
fonte
9
Isso não está correto; o greppoderia resultar em falsos positivos se git logmencionar o SHA de confirmação por outros motivos, por exemplo, é mencionado em uma mensagem de confirmação como resultado de uma porta de outra ramificação.
Adam Spiers
1
Corrigido (ou melhor, acrescentou outra opção).
27417 JiriS
3
Por favor, veja o comentário sobre a pergunta, que usa o conjunto de ferramentas git embutido. stackoverflow.com/questions/43535132/…
Ben
2
Eu gosto da primeira opção, mas para descartar a objeção de Adam, eu adicionaria a opção --format=format:%Ha git log.
PJSCopeland
71

Obtenha uma lista de ramificações que contêm o commit específico.

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

Verifique se uma ramificação possui o commit específico.

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

Pesquise o ramo (digamos feature) com a correspondência exata .

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

por exemplo, se você tem 3 filiais locais chamados feature, feature1, feature2em seguida,

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

# output
feature
feature1
feature2

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

# output
feature     

Você também pode pesquisar em ramos locale remote(uso -a) ou apenas em remoteramos (uso -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$'
Sajib Khan
fonte
1
O grepaqui também pode resultar em falsos positivos se houver outros ramos que contenham o commit cujos nomes também contenham <branch-name>como substring.
Adam Spiers
1
Sim @AdamSpiers, Actualizado a resposta com correspondência exata do nome de filial porgrep -E '(^|\s)branchname$'
Sajib Khan
1
Por esse comentário sobre a pergunta relacionada , pode ser útil adicionar a opção -r("remote") ou -a("all") git branchpara procurar ramificações que podem não ser replicadas no repo clone local.
Sxc731 23/05
Isso não funcionou para mim, eu precisava git branch --all --contains <commit-id>
Arthur Tacca
7

Comentário extraído por @torek como resposta:

Consulte a duplicata proposta para saber como encontrar todas as ramificações que contêm uma confirmação especificada.

Para descobrir se a ramificação atual contém confirmação C, use o comando "encanamento" git merge-base --is-ancestor. O ramo atual contém C se C é um ancestral de HEAD, portanto:

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

(Observação: em scripts de shell, um comando que sai zero é "verdadeiro", enquanto um que sai diferente de zero é "falso".)

torek
fonte
4

Para listar ramificações locais que contêm commit:

git branch --contains <commit-id>

e para listar todas as ramificações, incluindo apenas remotas, contendo commit:

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

Da mesma forma, para verificar se o commit está em particular branch:

git log <branch> | grep <commit_id>

e se a filial não existir, prefixe localmente o nome da filial com origin/

hgrey
fonte
Votada para a observação em -a. Obrigado por esse conselho!
Thorkil Værge
3

Sim outra alternativa:

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

Isso funciona melhor para mim, pois também funcionaria em ramificações remotas armazenadas em cache localmente, como remotes/origin/master, nas quais git branch --containsnão funcionará.

Isso cobre mais do que a pergunta do OP sobre apenas "ramo atual", mas acho idiota pedir uma versão "qualquer ramo" dessa pergunta, então decido postar aqui de qualquer maneira.

lógico ou
fonte
1
git branch --contains <commit-id> --points-at <target branch name>

Ele retornará o nome do ramo de destino se o ID de confirmação existir nesse ramo. Caso contrário, o comando falhará.

DreamUth
fonte
Não ...error: malformed object name 'branch-name'
bbodenmiller
1
Você pode obter esse erro em 2 casos 1. Quando o <nome da filial> fornecido não contiver o <ID de confirmação> 2. O checkout <nome da filial> não é o <nome da filial>
especificado
0

Como esta pergunta tem algumas respostas legais, estou adicionando meus favoritos.

Este mostrará a você, para os últimos $ncommits nos $brquais os branches contêm cada um:

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

Este é semelhante, mas faz o mesmo para uma lista de ramos:

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
Bruno Bronosky
fonte