Qual é a melhor (e mais segura) maneira de mesclar uma ramificação Git no master?

2104

Um novo ramo masteré criado, como chamamos test.

Existem vários desenvolvedores que se comprometem masterou criam outros ramos e depois se fundem master.

Digamos que o trabalho testesteja demorando vários dias e você deseja manter-se testatualizado continuamente com confirmações dentro master.

Eu faria git pull origin masterde test.

Pergunta 1: Essa é a abordagem correta? Outros desenvolvedores poderiam ter trabalhado facilmente nos mesmos arquivos que eu trabalhei.


Meu trabalho testestá concluído e estou pronto para mesclá-lo novamente master. Aqui estão as duas maneiras em que consigo pensar:

UMA:

git checkout test
git pull origin master
git push origin test
git checkout master
git pull origin test 

B:

git checkout test
git pull origin master
git checkout master
git merge test

Eu não estou usando --rebaseporque, pelo que entendi, o rebase obterá as alterações mastere empilhará as minhas, portanto, poderá sobrescrever as alterações feitas por outras pessoas.

Pergunta 2: Qual desses dois métodos está correto? Qual a diferença aí?

O objetivo de tudo isso é manter minha testramificação atualizada com as coisas acontecendo mastere, mais tarde, eu poderia fundi-las novamente na masteresperança de manter a linha do tempo o mais linear possível.

moe
fonte
18
não .. rebase nunca sobrescreve, apenas tentando alcançar uma história mais limpa. por Reanexar (ou falso) da história até o ponto final do mestre
Junchen Liu
7
rebase não substitui seus commits. Desfaz suas confirmações, aplica as confirmações na ramificação mestre à sua ramificação de teste e, em seguida, aplica suas confirmações de volta ao teste.
zundi

Respostas:

2993

Como eu faria isso

git checkout master
git pull origin master
git merge test
git push origin master

Se eu tenho uma filial local de uma remota, não me sinto à vontade para mesclar outras ramificações além desta com o remoto. Além disso, eu não pressionaria minhas alterações, até estar feliz com o que quero pressionar e também não pressionaria nada, que são apenas para mim e meu repositório local. Na sua descrição, parece que testé apenas para você? Portanto, não há razão para publicá-lo.

O git sempre tenta respeitar as suas e as outras mudanças, e o fará --rebase. Eu não acho que posso explicar isso adequadamente, então dê uma olhada no livro Git - Rebasing ou pronto para git: Introdução a rebasing para uma pequena descrição. É um recurso bem legal

KingCrunch
fonte
2
git merge testme dá fatal: 'test' does not point to a commit. Eu tenho que procurar git logo ponto de confirmação no ramo de teste, voltar para o ramo principal e, em seguida, fazer git merge 0f37d3154abbf52a4cbbbb5109f08af6a7567234.
Duncanmoo
17
@ Duncanmoo Bem, é claro que o ramo testdeve existir. Claro, você pode usar o hash de confirmação, mas geralmente é mais fácil usar o nome da ramificação. Internamente, apenas recupera o hash do HEADramo.
KingCrunch 4/12/14
44
@shanyangqu Para obter as alterações mais recentes do controle remoto. Se você trabalha sozinho e apenas com um sistema, não há problema. Mas quando houver alterações enviadas por um sistema diferente (provavelmente de um desenvolvedor diferente), você verá um conflito assim que tentar empurrar sua mesclagem de volta (a quarta etapa). A única solução agora é mesclar seu mestre local no mestre de controles remotos, que acaba em uma confirmação de mesclagem bastante feia "mestre mesclado em origem / mestre". Portanto, é sempre uma boa idéia fazer um puxão antes da mesclagem
KingCrunch 24/12/15
7
"Na sua descrição, parece que esse teste é apenas para você? Portanto, não há razão para publicá-lo." Você pode enviar sua filial local para um servidor se, por exemplo, esse servidor fornecer um backup contra a falha de sua unidade local ou se você não tiver outros meios para fazer um backup.
Eric
5
"... Além disso, eu não pressionaria minhas alterações até estar feliz com o que quero pressionar ..." por que não pressionar com o objetivo de fazer backup do seu código, caso suas máquinas locais morram e dias de esforços se foram?
Rich Stone
400

