Eu tenho um repositório com ramos mestre e A e muita atividade de mesclagem entre os dois. Como posso encontrar o commit no meu repositório quando o ramo A foi criado com base no mestre?
Meu repositório basicamente se parece com isso:
-- X -- A -- B -- C -- D -- F (master)
\ / \ /
\ / \ /
G -- H -- I -- J (branch A)
Estou procurando a revisão A, que não é o que git merge-base (--all)
encontra.
Respostas:
Eu estava procurando a mesma coisa e encontrei esta pergunta. Obrigado por perguntar!
No entanto, descobri que as respostas que eu vejo aqui não parecem bastante dar a resposta que você pediu (ou que eu estava procurando) - eles parecem dar a
G
comprometer, em vez doA
cometer.Então, eu criei a seguinte árvore (letras atribuídas em ordem cronológica), para que eu pudesse testar as coisas:
Isso parece um pouco diferente do seu, porque eu queria ter certeza (de referir-me a este gráfico, não o seu) B, mas não A (e não D ou E). Aqui estão as cartas anexadas aos prefixos SHA e às mensagens de confirmação (meu repositório pode ser clonado daqui , se isso for interessante para alguém):
Assim, o objetivo: encontrar B . Aqui estão três maneiras que eu encontrei, depois de alguns ajustes:
1. visualmente, com gitk:
Você deve ver visualmente uma árvore como esta (como vista do mestre):
ou aqui (conforme exibido no tópico):
nos dois casos, selecionei o commit que está
B
no meu gráfico. Depois de clicar nele, seu SHA completo é apresentado em um campo de entrada de texto logo abaixo do gráfico.2. visualmente, mas a partir do terminal:
git log --graph --oneline --all
(Editar / observação: adicionar
--decorate
também pode ser interessante; adiciona uma indicação de nomes de ramificações, tags etc.) Não adiciona isso à linha de comando acima, pois a saída abaixo não reflete seu uso.que mostra (supondo
git config --global color.ui auto
):Ou, em texto direto:
nos dois casos, vemos o commit 6aafd7f como o menor ponto comum, ou seja,
B
no meu gráfico ouA
no seu.3. Com casca mágica:
Você não especifica na sua pergunta se deseja algo como o descrito acima ou um único comando que fornecerá a única revisão e nada mais. Bem, aqui está o último:
Que você também pode colocar no seu ~ / .gitconfig como (nota: o traço final é importante; obrigado Brian por chamar a atenção para isso) :
O que poderia ser feito através da seguinte linha de comando (complicada entre aspas):
Nota:
zsh
poderia facilmente ter sidobash
, massh
será não trabalho - a<()
sintaxe não existe no baunilhash
. (Obrigado novamente, @conny, por me informar sobre isso em um comentário em outra resposta nesta página!)Nota: Versão alternativa do acima:
Obrigado a liori por apontar que o acima pode cair ao comparar ramos idênticos e criar uma forma diff diferente que remove a forma sed da mistura e torna isso "mais seguro" (isto é, retorna um resultado (ou seja, o confirmação mais recente), mesmo quando você compara mestre a mestre):
Como uma linha .git-config:
Do shell:
Então, na minha árvore de teste (que ficou indisponível por um tempo, desculpe; está de volta), que agora funciona tanto no mestre quanto no tópico (dando confirmações G e B, respectivamente). Mais uma vez obrigado, liori, pela forma alternativa.
Então, foi isso que eu [e liori] propus. Parece funcionar para mim. Também permite alguns aliases adicionais que podem ser úteis:
Git-ing feliz!
fonte
diff
é if-then-else modo e apagar alteradas / deletadas linhas de sua saída em vez de contar em ter contexto grande o suficiente, por.:diff --old-line-format='' --new-line-format='' <(git rev-list …) <(git rev-list …)|head -1
.git log -n1 --format=format:%H $(git log --reverse --format=format:%H master..topic | head -1)~
funcionará também, eu acho #git merge-base --fork-point ...
dar o commit B (commit6aafd7f
) para esta árvore? Eu estava ocupado com outras coisas quando você postou isso, e parecia bom, mas finalmente tentei e não estou conseguindo fazer o trabalho ... Ou recebo algo mais recente ou apenas uma falha silenciosa (sem erro mensagem, mas status de saída 1), tentando argumentos comogit co master; git merge-base --fork-point topic
,git co topic; git merge-base --fork-point master
,git merge-base --fork-point topic master
(quer para checkout), etc. existe algo que eu estou fazendo de errado ou faltando?--fork-point
é baseado no reflog, portanto, só funcionará se você tiver feito as alterações localmente. Mesmo assim, as entradas do reflog poderiam ter expirado. É útil, mas não confiável.Você pode estar procurando
git merge-base
:fonte
--all
opção "git merge-base
"git merge-base
cinco horas após a publicação da minha resposta (provavelmente em resposta à minha resposta). No entanto, deixarei esta resposta como está, pois ainda pode ser útil para outra pessoa que encontrar essa pergunta por meio de pesquisa.Eu usei
git rev-list
para esse tipo de coisa. Por exemplo, (observe os 3 pontos)cuspirá o ponto de ramificação. Agora, não é perfeito; desde que você mesclou o mestre na ramificação A algumas vezes, isso dividirá alguns pontos de ramificação possíveis (basicamente, o ponto de ramificação original e, em seguida, cada ponto no qual você mesclou o mestre na ramificação A). No entanto, deve pelo menos diminuir as possibilidades.
Eu adicionei esse comando aos meus aliases em
~/.gitconfig
:para que eu possa chamá-lo como:
fonte
G
vez deA
, de acordo com o gráfico da pergunta original.) Tenho uma resposta que receboA
, que postarei no momento.git checkout topic
e executá-lotopic
no lugar debranch-a
), ele lista648ca357b946939654da12aaf2dc072763f3caee
e37ad15952db5c065679d7fc31838369712f0b338
- ambos37ad159
e648ca35
estão no ancestral dos ramos atuais (o último sendo o atual HEAD detopic
), mas também não é o ponto antes da ramificação. Você tem algo diferente?Se você gosta de comandos concisos,
Aqui está uma explicação.
O comando a seguir fornece a lista de todas as confirmações no mestre que ocorreram após a criação do branch_name
Como você se preocupa apenas com as confirmações mais antigas, deseja a última linha da saída:
O pai do commit mais antigo que não é um ancestral de "branch_name" está, por definição, em "branch_name" e está em "master", pois é um ancestral de algo em "master". Então você tem o commit mais antigo que existe nos dois ramos.
O comando
é apenas uma maneira de mostrar a referência de confirmação pai. Você poderia usar
como queiras.
PS: Não concordo com o argumento de que a ordem dos ancestrais é irrelevante. Depende do que você quer. Por exemplo, neste caso
faz todo o sentido emitir C2 como o commit "ramificado". É quando o desenvolvedor se ramifica de "mestre". Quando ele se ramificou, o ramo "B" nem sequer foi fundido em seu ramo! É isso que a solução deste post fornece.
Se o que você deseja é o último commit C, de modo que todos os caminhos da origem até o último commit no ramo "A" passem por C, então você deseja ignorar a ordem de ancestralidade. Isso é puramente topológico e dá uma idéia de quando você tem duas versões do código funcionando ao mesmo tempo. É quando você usa abordagens baseadas em mesclagem, e ele retornará C1 no meu exemplo.
fonte
git rev-list commit^^!
pode ser simplificada comogit rev-parse commit^
git rev-list --first-parent ^branch_name master
comgit rev-list --first-parent branch_name ^master
porque se o branch master é 0 commits à frente do outro ramo (fast-forwardable a ele), nenhuma saída seria criado. Com minha solução, nenhuma saída é criada se o mestre estiver estritamente à frente (ou seja, o ramo foi totalmente mesclado), que é o que eu quero.git rev-list --first-parent ^topic master
só o levará de volta ao primeiro commit após a última mesclagem demaster
paratopic
(se isso existir).Dado que muitas das respostas neste segmento não dão a resposta que a pergunta estava solicitando, aqui está um resumo dos resultados de cada solução, juntamente com o script que eu usei para replicar o repositório fornecido na pergunta.
O registro
Criando um repositório com a estrutura fornecida, obtemos o log do git de:
Minha única adição é a tag que a torna explícita sobre o ponto em que criamos o branch e, portanto, o commit que desejamos encontrar.
A solução que funciona
A única solução que funciona é a fornecida por lindes retorna corretamente
A
:Como Charles Bailey aponta, porém, essa solução é muito frágil.
Se você
branch_A
entrarmaster
e depoismaster
entrarbranch_A
sem comprometer a intervenção, a solução de Lindes apenas fornecerá a primeira divergência mais recente .Isso significa que, para o meu fluxo de trabalho, acho que vou ter que marcar o ponto de ramificação de ramificações de execução longa, pois não posso garantir que elas possam ser encontradas mais tarde.
Isso realmente tudo se resume a
git
s falta do quehg
chama ramos nomeados . O JHW blogueiro chama essas linhagens vs. famílias em seu artigo porque eu gosto Mercurial More Than Git e seu artigo de follow-up Mais sobre Mercurial vs. Git (com gráficos!) . Eu recomendaria pessoas lê-los para ver por que alguns convertidos mercuriais não perca ter chamado ramos emgit
.As soluções que não funcionam
A solução fornecida pelo mipadi retorna duas respostas
I
eC
:A solução fornecida por Greg Hewgill retorna
I
A solução fornecida por Karl retorna
X
:O script
Duvido que a versão git faça muita diferença para isso, mas:
Agradeço a Charles Bailey por me mostrar uma maneira mais compacta de criar scripts para o repositório de exemplo.
fonte
diff -u <(git rev-list branch_A) <(git rev-list master) | tail -2 | head -1
. Obrigado por fornecer instruções para criar o repo :)Em geral, isso não é possível. No histórico de uma ramificação, uma ramificação e mesclagem antes que uma ramificação nomeada fosse ramificada e uma ramificação intermediária de duas ramificações nomeadas são iguais.
No git, ramificações são apenas os nomes atuais das dicas de seções da história. Eles realmente não têm uma identidade forte.
Isso geralmente não é um grande problema, pois a base de mesclagem (consulte a resposta de Greg Hewgill) de dois commits geralmente é muito mais útil, fornecendo o commit mais recente compartilhado pelos dois ramos.
Uma solução que depende da ordem dos pais de uma consolidação obviamente não funcionará em situações em que uma ramificação foi totalmente integrada em algum momento do histórico da ramificação.
Essa técnica também cai se uma mesclagem de integração tiver sido feita com os pais revertidos (por exemplo, uma ramificação temporária foi usada para executar uma mesclagem de teste no mestre e, em seguida, avançou rapidamente na ramificação do recurso para aumentar ainda mais).
fonte
git
tinha um equivalente aohg
's chamado ramos, seria tornar o gerenciamento de ramos de manutenção de longa vida de modo muito mais fácil.Que tal algo como
fonte
diverges = !bash -c 'git rev-parse $(diff <(git log --pretty=oneline ${1}) <(git log --pretty=oneline ${2}) | tail -1 | cut -c 3-42)^'
(sem arquivos temporários)G
vez deA
, de acordo com o gráfico da pergunta original.) Acho que encontrei uma resposta, que postarei atualmente.diff -u <(git rev-list branch_A) <(git rev-list master) | tail -2 | head -1
Certamente estou perdendo alguma coisa, mas na IMO, todos os problemas acima são causados porque estamos sempre tentando encontrar o ponto de ramificação que remonta à história e isso causa todos os tipos de problemas devido às combinações disponíveis.
Em vez disso, segui uma abordagem diferente, com base no fato de que ambas as filiais compartilham muito histórico, exatamente todo o histórico antes da ramificação é 100% o mesmo. Portanto, em vez de voltar, minha proposta é seguir em frente (a partir de 1º commit), procurando a 1ª diferença nos dois ramos. O ponto de ramificação será, simplesmente, o pai da primeira diferença encontrada.
Na prática:
E está resolvendo todos os meus casos habituais. Claro que existem fronteiras que não são cobertas, mas ... ciao :-)
fonte
comm --nocheck-order -1 -2 <(git rev-list --reverse --topo-order topic) <(git rev-list --reverse --topo-order master) | head -1
Recentemente, também precisei resolver esse problema e acabei escrevendo um script Ruby para isso: https://github.com/vaneyckt/git-find-branching-point
fonte
Depois de muitas pesquisas e discussões, fica claro que não há nenhuma bala mágica que funcionaria em todas as situações, pelo menos não na versão atual do Git.
Foi por isso que escrevi alguns patches que adicionam o conceito de
tail
ramo. Cada vez que uma ramificação é criada, também é criado um ponteiro para o ponto original, atail
ref. Essa referência é atualizada toda vez que a ramificação é rebaseada.Para descobrir o ponto de ramificação do ramo de desenvolvimento, tudo que você precisa fazer é usar
devel@{tail}
, é isso.https://github.com/felipec/git/commits/fc/tail
fonte
Aqui está uma versão melhorada da minha resposta anterior resposta anterior . Ele se baseia nas mensagens de confirmação das mesclagens para descobrir onde a ramificação foi criada pela primeira vez.
Ele funciona em todos os repositórios mencionados aqui, e eu até resolvi alguns que surgiram na lista de discussão . Eu também escrevi testes para isso.
fonte
O comando a seguir revelará o SHA1 do Commit A
git merge-base --fork-point A
fonte
Parece que estou tendo alguma alegria com
A última linha que você obtém é a primeira confirmação no ramo, então é uma questão de obter o pai dela. assim
Parece funcionar para mim e não precisa de diffs e assim por diante (o que é útil, pois não temos essa versão do diff)
Correção: isso não funciona se você estiver no ramo principal, mas estou fazendo isso em um script, o que é menos problemático
fonte
Para encontrar confirmações a partir do ponto de ramificação, você pode usar isso.
fonte
Às vezes, é efetivamente impossível (com algumas exceções de onde você pode ter sorte de ter dados adicionais) e as soluções aqui não funcionam.
O Git não preserva o histórico de referências (que inclui ramificações). Ele armazena apenas a posição atual de cada filial (a cabeça). Isso significa que você pode perder algum histórico de ramificação no git ao longo do tempo. Sempre que você ramifica, por exemplo, perde-se imediatamente qual ramificação era a original. Tudo o que um ramo faz é:
Você pode supor que o primeiro comprometido seja o ramo. Isso costuma ser o caso, mas nem sempre é assim. Não há nada que impeça você de se comprometer com qualquer ramificação primeiro após a operação acima. Além disso, não é garantido que os carimbos de data e hora do git sejam confiáveis. Não é até você se comprometer com os dois que eles realmente se tornam ramificações estruturalmente.
Enquanto nos diagramas tendemos a numerar confirmações conceitualmente, o git não tem um conceito realmente estável de sequência quando a árvore de confirmação se ramifica. Nesse caso, você pode assumir que os números (indicando a ordem) são determinados pelo registro de data e hora (pode ser divertido ver como uma interface do usuário do git lida com as coisas quando você define todos os registros de data e hora para o mesmo).
Isto é o que um humano espera conceitualmente:
Isto é o que você realmente obtém:
Você assumiria que B1 é o ramo original, mas poderia ser simplesmente um ramo morto (alguém fez o checkout -b, mas nunca se comprometeu com ele). Não é até você se comprometer com os dois que você obtém uma estrutura de ramificação legítima no git:
Você sempre sabe que C1 veio antes de C2 e C3, mas nunca sabe com segurança se C2 veio antes de C3 ou C3 antes de C2 (porque você pode definir o horário da estação de trabalho para qualquer coisa, por exemplo). B1 e B2 também são enganosos, pois você não pode saber qual ramificação veio primeiro. Você pode adivinhar muito bem e geralmente preciso em muitos casos. É um pouco como uma pista de corrida. Todas as coisas geralmente são iguais aos carros, então você pode assumir que um carro que vem atrás de uma volta começou uma volta atrás. Também temos convenções muito confiáveis, por exemplo, o mestre quase sempre representa os ramos mais antigos, embora, infelizmente, eu tenha visto casos em que mesmo esse não é o caso.
O exemplo fornecido aqui é um exemplo de preservação de histórico:
O real aqui também é enganoso, porque nós, como humanos, o lemos da esquerda para a direita, da raiz à folha (ref). Git não faz isso. Onde fazemos (A-> B) em nossas cabeças, o git faz (A <-B ou B-> A). Ele lê de ref para root. As referências podem estar em qualquer lugar, mas tendem a ser folhas, pelo menos para ramos ativos. Um ref aponta para um commit e commit apenas contém um like para seus pais, não para seus filhos. Quando um commit é um commit de mesclagem, ele terá mais de um pai. O primeiro pai é sempre o commit original que foi mesclado. Os outros pais sempre são confirmados que foram mesclados no commit original.
Esta não é uma representação muito eficiente, mas uma expressão de todos os caminhos que o git pode seguir de cada referência (B1 e B2).
O armazenamento interno do Git se parece mais com isso (não que A como pai apareça duas vezes):
Se você despejar um commit git bruto, verá zero ou mais campos pai. Se houver zero, significa que não há pai e o commit é uma raiz (você pode realmente ter várias raízes). Se houver um, significa que não houve mesclagem e não é um commit raiz. Se houver mais de um, significa que o commit é o resultado de uma mesclagem e todos os pais após o primeiro são mesclados.
Quando os dois atingem A, a cadeia será a mesma, antes disso a cadeia será totalmente diferente. O primeiro commit que outros dois commits têm em comum é o ancestral comum e de onde eles divergem. pode haver alguma confusão aqui entre os termos commit, branch e ref. Na verdade, você pode mesclar um commit. É isso que a mesclagem realmente faz. Uma ref simplesmente aponta para um commit e uma ramificação nada mais é que uma ref na pasta .git / refs / heads, o local da pasta é o que determina que uma ref é uma ramificação e não algo como uma tag.
Onde você perde a história é que a mesclagem fará uma de duas coisas, dependendo das circunstâncias.
Considerar:
Nesse caso, uma mesclagem em qualquer direção criará um novo commit com o primeiro pai como o commit apontado pelo ramo atual com check-out e o segundo pai como o commit na ponta do ramo que você mesclou em seu ramo atual. Ele precisa criar um novo commit, pois os dois ramos têm alterações desde o ancestral comum que deve ser combinado.
Neste ponto, D (B1) agora possui os dois conjuntos de alterações de ambos os ramos (ele mesmo e B2). No entanto, o segundo ramo não possui as alterações de B1. Se você mesclar as alterações de B1 em B2 para que elas sejam sincronizadas, você pode esperar algo parecido com isso (você pode forçar o git merge a fazer isso dessa maneira, porém com --no-ff):
Você conseguirá isso mesmo que B1 tenha confirmações adicionais. Enquanto não houver alterações em B2 que B1 não possua, as duas ramificações serão mescladas. Ele faz um avanço rápido que é como uma rebase (as rebotes também comem ou linearizam o histórico), exceto ao contrário de uma rebase, pois apenas uma ramificação tem um conjunto de alterações, não é necessário aplicar um conjunto de alterações de uma ramificação em cima da outra.
Se você parar de trabalhar no B1, tudo ficará bem em preservar a história a longo prazo. Somente B1 (que pode ser mestre) avançará normalmente, portanto o local de B2 no histórico de B2 representa com êxito o ponto em que foi mesclado em B1. Isto é o que o git espera que você faça, para ramificar B de A e, em seguida, você pode mesclar A em B o quanto quiser enquanto as mudanças se acumulam, no entanto, ao mesclar B de volta a A, não é esperado que você trabalhe em B e mais . Se você continuar trabalhando em sua ramificação após avançar rapidamente, incorporando-a novamente à ramificação em que estava trabalhando, apagará o histórico anterior de B todas as vezes. Você está realmente criando uma nova ramificação toda vez que o avanço rápido é confirmado na origem e depois confirmado na ramificação.
1 a 3 e 5 a 8 são ramificações estruturais que aparecem se você seguir o histórico de 4 ou 9. Não há como o git saber a qual desses ramificações estruturais sem nome e sem referência pertencem os ramos nomeados e de referência como o fim da estrutura. Você pode supor neste desenho que 0 a 4 pertence a B1 e 4 a 9 pertence a B2, mas, além de 4 e 9, não era possível saber qual ramo pertence a qual ramo, eu simplesmente o desenhei de uma maneira que ilusão disso. 0 pode pertencer a B2 e 5 pode pertencer a B1. Existem 16 possibilidades diferentes nesse caso, das quais ramificações nomeadas às quais cada uma das ramificações estruturais poderia pertencer.
Existem várias estratégias git que resolvem isso. Você pode forçar o git merge a nunca avançar rapidamente e sempre criar um branch de mesclagem. Uma maneira horrível de preservar o histórico de ramificações é com tags e / ou ramificações (as tags são realmente recomendadas), de acordo com algumas convenções de sua escolha. Eu realmente não recomendaria um commit vazio no ramo em que você está se fundindo. Uma convenção muito comum é não mesclar em uma ramificação de integração até que você queira realmente fechar sua ramificação. Essa é uma prática que as pessoas devem tentar aderir, caso contrário você está trabalhando em torno de ter ramificações. No entanto, no mundo real, o ideal nem sempre é um significado prático; fazer a coisa certa não é viável para todas as situações. Se o que você '
fonte
man git-reflog
e a parte sobre datas: "master@{one.week.ago} significa" onde o mestre costumava apontar uma semana atrás neste repositório local "". Ou a discussão<refname>@{<date>}
emman gitrevisions
. Ecore.reflogExpire
dentroman git-config
.Não é uma solução para a pergunta, mas achei que valeria a pena observar a abordagem que utilizo quando tenho um ramo de vida longa:
Ao mesmo tempo em que crio a ramificação, também crio uma tag com o mesmo nome, mas com um
-init
sufixo, por exemplo,feature-branch
efeature-branch-init
.(É meio bizarro que essa seja uma pergunta tão difícil de responder!)
fonte
Uma maneira simples de facilitar a visualização do ponto de ramificação
git log --graph
é usar a opção--first-parent
.Por exemplo, aceite o repositório com a resposta aceita :
Agora adicione
--first-parent
:Isso facilita!
Observe que se o repositório tiver muitos ramos, você desejará especificar os 2 ramos que você está comparando em vez de usar
--all
:fonte
O problema parece ser o de encontrar o corte mais recente e de confirmação única entre os dois ramos de um lado e o ancestral comum mais antigo do outro (provavelmente o commit inicial do repo). Isso corresponde à minha intuição de qual é o ponto "ramificação".
Assim, isso não é nada fácil de calcular com os comandos normais do git shell, já que
git rev-list
- nossa ferramenta mais poderosa - não nos permite restringir o caminho pelo qual um commit é alcançado. O mais próximo que temos égit rev-list --boundary
, o que pode nos dar um conjunto de todos os commits que "bloquearam nosso caminho". (Nota:git rev-list --ancestry-path
é interessante, mas não sei como torná-lo útil aqui.)Aqui está o script: https://gist.github.com/abortz/d464c88923c520b79e3d . É relativamente simples, mas devido a um loop, é complicado o suficiente para justificar uma essência.
Observe que a maioria das outras soluções propostas aqui não pode funcionar em todas as situações por um simples motivo:
git rev-list --first-parent
não é confiável no histórico de linearização, pois pode haver mesclagens em qualquer um dos pedidos.git rev-list --topo-order
, por outro lado, é muito útil - para realizar commits em ordem topográfica -, mas fazer diffs é frágil: existem várias ordens topográficas possíveis para um determinado gráfico, portanto, você depende de uma certa estabilidade das ordens. Dito isto, a solução da strongk7 provavelmente funciona muito bem na maioria das vezes. No entanto, é mais lento que o meu como resultado de ter que percorrer toda a história do repositório ... duas vezes. :-)fonte
O seguinte implementa o equivalente git do svn log --stop-on-copy e também pode ser usado para encontrar a origem da ramificação.
Aproximação
Como todos os rios correm para o mar, todos os galhos correm para dominar e, portanto, encontramos uma base de fusão entre galhos aparentemente não relacionados. À medida que voltamos da cabeça do ramo através dos ancestrais, podemos parar na primeira base de mesclagem potencial, pois, em teoria, deveria ser o ponto de origem desse ramo.
Notas
detalhes: https://stackoverflow.com/a/35353202/9950
fonte
Você pode usar o seguinte comando para retornar a confirmação mais antiga em branch_a, que não pode ser acessada pelo mestre:
Talvez com uma verificação de sanidade adicional, verifique se o pai desse commit é realmente acessível pelo mestre ...
fonte
Você pode examinar o reflog do ramo A para descobrir a partir de qual commit ele foi criado, bem como o histórico completo do qual o commit apontou. Os registros estão em
.git/logs
.fonte
Acredito que encontrei uma maneira de lidar com todos os casos mencionados aqui:
Charles Bailey está certo de que as soluções baseadas na ordem dos ancestrais têm apenas um valor limitado; no final do dia, você precisa de algum tipo de registro "esse commit veio do ramo X", mas esse registro já existe; por padrão, 'git merge' usaria uma mensagem de confirmação como "Merge branch 'branch_A' into master", isso informa que todas as confirmações do segundo pai (commit ^ 2) vieram de 'branch_A' e foram mescladas com o primeiro pai (confirmação ^ 1), que é 'mestre'.
Armado com essas informações, você pode encontrar a primeira mesclagem de 'branch_A' (que é quando o 'branch_A' realmente surgiu) e encontrar a base de mesclagem, que seria o ponto de ramificação :)
Eu tentei com os repositórios de Mark Booth e Charles Bailey e a solução funciona; como não pôde? A única maneira de isso não funcionar é se você tiver alterado manualmente a mensagem de confirmação padrão para mesclagens, para que as informações da filial sejam realmente perdidas.
Para utilidade:
Então você pode fazer '
git branch-point branch_A
'.Desfrutar ;)
fonte
git merge -m
para dizer em que mesclei, em vez do nome de um ramo potencialmente efêmero (por exemplo, "mesclar alterações da linha principal no refator do recurso xyz"). Suponha que eu tenha sido menos útil com o meu-m
no meu exemplo? O problema simplesmente não é solúvel em sua plena generalidade, porque eu posso fazer a mesma história com um ou dois ramos temporários e não há como diferenciar.