Como criar o branch a partir de um commit específico em um branch diferente

102

Fiz vários commits no branch master e depois os mesclei no branch dev.

Quero criar um branch a partir de um commit específico no branch dev, que foi confirmado primeiro no branch master.

Usei os comandos:

git checkout dev
git branch  <branch name> <commit id>

No entanto, isso cria o branch do branch master, não o branch dev que eu esperava. O ID de commit é o mesmo no branch master e no branch dev. Então, como posso distinguir o mesmo id de commit em um branch diferente?

PS: Eu fiz um exemplo no github aqui https://github.com/RolandXu/test_for_branch

Usei os comandos:

git checkout dev
git branch test 07aeec983bfc17c25f0b0a7c1d47da8e35df7af8

O que espero é que o branch de teste contenha aa.txt bb.txt cc.txt. No entanto, o branch de teste contém apenas aa.txt e cc.txt. Provavelmente, ele criou o branch do branch master.

RolandXu
fonte

Respostas:

145

Se você estiver usando esta forma de branchcomando (com ponto inicial), não importa onde você HEADestá.

O que você está fazendo:

git checkout dev
git branch test 07aeec983bfc17c25f0b0a7c1d47da8e35df7af8
  • Primeiro, você configura seu HEADpara o branch dev,

  • Segundo, você inicia um novo branch no commit 07aeec98. Não há bb.txt neste commit (de acordo com seu repositório github).

Se você deseja iniciar um novo branch no local que acabou de verificar, você pode executar o branch sem ponto de partida:

git branch test

ou como outro respondeu, ramifique e faça checkout lá em uma operação:

git checkout -b test

Acho que você pode ficar confuso com o fato de que 07aeec98faz parte do ramo dev. É verdade que este commit é um ancestral de dev, suas mudanças são necessárias para alcançar o último commit em dev. No entanto, eles são outros commits necessários para atingir o último dev, e não estão necessariamente na história do 07aeec98.

8480e8ae(onde você adicionou bb.txt), por exemplo, não está na história de 07aeec98. Se você ramificar de 07aeec98, não obterá as alterações introduzidas por 8480e8ae.

Em outras palavras: se você mesclar o branch A e o branch B no branch C e, em seguida, criar um novo branch em um commit de A, você não obterá as alterações introduzidas em B.

O mesmo aqui, você tinha duas ramificações paralelas master e dev, que você fundiu em dev. Ramificar a partir de um commit do master (mais antigo que o merge) não fornecerá as mudanças de dev.


Se você deseja integrar permanentemente novas mudanças do master em seus branches de recursos, você deve fundir masterneles e continuar. Isso criará commits de mesclagem em seus branches de recursos, no entanto.

Se você ainda não publicou seus ramos de novos recursos, você também pode rebase-los no mestre actualização: git rebase master featureA. Esteja preparado para resolver possíveis conflitos.

Se você deseja um fluxo de trabalho onde pode trabalhar em branches de recursos sem mesclar commits e ainda integrar com mudanças mais recentes no master, recomendo o seguinte:

  • baseie cada novo branch de recurso em um commit do master
  • criar um devbranch em um commit do master
  • quando você precisar ver como seu branch de recurso se integra com as novas mudanças no master, mescle o master e o branch de recurso em dev.

Não se comprometa devdiretamente, use-o apenas para mesclar outros ramos.

Por exemplo, se você estiver trabalhando nos recursos A e B:

a---b---c---d---e---f---g -master
    \       \
     \       \-x -featureB
      \
       \-j---k -featureA

Mescle branches em um devbranch para verificar se funcionam bem com o novo master:

a---b---c---d---e---f---g -master
    \       \            \
     \       \            \--x'---k' -dev
      \       \             /    /   
       \       \-x----------    /    -featureB
        \                      /
         \-j---k--------------- -featureA

Você pode continuar trabalhando em suas ramificações de recursos e continuar mesclando as novas alterações das ramificações mestre e de recursos devregularmente.

a---b---c---d---e---f---g---h---i----- -master
    \       \            \            \
     \       \            \--x'---k'---i'---l' -dev
      \       \             /    /         /
       \       \-x----------    /         /  -featureB
        \                      /         /  
         \-j---k-----------------l------ -featureA