Esta é uma pergunta muito prática, mas todas as respostas acima não são práticas.

Gostar

git checkout master
git pull origin master
git merge test
git push origin master

Essa abordagem tem dois problemas :

  1. É inseguro, porque não sabemos se existem conflitos entre a ramificação de teste e a ramificação principal.

  2. Ele "espremeria" todos os commits de teste em um commit de mesclagem no master; isto é, no ramo principal, não podemos ver todos os logs de alterações do ramo de teste.

Portanto, quando suspeitamos que haveria alguns conflitos, podemos ter as seguintes operações git:

git checkout test
git pull 
git checkout master
git pull
git merge --no-ff --no-commit test

Teste mergeantes commit, evite um commit rápido --no-ff,

Se um conflito for encontrado, podemos correr git statuspara verificar detalhes sobre os conflitos e tentar resolver

git status

Depois de resolvermos os conflitos, ou se não houver conflito, nós commite pusheles

git commit -m 'merge test branch'
git push

Mas dessa maneira perderá o histórico de alterações registrado na ramificação de teste e tornaria difícil a ramificação principal para outros desenvolvedores entenderem a história do projeto.

Portanto, o melhor método é o que devemos usar em rebasevez de merge(suponha que, neste momento, resolvamos os conflitos de ramificação).

A seguir, é apresentado um exemplo simples, para operações avançadas, consulte http://git-scm.com/book/en/v2/Git-Branching-Rebasing

git checkout master
git pull
git checkout test
git pull
git rebase -i master
git checkout master
git merge test

Sim, quando você tiver concluído, todas as confirmações da ramificação Teste serão movidas para a cabeça da ramificação Mestre. O principal benefício do rebase é que você obtém um histórico de projeto linear e muito mais limpo.

A única coisa que você precisa evitar é: nunca use rebaseem ramo público, como ramo mestre.

Nunca faça operações como as seguintes:

git checkout master
git rebase -i test

Detalhes para https://www.atlassian.com/git/tutorials/merging-vs-rebasing/the-golden-rule-of-rebasing

apêndice:

John Yin
fonte
4
Concordo que refazer a etapa de teste para depois ser mesclada ao master é o caminho a seguir. Até as outras respostas estão corretas, isso manterá o histórico de alterações do teste de ramificação na cabeça do mestre, pois a outra menção "você recebe um projeto de revestimento e muito mais limpo", que é o objetivo do sistema de controle de versão.
Le0diaz 5/05
16
A afirmação "não é uma maneira de segurança, porque não sabemos se há conflitos entre a ramificação de teste e a ramificação principal" não é verdadeira: sempre é possível abortar a mesclagem. E mesmo que não haja conflitos, você sempre pode desfazer o último commit local, desde que não seja enviado por push. Sem o entendimento correto do git, algumas coisas podem parecer um pouco assustadoras ou pouco claras, mas "inseguras" é incorreta de qualquer forma. Tenha cuidado para não confundir outras pessoas com informações incorretas.
Paul van Leeuwen
4
concorde com @PaulvanLeeuwen, quando você mesclar a ramificação de teste no master, você será notificado sobre conflitos, e é aí que você intervirá e mesclará as alterações. Quando terminar, você confirmará a mesclagem e retornará. Se você se arrepender ou não conseguir mesclá-lo corretamente, sempre poderá descartar seu trabalho e retirar do master novamente. Portanto, não é definitivamente insegura ..
Juan
3
por que rebase -i?
MushyPeas
8
Rebasear é inerentemente mais inseguro do que mesclar. Propor o rebasing como uma opção mais segura para mesclar está errado. Rebasing é uma estratégia válida, mas vem com mais advertências que o usuário deve tomar cuidado.
Ikke
90

Nem uma recuperação nem uma mesclagem devem substituir as alterações de ninguém (a menos que você opte por fazer isso ao resolver um conflito).

A abordagem usual durante o desenvolvimento é

