De alguma forma, meu mestre e minha origem / ramo mestre divergiram.
Na verdade, não quero que eles divergam.
Como posso ver essas diferenças e 'mesclá-las'?
De alguma forma, meu mestre e minha origem / ramo mestre divergiram.
Na verdade, não quero que eles divergam.
Como posso ver essas diferenças e 'mesclá-las'?
Respostas:
Você pode revisar as diferenças com um:
git log HEAD..origin/master
antes de puxá-lo (buscar + mesclar) (consulte também "Como você faz com que o git sempre puxe de um ramo específico?" )
Quando você tem uma mensagem como:
"Sua ramificação e 'origem / mestre' divergiram, # e têm 1 e 1 commit (s) diferente cada, respectivamente."
, verifique se você precisa atualizarorigin
. Se origin
estiver atualizado, algumas confirmações foram enviadas para origin
outro repositório enquanto você fazia suas próprias confirmações localmente.
... o ---- o ---- A ---- B origin/master (upstream work)
\
C master (your work)
Você baseou o commit C no commit A porque esse foi o trabalho mais recente que você buscou do upstream na época.
No entanto, antes de você tentar voltar à origem, alguém empurrou o commit B.
O histórico de desenvolvimento divergiu em caminhos separados.
Você pode mesclar ou refazer o processo. Consulte Pro Git: Ramificação do Git - Rebasing para obter detalhes.
Mesclar
Use o comando git merge:
$ git merge origin/master
Isso diz ao Git para integrar as alterações origin/master
no seu trabalho e criar uma confirmação de mesclagem.
O gráfico da história agora se parece com isso:
... o ---- o ---- A ---- B origin/master (upstream work)
\ \
C ---- M master (your work)
A nova mesclagem, commit M, tem dois pais, cada um representando um caminho de desenvolvimento que levou ao conteúdo armazenado nesse commit.
Observe que o histórico por trás de M agora não é linear.
Rebase
Use o comando git rebase:
$ git rebase origin/master
Isso diz ao Git para reproduzir o commit C (seu trabalho) como se você o tivesse baseado no commit B em vez de A. Os
usuários do CVS e do Subversion rotineiramente reencaminham suas alterações locais sobre o trabalho upstream quando atualizam antes do commit.
O Git apenas adiciona separação explícita entre as etapas de confirmação e rebase.
O gráfico da história agora se parece com isso:
... o ---- o ---- A ---- B origin/master (upstream work)
\
C' master (your work)
A confirmação C 'é uma nova confirmação criada pelo comando git rebase.
É diferente de C de duas maneiras:
Observe que o histórico por trás de C 'ainda é linear.
Escolhemos (por enquanto) permitir apenas a entrada de histórico linear cmake.org/cmake.git
.
Essa abordagem preserva o fluxo de trabalho baseado no CVS usado anteriormente e pode facilitar a transição.
Uma tentativa de enviar C 'para o nosso repositório funcionará (supondo que você tenha permissões e ninguém tenha pressionado enquanto você estava refazendo).
O comando git pull fornece uma maneira abreviada de buscar a origem e refazer o trabalho local:
$ git pull --rebase
Isso combina as etapas de busca e rebase acima em um comando.
git reset --hard HEAD
removeria apenas qualquer modificação não confirmada indexada local e não faria nada para reconciliar as diferenças entre confirmações local e remota . Somente uma mesclagem ou uma nova reformulação reunirão os dois conjuntos de confirmações (o local e o remoto).
master
apontar para o B
seu exemplo.
git reset --hard origin/master
como mencionado na resposta abaixo: stackoverflow.com/a/8476004/6309
Eu tive isso e estou confuso com o que causou isso, mesmo depois de ler as respostas acima. Minha solução foi fazer
git reset --hard origin/master
Em seguida, isso redefine minha cópia (local) do mestre (que eu presumo estar estragada) no ponto correto, conforme representado pela origem (remota) / mestre.
AVISO : Você perderá todas as alterações ainda não enviadas para
origin/master
.
git reflog
los ou vê-los gitk --all
. Mas, no entanto, é claro que o hard reset é outra coisa que uma recuperação.
git pull --rebase origin/master
é um comando único que pode ajudá-lo na maior parte do tempo.
Editar: extrai as confirmações da origem / mestre e aplica suas alterações no histórico da ramificação recém-extraída.
Eu me encontrei nessa situação quando tentei refazer uma ramificação que estava rastreando uma ramificação remota e tentando refazê-la no mestre. Nesse cenário, se você tentar se refazer, provavelmente encontrará sua ramificação divergente e poderá criar uma bagunça que não é para os git nubees!
Digamos que você esteja no ramo my_remote_tracking_branch, que foi ramificado do master
$ git status
# Na ramificação my_remote_tracking_branch
nada a confirmar (diretório de trabalho limpo)
E agora você está tentando se recuperar do master como:
mestre do rebit do git
PARE AGORA e poupe alguns problemas! Em vez disso, use mesclagem como:
mestre de mesclagem git
Sim, você terminará com confirmações extras em sua filial. Mas, a menos que você esteja disposto a ramificações "não divergentes", esse será um fluxo de trabalho muito mais suave do que a reestruturação. Veja este blog para uma explicação muito mais detalhada.
Por outro lado, se o seu ramo é apenas um ramo local (ou seja, ainda não foi enviado a nenhum controle remoto), você deve fazer uma nova reformulação (e seu ramo não divergirá nesse caso).
Agora, se você está lendo isso porque já está em um cenário "divergente" devido a tal rebase, pode voltar à última confirmação da origem (ou seja, em um estado não divergente) usando:
git reset --hard origin / my_remote_tracking_branch
rebase
se a ramificação que você está refazendo não foi publicada (e usada por outras pessoas). Caso contrário, use merge
. Se você reformular as ramificações já publicadas (e usadas), precisará coordenar uma conspiração para reescrever o histórico em todos os desenvolvedores que usaram sua ramificação.
git rebase master
...
git reset --hard origin/my_remote_tracking_branch
é o que realmente funcionou
No meu caso, aqui está o que eu fiz para causar o mensagem divergente : fiz, git push
mas depois fiz, git commit --amend
para adicionar algo à mensagem de confirmação. Então eu também fiz outro commit.
Então, no meu caso, isso simplesmente significava que a origem / mestre estava desatualizada. Como eu sabia que ninguém mais tocava a origem / mestre, a correção foi trivial: git push -f
(onde -f
significa força)
git push -f
substituir as alterações confirmadas anteriormente e enviadas para a origem. Também tenho certeza de que ninguém mais tocou no repositório.
No meu caso, enviei alterações para origin/master
e depois percebi que não deveria fazê-lo :-( Isso foi complicado pelo fato de as alterações locais estarem em uma subárvore. Então, voltei ao último bom commit antes do local "ruim" alterações (usando SourceTree) e então recebi a "mensagem de divergência".
Depois de consertar minha bagunça localmente (os detalhes não são importantes aqui), eu queria "voltar no tempo" a origin/master
ramificação remota para que ela estivesse sincronizada com a local master
novamente. A solução no meu caso foi:
git push origin master -f
Observe o -f
interruptor (força). Isso excluiu as "alterações incorretas" que foram enviadas origin/master
por engano e agora as ramificações local e remota estão sincronizadas.
Lembre-se de que esta é uma operação potencialmente destrutiva, portanto, execute-a apenas se tiver 100% de certeza de que "voltar" o mestre remoto no tempo está correto.
You are not allowed to force push code to a protected branch on this project.
. Estou tentando empurrar para o meu garfo.
Sei que há muitas respostas aqui, mas acho que git reset --soft HEAD~1
merece alguma atenção, porque isso permite que você mantenha as alterações no último commit local (não pressionado) enquanto resolve o estado divergente. Eu acho que essa é uma solução mais versátil do que rebase
usar, porque o commit local pode ser revisado e até movido para outro ramo.
A chave está usando --soft
, em vez de dura --hard
. Se houver mais de 1 confirmação, uma variação de HEAD~x
deverá funcionar. Então, aqui estão todas as etapas que resolveram minha situação (eu tinha 1 confirmação local e 8 confirmações no controle remoto):
1) git reset --soft HEAD~1
para desfazer a consolidação local. Para as próximas etapas, usei a interface no SourceTree, mas acho que os seguintes comandos também devem funcionar:
2) git stash
para esconder as alterações de 1). Agora todas as mudanças estão seguras e não há mais divergências.
3) git pull
para obter as alterações remotas.
4) git stash pop
ou git stash apply
para aplicar as últimas alterações ocultas, seguidas de uma nova confirmação, se desejado. Esta etapa é opcional, juntamente com 2) , quando você deseja descartar as alterações na confirmação local. Além disso, quando desejar confirmar com outra ramificação, essa etapa deve ser realizada após a mudança para a desejada.
pull --rebase
esconderijo seria automaticamente. stackoverflow.com/a/30209750/6309
Para visualizar as diferenças:
git difftool --dir-diff master origin/master
Isso exibirá as alterações ou diferenças entre os dois ramos. Em araxis (Meu favorito), ele é exibido no estilo diff de pasta. Mostrando cada um dos arquivos alterados. Posso clicar em um arquivo para ver os detalhes das alterações no arquivo.
No meu caso, isso foi causado por não cometer minha resolução de conflitos.
O problema foi causado pela execução do git pull
comando. Alterações na origem levaram a conflitos com meu repositório local, que resolvi. No entanto, eu não os cometi. A solução neste momento é confirmar as alterações ( git commit
o arquivo resolvido)
Se você também modificou alguns arquivos desde que resolveu o conflito, o git status
comando mostrará as modificações locais como modificações locais sem estágio e mesclará a resolução como modificações locais com etapas. Isso pode ser resolvido adequadamente, confirmando as alterações desde a mesclagem primeiro git commit
e adicionando e confirmando as alterações não faseadas como de costume (por exemplo, por git commit -a
).
Eu tinha a mesma mensagem quando estava tentando editar a última mensagem de confirmação, de confirmação já enviada, usando: git commit --amend -m "New message"
Quando enviei as alterações usando, git push --force-with-lease repo_name branch_name
não havia problemas.
Conheci esse problema quando criei uma ramificação baseada na ramificação A por
git checkout -b a
e, em seguida, defino o fluxo up da ramificação A para originar a ramificação B por
git branch -u origin/B
Então recebi a mensagem de erro acima.
Uma maneira de resolver esse problema para mim foi:
git checkout -b b origin/B