Quando for a hora de integrar os novos recursos, mescle os ramos do recurso (não dev!) No mestre.

Gauthier
fonte
obrigado. Você responde minha pergunta. Estou errado no entendimento do modo de branch git. E você tem alguma sugestão para o meu problema. Eu tenho o branch master que tem muitos commits oportunos de outros (sincronizar com o perforce). Tenho um ramo de desenvolvimento que faço um trabalho pessoal. Eu quero um branch que contém todos os commits do branch master e do branch dev, então posso criar facilmente um branch com base neste branch, e então iniciar o trabalho específico.
RolandXu
Não consegui responder em um comentário, então atualizo minha resposta com fluxos de trabalho sugeridos.
Gauthier
Ei - obrigado pela resposta brilhante e completa! Apenas curiosidade: no final, por que deveria merge the feature branches (not dev!) into master?
cassi.lup
Não há nenhum novo desenvolvimento real no devramo. Você deve manter os recursos de seus branches específicos. devcontém apenas commits de mesclagem. Faz mais sentido mesclar todos os novos recursos diretamente do masterque mesclar os recursos e depois mesclar o resultado em master.
Gauthier de
@Gauthier Você não respondeu por quê. Para mim, parece que mesclar um devcom apenas recursos A Be mesclar Cnele masteré idêntico a mesclar A Be Cem individualmente master. Se não, isso desafia meu entendimento de como o git funciona e eu ficaria muito curioso para saber o porquê!
Steven Lu
53

Você tem os argumentos na ordem errada:

git branch <branch-name> <commit>

e para isso, não importa qual branch é verificado; vai fazer o que você diz. (Se você omitir o argumento commit, o padrão é criar um branch no mesmo lugar do atual.)

Se você deseja verificar o novo branch à medida que o cria:

git checkout -b <branch> <commit>

com o mesmo comportamento se você omitir o argumento commit.

Cascabel
fonte
22

Você pode fazer isso localmente, já que todos mencionaram usando

git checkout -b <branch-name> <sha1-of-commit>

Como alternativa, você pode fazer isso no próprio github, siga as etapas:

1- No repositório, clique em Commits.

2- no commit do qual você deseja ramificar, clique em <>para navegar no repositório neste ponto da história.

compromete história

3- Clique em tree: xxxxxxno canto superior esquerdo. Basta digitar um novo nome de branch e clicar Create branch xxxconforme mostrado abaixo.

criar novo ramo

Agora você pode obter as alterações desse branch localmente e continuar a partir daí.

Muhammad Soliman
fonte
Isso é o que eu precisava .. Como fazer no site
eharo2
Eu nunca soube disso. É isso. A GUI é ótima e eu queria ficar longe da CLI.
Rohit Gupta
10

Experimentar

git checkout <commit hash>
git checkout -b new_branch

O commit deve existir apenas uma vez em sua árvore, não em dois ramos separados.

Isso permite que você verifique aquele commit específico e nomeie como quiser.

ZMorek
fonte
oi, eu tento o git log dev e o git log master, descobri que o hash id do commit é o mesmo para o commit que mesclo para o branch dev do branch master
RolandXu
pode ser útil usar algo como gitkvisualizar seu registro
ZMorek
Recentemente, adicionei um exemplo no github. E Gauthier já respondeu à minha pergunta que eu não entendi o modo de ramificação git. Obrigado :)
RolandXu
Esta é uma resposta acertada, eu acho. Obrigado
virusss8 de
9

Você tem que fazer:

git branch <branch_name> <commit>

(você estava trocando o nome do branch e o commit)

Ou você pode fazer:

git checkout -b <branch_name> <commit>

Se no lugar de você usar o nome do ramo, você obterá um ramo da ponta do ramo.

manojlds
fonte
Não é isso que HEADsignifica. Você poderia dizer "a ponta do galho" ou "o commit para o qual o galho aponta".
Cascabel
@Jefromi - Para ser puristas, podemos dizer apenas o galho, já que o galho em si é um ponteiro para, bem, a ponta do galho.
manojlds