git checkout master
git pull
git checkout test
git log master.. # if you're curious
git merge origin/test # to update your local test from the fetch in the pull earlier

Quando você estiver pronto para voltar ao master,

git checkout master
git log ..test # if you're curious
git merge test
git push

Se você está preocupado com a quebra de algo na mesclagem, git merge --abortexiste para você.

Usar push e pull como meio de mesclagem é bobagem. Também não sei por que você está empurrando o teste para a origem.

raylu
fonte
1
Esse processo aumentará o número de confirmações, toda vez que você alternar entre ramificações, precisará confirmar sua ramificação.
iBug 21/07
2
O que? Você está dizendo que isso aumentará o número de confirmações sempre que você alternar ramificações? Ou você está dizendo que toda vez que você muda de ramificação, precisa "confirmar sua ramificação"? O primeiro é falso e não tenho certeza do que o segundo significa.
raylu 21/07
antes do checkout, você deve confirmar a ramificação. que é o que estou dizendo
iBug
11
Você não: isso é (uma das coisas) git stashserve.
msanford
1
Ou você pode alterar seu último commit (no ramo local) e torná-lo o perfeito antes de pressionar.
whihathac
42

Primeiro, tornaria o ramo a ser mesclado o mais limpo possível. Execute seus testes, verifique se o estado está como você deseja. Limpe os novos commits pelo git squash .

Além da resposta do KingCrunches , sugiro usar

git checkout master
git pull origin master
git merge --squash test
git commit
git push origin master

Você pode ter feito muitas confirmações na outra ramificação, que deve ser apenas uma confirmação na ramificação principal. Para manter o histórico de confirmação o mais limpo possível, você pode compactar todos os seus commit no ramo de teste em um commit no ramo mestre (veja também: Git: Squash ou não squash? ). Em seguida, você também pode reescrever a mensagem de confirmação para algo muito expressivo. Algo fácil de ler e entender, sem se aprofundar no código.

editar: você pode estar interessado em

Então, no GitHub, acabo fazendo o seguinte para um ramo de recursos mybranch:

Receba as últimas informações de origem

$ git checkout master
$ git pull origin master

Encontre o hash da base de mesclagem:

$ git merge-base mybranch master
c193ea5e11f5699ae1f58b5b7029d1097395196f

$ git checkout mybranch
$ git rebase -i c193ea5e11f5699ae1f58b5b7029d1097395196f

Agora, verifique se apenas o primeiro é picko restante s:

pick 00f1e76 Add first draft of the Pflichtenheft
s d1c84b6 Update to two class problem
s 7486cd8 Explain steps better

Em seguida, escolha uma boa mensagem de confirmação e envie para o GitHub. Faça a solicitação de recebimento então.

Após a mesclagem da solicitação pull, você pode excluí-la localmente:

$ git branch -d mybranch

e no GitHub

$ git push origin :mybranch
Martin Thoma
fonte
" que deve ser apenas um commit no ramo mestre ", bem, não necessariamente; você pode wekk quer manter a história
Cocowalla
Certo. Mas, então, simplesmente não esmagar os commits
Martin Thoma
Eu acho que --primeiro pai parece ser a melhor solução. davidchudzicki.com/posts/first-parent
bkribbs
7

Tópico antigo, mas não encontrei o meu jeito de fazê-lo. Pode ser valioso para alguém que trabalha com rebase e deseja mesclar todas as confirmações de uma ramificação (recurso) sobre o mestre. Se houver um conflito no caminho, você poderá resolvê-los para cada confirmação. Você mantém controle total durante o processo e pode abortar a qualquer momento.

Atualize o Master e o Branch:

git checkout master
git pull --rebase origin master
git checkout <branch_name>
git pull --rebase origin <branch_name>

Mesclar ramificação sobre o mestre:

git checkout <branch_name>
git rebase master

Opcional: Se você tiver conflitos durante o Rebase:

Primeiro, resolva o conflito no arquivo. Então:

git add .
git rebase --continue

Empurre seu ramo rebased:

git push origin <branch_name>

