o que você quer dizer com divergir? você rebase seu mestre depois de empurrá-lo?
hasen
13
Recebo uma mensagem dizendo "Sua filial e 'origem / mestre' divergiram, # e têm 1 e 1 confirmação (ões) diferente cada, respectivamente."
31410 Frank
Atualizei minha resposta para refletir essa mensagem de aviso "divergente".
VonC 16/03/10
A resposta aceita para outra pergunta também pode ser útil na resolução de certos casos em que isso pode entrar em ação (por exemplo, você está tentando mudar seu mestre, mas ele já foi pressionado): stackoverflow.com/questions/2862590/…
"Sua ramificação e 'origem / mestre' divergiram, # e têm 1 e 1 commit (s) diferente cada, respectivamente."
, verifique se você precisa atualizarorigin . Se originestiver atualizado, algumas confirmações foram enviadas para originoutro 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.
Isso diz ao Git para integrar as alterações origin/masterno 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:
Tem uma história diferente: B em vez de A.
Seu conteúdo é responsável por alterações em B e C; é o mesmo que M do exemplo de mesclagem.
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.
Descobri isso enquanto procurava o mesmo problema. Você pode explicar por que 'git reset --hard HEAD' não resolveu o problema?
Neth
12
@ Neth: porque não se trata de modificações em etapas (ou seja, modificações presentes no índice, mas ainda não confirmadas), mas em confirmações locais (que diferem das confirmações presentes no controle remoto). git reset --hard HEADremoveria 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).
VonC 26/11/2010
4
Uau, obrigado por esta resposta incrível. Acidentalmente, fizemos um "git pull" sem "--rebase", e "git rebase origin / master" foi apenas a correção!
Mrooney
3
Que tal - eu só quero ignorar / despejar minhas alterações locais e estar com minha filial local onde está o controle remoto? Em outras palavras, quero masterapontar para o Bseu exemplo.
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.
sim, ele se sente um pouco como a opção manequins, mas se não há perigo real e você está aqui para uma solução rápida - funciona este (pelo menos para mim)
PandaWood
7
Isso precisa estar na ramificação principal antes ("git checkout master").
blueyed
Isso aconteceu comigo uma vez quando recebi as últimas informações de origem, depois alguém fez uma força forçar a origem, o que causou a reversão do commit anterior na origem. Portanto, minha filial local tinha o commit revertido e, quando tentei obter as últimas informações de origem, estava dizendo que tinha que mesclar. Nesse caso, fazia sentido redefinir --hard origin / (branch) porque o problema já havia sido corrigido na origem.
Landon Poch
96
Você provavelmente deve alertar os usuários de que isso vai fazê-los perder todas as alterações ainda não empurrou a origem
Pedro Loureiro
6
Os Commits do @PedroLoureiro são notas realmente perdidas, você ainda pode encontrá- git refloglos ou vê-los gitk --all. Mas, no entanto, é claro que o hard reset é outra coisa que uma recuperação.
sebkraemer
52
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.
por favor mencione que o comando faz, as pessoas mais pode executá-lo e acabar por estragar
Baz1nga
1
Se não houver nenhum problema, você deverá terminar com o seu mestre, contendo todas as alterações de origem / mestre e todas as confirmações locais serão reproduzidas por cima. Parece bom para mim.
Philipp Claßen
7
Exceto quando existem diferenças reais e isso o deixa em uma nova abortada.
ffledgling
Isso gera um erro: erro: falha ao mesclar as alterações. O patch falhou nos modelos de solicitação e resposta 0024
IgorGanapolsky
32
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:
Uma regra prática é usar rebasese 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.
Mikko Rantalainen
1
Infelizmente, eu não li esta mensagem antes de fazer o git rebase master...
Vitaly Isaev
Se eu fizer o git rebase master enquanto estiver no ramo 'foobar', tecnicamente o foobar será desviado da origem / foobar até que eu faça um git push -f, certo?
git reset --hard origin/my_remote_tracking_branché o que realmente funcionou
roothahn
24
No meu caso, aqui está o que eu fiz para causar o mensagem divergente : fiz, git pushmas depois fiz, git commit --amendpara 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 -fsignifica força)
+1 para git push -fsubstituir as alterações confirmadas anteriormente e enviadas para a origem. Também tenho certeza de que ninguém mais tocou no repositório.
Zacharydl
4
Comando muito arriscado. Por favor, escreva uma breve informação sobre o fator de risco do comando.
J4cK
1
@ Malandro: Eu já havia descrito o risco: "como eu sabia que ninguém mais estava tocando origem / mestre". Eu acredito que, nesse caso, este não é um comando arriscado.
Darren Cook
1
Se alguém comete no mestre e, em seguida, uma pessoa executar o impulso de comando git -f então é comando de alto risco
J4cK
11
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/masterramificação remota para que ela estivesse sincronizada com a local masternovamente. A solução no meu caso foi:
git push origin master -f
Observe o -finterruptor (força). Isso excluiu as "alterações incorretas" que foram enviadas origin/masterpor 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.
Sei que há muitas respostas aqui, mas acho que git reset --soft HEAD~1merece 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 rebaseusar, 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~xdeverá 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 applypara 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.
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 pullcomando. 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 commito arquivo resolvido)
Se você também modificou alguns arquivos desde que resolveu o conflito, o git statuscomando 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 commite 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.
Respostas:
Você pode revisar as diferenças com um:
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:
, verifique se você precisa atualizar
origin
. Seorigin
estiver atualizado, algumas confirmações foram enviadas paraorigin
outro repositório enquanto você fazia suas próprias confirmações localmente.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:
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:
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:
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:
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:
Isso combina as etapas de busca e rebase acima em um comando.
fonte
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 oB
seu exemplo.git reset --hard origin/master
como mencionado na resposta abaixo: stackoverflow.com/a/8476004/6309Eu tive isso e estou confuso com o que causou isso, mesmo depois de ler as respostas acima. Minha solução foi fazer
Em seguida, isso redefine minha cópia (local) do mestre (que eu presumo estar estragada) no ponto correto, conforme representado pela origem (remota) / mestre.
fonte
git reflog
los ou vê-losgitk --all
. Mas, no entanto, é claro que o hard reset é outra coisa que uma recuperação.é 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.
fonte
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
E agora você está tentando se recuperar do master como:
PARE AGORA e poupe alguns problemas! Em vez disso, use mesclagem como:
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:
fonte
rebase
se a ramificação que você está refazendo não foi publicada (e usada por outras pessoas). Caso contrário, usemerge
. 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 funcionouNo 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)fonte
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 localmaster
novamente. A solução no meu caso foi:Observe o
-f
interruptor (força). Isso excluiu as "alterações incorretas" que foram enviadasorigin/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.
fonte
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 querebase
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 deHEAD~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
ougit 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.fonte
pull --rebase
esconderijo seria automaticamente. stackoverflow.com/a/30209750/6309Para 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.
fonte
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 primeirogit commit
e adicionando e confirmando as alterações não faseadas como de costume (por exemplo, porgit commit -a
).fonte
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.fonte
Conheci esse problema quando criei uma ramificação baseada na ramificação A por
e, em seguida, defino o fluxo up da ramificação A para originar a ramificação B por
Então recebi a mensagem de erro acima.
Uma maneira de resolver esse problema para mim foi:
fonte