Os diferentes métodos abaixo são maneiras pragmáticas, úteis e úteis de inferir uma resposta provável , mas note que no git a pergunta em si é um mal-entendido, os commits não vêm de ramos. As ramificações vêm e vão, elas se movem, apenas confirmações representam a verdadeira história do repo. Por outro lado, essa não é uma maneira de dizer que as soluções abaixo são ruins. Apenas saiba que nenhum deles fornece uma resposta totalmente confiável, o que é impossível de obter por design no git. Ramos (Um caso simples é excluídos: I ramo, eu cometo duas vezes, I se fundem em um outro ramo, eu apagar o primeiro ramo Onde é que o commit "vir" a partir.?
RomainValeri
1
Eu tenho um caso em que eu puxo explicitamente um clone raso de profundidade 1 de uma tag. É barato, fácil e eficiente ... e até agora fiz tudo que eu queria lindamente. Agora que eu gostaria de saber em qual filial a etiqueta estava, estou de mangueira, pelo menos para esse detalhe. Você nem sempre pode ir para casa, lol
Paul Hodges
Respostas:
865
Embora Dav esteja certo de que as informações não são armazenadas diretamente, isso não significa que você nunca possa descobrir. Aqui estão algumas coisas que você pode fazer.
Localizar ramificações nas quais a confirmação está
git branch -a --contains <commit>
Isso informará todos os ramos que possuem o commit fornecido em sua história. Obviamente, isso é menos útil se o commit já tiver sido mesclado.
Pesquise os reflogs
Se você estiver trabalhando no repositório no qual a confirmação foi feita, poderá procurar nos reflogs a linha para essa confirmação. Os registros novos com mais de 90 dias são removidos pelo git-gc; portanto, se o commit for muito antigo, você não o encontrará. Dito isto, você pode fazer isso:
git reflog show --all | grep a871742
encontrar commit a871742. Note que você DEVE usar os 7 primeiros dígitos abreviados do commit. A saída deve ser algo como isto:
a871742 refs/heads/completion@{0}: commit (amend): mpc-completion: total rewrite
indicando que a confirmação foi feita na ramificação "conclusão". A saída padrão mostra hashes de confirmação abreviados, portanto, não procure o hash completo ou você não encontrará nada.
git reflog showé na verdade apenas um apelido para git log -g --abbrev-commit --pretty=oneline, então, se você quiser mexer no formato de saída para disponibilizar coisas diferentes para o grep, esse é o seu ponto de partida!
Se você não estiver trabalhando no repositório em que o commit foi feito, o melhor que você pode fazer neste caso é examinar os reflogs e descobrir quando o commit foi introduzido pela primeira vez em seu repositório; com alguma sorte, você buscou o ramo em que estava comprometido. Isso é um pouco mais complexo, porque você não pode percorrer a árvore de confirmação e os reflogs simultaneamente. Você deseja analisar a saída do reflog, examinando cada hash para ver se contém a confirmação desejada ou não.
Encontre uma confirmação de mesclagem subsequente
Isso depende do fluxo de trabalho, mas com bons fluxos de trabalho, as confirmações são feitas nas ramificações de desenvolvimento que são mescladas. Você pode fazer isso:
git log --merges <commit>..
para ver os commits de mesclagem que têm o commit fornecido como um ancestral. (Se o commit foi mesclado apenas uma vez, o primeiro deve ser a mesclagem que você procura; caso contrário, você terá que examinar alguns, suponho.) A mensagem de commit de mesclagem deve conter o nome do ramo que foi mesclado.
Se você quiser contar com isso, use a --no-ffopção git mergepara forçar a criação de consolidação de mesclagem, mesmo no caso de avanço rápido. (Porém, não fique muito ansioso. Isso pode se tornar ofuscante se for usado em excesso.) A resposta de VonC a uma pergunta relacionada é útil para elaborar esse tópico.
+1. A simples ausência de informações para esse problema específico faz você se perguntar se é realmente um problema? As ramificações podem mudar, ser renomeadas ou excluídas a qualquer momento. Pode ser o git describesuficiente, pois as tags (anotadas) podem ser vistas como mais significativas que as ramificações.
VonC
9
Eu definitivamente concordo - os galhos devem ser leves e flexíveis. Se você adotar um fluxo de trabalho no qual essas informações se --no-fftornem importantes, poderá usar a opção para garantir que haja sempre uma confirmação de mesclagem, para poder sempre rastrear o caminho de uma confirmação dada à medida que ela é mesclada com o mestre.
Cascabel
32
Para sua informação, se você deseja encontrar confirmações que existem apenas no controle remoto, adicione a -aflag ao primeiro comando, por exemplo:git branch -a --contains <commit>
Jonathan Day
8
@ JonathanDay: Não, isso encontrará confirmações em qualquer filial. Se você quiser apenas os do controle remoto, use -r.
Cascabel
7
@SimonTewsi Como eu disse, se é realmente um problema, use merge --no-ffpara registrar de forma confiável o nome da filial quando você mesclar. Caso contrário, pense nos nomes das filiais como rótulos abreviados temporários e envie as descrições como permanentes. "Que nome abreviado nos referimos a isso durante o desenvolvimento?" realmente não deve ser uma pergunta tão importante quanto "o que esse commit faz?"
Cascabel 15/05
154
Este comando simples funciona como um encanto:
git name-rev <SHA>
Por exemplo (onde test-branch é o nome do branch):
E levou apenas 8 anos para esta solução perfeita. Obrigado!
S1J0
6
Eu achei git name-rev --name-only <SHA>mais útil obter apenas o nome do ramo. Minha pergunta ... Ele pode retornar mais de um ramo em qualquer circunstância?
git-what-branch(Script Perl, veja abaixo) não parece mais ser mantido.
git-when-mergedé uma alternativa escrita em Python que está funcionando muito bem para mim.
Descubra quando uma consolidação foi mesclada em uma ou mais ramificações.
Localize a consolidação de mesclagem que trouxe COMMITpara as FILIAIS especificadas.
Especificamente, procure o commit mais antigo no histórico do primeiro pai BRANCHque contém o COMMITcomo um ancestral.
Diga-nos (por padrão) o caminho causal mais antigo de confirmações e mesclagens para fazer com que a confirmação solicitada chegue a um ramo nomeado. Se uma confirmação foi feita diretamente em uma ramificação nomeada, esse é obviamente o caminho mais antigo.
Por caminho causal mais antigo, queremos dizer o caminho que se fundiu em um ramo nomeado o mais cedo, pelo tempo de consolidação (a menos que --topo-orderseja especificado).
DESEMPENHO
Se muitas ramificações (por exemplo, centenas) contiverem a confirmação, o sistema poderá demorar muito tempo (para uma confirmação específica na árvore do Linux, foram necessários 8 segundos para explorar uma ramificação, mas havia mais de 200 ramificações candidatas) para rastrear o caminho para cada confirmação.
A seleção de um determinado --reference-branch --reference tagexame será centenas de vezes mais rápido (se você tiver centenas de filiais candidatas).
EXEMPLOS
# git-what-branch --all 1f9c381fa3e0b9b9042e310c69df87eaf9b46ea4
1f9c381fa3e0b9b9042e310c69df87eaf9b46ea4 first merged onto master using the following minimal temporal path:
v2.6.12-rc3-450-g1f9c381 merged up at v2.6.12-rc3-590-gbfd4bda (Thu May 5 08:59:37 2005)
v2.6.12-rc3-590-gbfd4bda merged up at v2.6.12-rc3-461-g84e48b6 (Tue May 3 18:27:24 2005)
v2.6.12-rc3-461-g84e48b6 is on master
v2.6.12-rc3-461-g84e48b6 is on v2.6.12-n
[...]
Este programa não leva em consideração os efeitos de escolher a confirmação de interesse, apenas as operações de mesclagem.
git-what-branchnão parece mais ser mantido. O git-when-mesclado é uma alternativa escrita em Python que está funcionando muito bem para mim.
sschuberth
@sschuberth obrigado por esta atualização. Incluímos seu comentário na resposta para obter mais visibilidade.
VonC
37
Por exemplo, para descobrir que o c0118facommit veio redesign_interactions:
* ccfd449 (HEAD -> develop) Require to return undef if no digits found
* 93dd5ff Merge pull request #4 from KES777/clean_api
|\
| * 39d82d1 Fix tc0118faests for debugging debugger internals
| * ed67179 Move &push_frame out of core
| * 2fd84b5 Do not lose info about call point
| * 3ab09a2 Improve debugger output: Show info about emitted events
| * a435005 Merge branch 'redesign_interactions' into clean_api
| |\
| | * a06cc29 Code comments
| | * d5d6266 Remove copy/paste code
| | * c0118fa Allow command to choose how continue interaction
| | * 19cb534 Emit &interact event
Você deve executar:
git log c0118fa..HEAD --ancestry-path --merges
E role para baixo para encontrar o último commit de mesclagem . Qual é:
commit a435005445a6752dfe788b8d994e155b3cd9778f
Merge: 0953cac a06cc29
Author: Eugen Konkov
Date: Sat Oct 1 00:54:18 2016 +0300
Merge branch 'redesign_interactions' into clean_api
Esta foi a única solução que me deu o resultado desejado. Eu tentei o resto.
Crafter
Observe que isso só funciona se os resumos de consolidação de mesclagem contiverem os nomes das ramificações usadas nas mesclagens, o que geralmente ocorre por padrão. No entanto git merge -m"Any String Here", ocultará as informações de origem e destino da ramificação.
qneill
@qneill: Não, a fusão sempre tem informações sobre filiais incorporadas: Merge: f6b70fa d58bdcb. Você pode nomear seu commit de mesclagem como você. Não terei problema #
Eugen Konkov
1
@EugenKonkov depois que as ramificações atravessarem a mesclagem, o histórico sobre o caminho no gráfico de origem é deixado no reflog, mas não no banco de dados de objetos git. Eu postei uma resposta tentando explicar o que estou dizendo
qneill
UPD Works versão para mim, comando simples que encontra o original comprometer
vpalmu
9
git branch --contains <ref>é o comando "porcelana" mais óbvio para fazer isso. Se você quiser fazer algo semelhante apenas com os comandos "encanamento":
COMMIT=$(git rev-parse <ref>) # expands hash if needed
for BRANCH in $(git for-each-ref --format "%(refname)" refs/heads); do
if $(git rev-list $BRANCH | fgrep -q $COMMIT); then
echo $BRANCH
fi
done
Opção de um homem pobre é usar a ferramenta tig1 em HEAD, procure a cometer, e siga visualmente a linha do que cometem back-up até que um merge commit é visto. A mensagem de mesclagem padrão deve especificar para qual filial será mesclada onde :)
1 Tig é uma interface em modo de texto baseada em ncurses para o Git. Ele funciona principalmente como um navegador de repositório Git, mas também pode auxiliar no preparo de alterações para confirmação no nível do chunk e atuar como um pager para saída de vários comandos do Git.
Como experiência, criei um gancho pós-confirmação que armazena informações sobre a ramificação com check-out atualmente nos metadados de confirmação. Também modifiquei levemente o gitk para mostrar essa informação.
Para ser sincero, eu não sabia que existiam notas git quando escrevi isso. Sim, usar notas do git para conseguir a mesma coisa é provavelmente uma idéia melhor.
Pajp
3
Eu lido com o mesmo problema ( pipeline de várias filiais da Jenkins ) - tendo apenas confirmado informações e tentando encontrar um nome de filial de onde esse commit veio originalmente. Ele deve funcionar para ramificações remotas, cópias locais não estão disponíveis.
É com isso que trabalho:
git rev-parse HEAD | xargs git name-rev
Opcionalmente, você pode retirar a saída:
git rev-parse HEAD | xargs git name-rev | cut -d' ' -f2 | sed 's/remotes\/origin\///g'
Se o OP estiver tentando determinar o histórico que foi percorrido por uma ramificação quando uma confirmação específica foi criada ("descubra de que ramificação uma submissão é fornecida devido ao seu valor de hash SHA-1"), sem o reflog, não haverá nenhum registros no banco de dados de objetos Git que mostra qual ramificação nomeada estava vinculada a qual histórico de confirmação.
(Postei isso como resposta em resposta a um comentário.)
E qual é a saída git log 80c10e5..HEAD --ancestry-path --merges --oneline --color | tail -n 1e os git log 086c9ce..HEAD --ancestry-path --merges --oneline --color | tail -n 1comandos para os dois casos?
Eugen Konkov
É claro que os SHAs mudam sempre que os comandos são executados. Para respeitar seus comandos, usei HEAD ^ 1 e HEAD ^ 2 em uma nova execução. Os comandos e a saída são: o $ git log HEAD^1..HEAD --ancestry-path --merges --oneline --color | tail -n 1que produz 376142d merge branchese o $ git log HEAD^2..HEAD --ancestry-path --merges --oneline --color | tail -n 1que produz 376142d merge branches - o que mostra o resumo da consolidação de mesclagem, que (como eu estava afirmando) pode ser sobrescrito quando a mesclagem é criada, possivelmente ofuscando o histórico de ramificação da mesclagem.
21418 Qneill
0
TL; DR:
Use o abaixo se você se preocupa com os status de saída do shell:
branch-current - o nome do ramo atual
branch-names - nomes de filiais limpos (um por linha)
branch-name - Verifique se apenas uma ramificação é retornada de branch-names
Ambos branch-namee branch-namesaceitar um commit como argumento, e padrão para HEADse nenhum for dado.
Eu realmente não quero rebaixar isso, porque, estritamente falando, é verdade que o git não armazena permanentemente essas informações, mas é muito possível descobrir isso. Veja minha resposta.
Respostas:
Embora Dav esteja certo de que as informações não são armazenadas diretamente, isso não significa que você nunca possa descobrir. Aqui estão algumas coisas que você pode fazer.
Localizar ramificações nas quais a confirmação está
Isso informará todos os ramos que possuem o commit fornecido em sua história. Obviamente, isso é menos útil se o commit já tiver sido mesclado.
Pesquise os reflogs
Se você estiver trabalhando no repositório no qual a confirmação foi feita, poderá procurar nos reflogs a linha para essa confirmação. Os registros novos com mais de 90 dias são removidos pelo git-gc; portanto, se o commit for muito antigo, você não o encontrará. Dito isto, você pode fazer isso:
encontrar commit a871742. Note que você DEVE usar os 7 primeiros dígitos abreviados do commit. A saída deve ser algo como isto:
indicando que a confirmação foi feita na ramificação "conclusão". A saída padrão mostra hashes de confirmação abreviados, portanto, não procure o hash completo ou você não encontrará nada.
git reflog show
é na verdade apenas um apelido paragit log -g --abbrev-commit --pretty=oneline
, então, se você quiser mexer no formato de saída para disponibilizar coisas diferentes para o grep, esse é o seu ponto de partida!Se você não estiver trabalhando no repositório em que o commit foi feito, o melhor que você pode fazer neste caso é examinar os reflogs e descobrir quando o commit foi introduzido pela primeira vez em seu repositório; com alguma sorte, você buscou o ramo em que estava comprometido. Isso é um pouco mais complexo, porque você não pode percorrer a árvore de confirmação e os reflogs simultaneamente. Você deseja analisar a saída do reflog, examinando cada hash para ver se contém a confirmação desejada ou não.
Encontre uma confirmação de mesclagem subsequente
Isso depende do fluxo de trabalho, mas com bons fluxos de trabalho, as confirmações são feitas nas ramificações de desenvolvimento que são mescladas. Você pode fazer isso:
para ver os commits de mesclagem que têm o commit fornecido como um ancestral. (Se o commit foi mesclado apenas uma vez, o primeiro deve ser a mesclagem que você procura; caso contrário, você terá que examinar alguns, suponho.) A mensagem de commit de mesclagem deve conter o nome do ramo que foi mesclado.
Se você quiser contar com isso, use a
--no-ff
opçãogit merge
para forçar a criação de consolidação de mesclagem, mesmo no caso de avanço rápido. (Porém, não fique muito ansioso. Isso pode se tornar ofuscante se for usado em excesso.) A resposta de VonC a uma pergunta relacionada é útil para elaborar esse tópico.fonte
git describe
suficiente, pois as tags (anotadas) podem ser vistas como mais significativas que as ramificações.--no-ff
tornem importantes, poderá usar a opção para garantir que haja sempre uma confirmação de mesclagem, para poder sempre rastrear o caminho de uma confirmação dada à medida que ela é mesclada com o mestre.-a
flag ao primeiro comando, por exemplo:git branch -a --contains <commit>
-r
.merge --no-ff
para registrar de forma confiável o nome da filial quando você mesclar. Caso contrário, pense nos nomes das filiais como rótulos abreviados temporários e envie as descrições como permanentes. "Que nome abreviado nos referimos a isso durante o desenvolvimento?" realmente não deve ser uma pergunta tão importante quanto "o que esse commit faz?"Este comando simples funciona como um encanto:
git name-rev <SHA>
Por exemplo (onde test-branch é o nome do branch):
Mesmo isso está funcionando para cenários complexos, como:
Aqui
git name-rev commit<SHA2>
retorna branchB .fonte
git name-rev --name-only <SHA>
mais útil obter apenas o nome do ramo. Minha pergunta ... Ele pode retornar mais de um ramo em qualquer circunstância?Atualização em dezembro de 2013:
sschuberth comentários
É baseado em " Localizar consolidação de mesclagem, que inclui uma consolidação específica ".
Resposta original setembro de 2010:
Sebastien Douche apenas twittou (16 minutos antes desta resposta do SO):
Este é um script Perl de Seth Robertson que parece muito interessante:
fonte
git-what-branch
não parece mais ser mantido. O git-when-mesclado é uma alternativa escrita em Python que está funcionando muito bem para mim.Por exemplo, para descobrir que o
c0118fa
commit veioredesign_interactions
:Você deve executar:
E role para baixo para encontrar o último commit de mesclagem . Qual é:
Atualizar
Ou apenas um comando:
fonte
git merge -m"Any String Here"
, ocultará as informações de origem e destino da ramificação.Merge: f6b70fa d58bdcb
. Você pode nomear seu commit de mesclagem como você. Não terei problema #git branch --contains <ref>
é o comando "porcelana" mais óbvio para fazer isso. Se você quiser fazer algo semelhante apenas com os comandos "encanamento":(cruzamento desta resposta SO )
fonte
khichar.anil cobriu a maior parte disso em sua resposta.
Estou apenas adicionando o sinalizador que removerá as tags da lista de nomes de revisões. Isso nos dá:
fonte
Opção de um homem pobre é usar a ferramenta
tig
1 emHEAD
, procure a cometer, e siga visualmente a linha do que cometem back-up até que um merge commit é visto. A mensagem de mesclagem padrão deve especificar para qual filial será mesclada onde :)fonte
Como experiência, criei um gancho pós-confirmação que armazena informações sobre a ramificação com check-out atualmente nos metadados de confirmação. Também modifiquei levemente o gitk para mostrar essa informação.
Você pode conferir aqui: https://github.com/pajp/branch-info-commits
fonte
Eu lido com o mesmo problema ( pipeline de várias filiais da Jenkins ) - tendo apenas confirmado informações e tentando encontrar um nome de filial de onde esse commit veio originalmente. Ele deve funcionar para ramificações remotas, cópias locais não estão disponíveis.
É com isso que trabalho:
Opcionalmente, você pode retirar a saída:
fonte
Eu acho que alguém deve enfrentar o mesmo problema que não pode descobrir o ramo, embora ele exista realmente em um ramo.
É melhor você puxar tudo primeiro:
Em seguida, faça a pesquisa de ramificação:
ou:
fonte
Se o OP estiver tentando determinar o histórico que foi percorrido por uma ramificação quando uma confirmação específica foi criada ("descubra de que ramificação uma submissão é fornecida devido ao seu valor de hash SHA-1"), sem o reflog, não haverá nenhum registros no banco de dados de objetos Git que mostra qual ramificação nomeada estava vinculada a qual histórico de confirmação.
(Postei isso como resposta em resposta a um comentário.)
Felizmente, este script ilustra meu argumento:
A saída mostra a falta de alguma maneira de saber se o commit com 'Add f1' veio da ramificação b1 ou b2 do clone remoto / tmp / r2.
(Últimas linhas da saída aqui)
fonte
git log 80c10e5..HEAD --ancestry-path --merges --oneline --color | tail -n 1
e osgit log 086c9ce..HEAD --ancestry-path --merges --oneline --color | tail -n 1
comandos para os dois casos?$ git log HEAD^1..HEAD --ancestry-path --merges --oneline --color | tail -n 1
que produz376142d merge branches
e o$ git log HEAD^2..HEAD --ancestry-path --merges --oneline --color | tail -n 1
que produz376142d merge branches
- o que mostra o resumo da consolidação de mesclagem, que (como eu estava afirmando) pode ser sobrescrito quando a mesclagem é criada, possivelmente ofuscando o histórico de ramificação da mesclagem.TL; DR:
Use o abaixo se você se preocupa com os status de saída do shell:
branch-current
- o nome do ramo atualbranch-names
- nomes de filiais limpos (um por linha)branch-name
- Verifique se apenas uma ramificação é retornada debranch-names
Ambos
branch-name
ebranch-names
aceitar um commit como argumento, e padrão paraHEAD
se nenhum for dado.Aliases úteis em scripts
Confirmar apenas acessível a partir de apenas uma ramificação
0
.Confirmar alcançável a partir de várias ramificações
1
.Devido ao status de saída, eles podem ser construídos com segurança. Por exemplo, para usar o controle remoto para buscar:
fonte
Para encontrar a filial local:
Para encontrar a ramificação remota:
fonte
Além de pesquisar por toda a árvore até encontrar um hash correspondente, não.
fonte