Agora você tem duas opções:

  • A) Crie um PR (por exemplo, no GitHub) e faça a mesclagem através da interface do usuário
  • B) Volte na linha de comando e mescle o ramo no master
git checkout master
git merge --no-ff <branch_name>
git push origin master

Feito.

Robin Wieruch
fonte
6

Esse é o fluxo de trabalho que eu uso no meu trabalho com a equipe. O cenário é como você descreveu. Primeiro, quando eu termino de trabalhar, testeu me refiz com o master para obter o que foi adicionado ao master durante o tempo em que trabalhei no testramo.

git pull -r upstream master

Isso fará com que as alterações sejam dominadas desde que você bifurcou o test ramificação e as aplique e, em seguida, aplique as alterações feitas para testar "em cima" do estado atual do mestre. Pode haver conflitos aqui, se as outras pessoas fizeram alterações nos mesmos arquivos que você editou no teste. Se houver, você precisará corrigi-los manualmente e confirmar. Depois de fazer isso, será bom mudar para o ramo principal e entrar testsem problemas.

djheru
fonte
3
git checkout master
git pull origin master
# Merge branch test into master
git merge test

Após a mesclagem, se o arquivo for alterado, quando você o mesclar, ocorrerá o erro "Resolver conflito"

Então, primeiro você precisa resolver todos os seus conflitos, confirmar novamente todas as alterações e pressionar

git push origin master

É melhor fazer quem fez alterações no ramo de teste, porque ele sabia que mudanças ele fez.

Vinay Sikarwar
fonte
3

Eu usaria o método rebase. Principalmente porque reflete perfeitamente seu caso semanticamente, ie. o que você quer fazer é atualizar o estado do seu ramo atual e "fingir" como se fosse baseado no mais recente.

Portanto, sem sequer verificar master, eu faria:

git fetch origin
git rebase -i origin/master
# ...solve possible conflicts here

Obviamente, apenas buscar a origem não atualiza o estado local master(pois não realiza uma mesclagem), mas é perfeitamente aceitável para o nosso propósito - queremos evitar a alternância, para economizar tempo.

user776686
fonte
2

A resposta do @ KingCrunch deve funcionar em muitos casos. Um problema que pode surgir é que você pode estar em uma máquina diferente que precisa extrair as últimas informações do teste. Então, eu recomendo puxar o teste primeiro. A revisão é assim:

git checkout test
git pull
git checkout master
git pull origin master
git merge test
git push origin master
cgnorthcutt
fonte
0

Você precisa fazer o check-out da ramificação para puxar, pois puxar significa mesclar no mestre e você precisa de uma árvore de trabalho para mesclar.

git checkout master
git pull

Não há necessidade de verificar primeiro; rebase faz a coisa certa com dois argumentos

git rebase master test  

git checkout master
git merge test

Por padrão, o git push empurra todos os ramos existentes aqui e no controle remoto

git push
git checkout test
Masoud Mokhtari
fonte
0

Como o título diz "Melhor maneira", acho uma boa idéia considerar a estratégia de mesclagem de paciência .

De: https://git-scm.com/docs/merge-strategies

Com esta opção, 'mesclagem-recursiva' gasta um pouco de tempo extra para evitar distorções que às vezes ocorrem devido a linhas correspondentes sem importância (por exemplo, chaves de funções distintas). Use isso quando os ramos a serem mesclados divergirem bastante. Veja também git-diff [1] --patience.

Uso:

git fetch
git merge -s recursive -X patience origin/master

Alias ​​do Git

Eu sempre uso um alias para isso, por exemplo, execute uma vez:

 git config --global alias.pmerge 'merge -s recursive -X patience'

Agora você pode fazer:

git fetch
git pmerge origin/master
Julian
fonte
0

Este é do GitLab: basta seguir as instruções:

insira a descrição da imagem aqui

shdr
fonte
0

Responderei conforme desenvolver e destacar ramos,

se você estiver no ramo de recursos e precisar atualizá-lo com os comandos develop use abaixo: git checkout desenvolva git pull git checkout feature / xyz git merge develop

Agora, seu recurso está atualizado com o Develop. Você pode enviar suas alterações.

omkar
fonte