Eu tenho o mesmo problema. Podemos dizer que "a maneira certa de fazer" é realocar o branch local e só então enviar?
Mher Didaryan
Respostas:
154
Quando você rebase um branch, você tem que reescrever os commits para qualquer commit que esteja acima dos commits no branch no qual você está rebase. Isso ocorre porque uma das propriedades de um commit é seu pai (ou pais). Quando você rebase, você está mudando o pai do commit local mais antigo em seu branch - e assim mudando os hashes de commit de todos os seus commits locais, uma vez que esta mudança borbulha pelos commits transitivamente.
Uma vez que você já fez push do branch, você deveria ter fundido no branch de origem, ao invés de rebasing contra ele. É possível "forçar o push" em seu novo branch (usando a -fbandeira), mas um push normal não funcionará, porque a integridade do histórico de branches será perturbada. Se você está colaborando com outras pessoas neste ramo, empurrar à força é uma má ideia, pois fará com que outros colaboradores fiquem muito confusos quando sua história de repente não coincidir.
TL; DR - Se você não estiver colaborando, empurre o branch usando push -f. Se estiver, redefina a ramificação para o estado anterior e mescle na ramificação de origem.
"Já que você já fez push do branch, deveria ter mesclado no branch de origem" - por que isso?
hammett
1
@HamiltonVerissimo A primeira frase de Jason: "Quando você rebase um branch, você tem que reescrever os commits para qualquer commit que esteja acima dos commits no branch no qual você está rebase." Mesmo que as mudanças capturadas nos commits "acima" tenham o mesmo conteúdo lógico, elas estão sendo aplicadas a uma base diferente e, portanto, são commits diferentes com hashes diferentes. Se outros desenvolvedores estiverem trabalhando a partir do branch pré-rebaseado, fazer um git push -f seria extremamente perturbador para o fluxo de trabalho. Portanto, como este branch foi transferido para uma fonte pública, ele deveria ter fundido.
awolf
4
você também pode usar push --force-with-lease se não tiver certeza se alguém já enviou algo.
Console de
1
@ jason-lebrun Não é a desvantagem de mesclar as alterações do upstream que você pode sobrescrever seu próprio trabalho sem aviso? Os conflitos de mesclagem são detectados da mesma forma que no rebasing? Por exemplo, se eu remover uma seção de um arquivo em meu branch porque ela não é mais necessária, mas outra pessoa fez uma alteração trivial na mesma seção no upstream, como remover alguns espaços em branco ou alguma ação global localizar / substituir, não mesclar isso no topo do meu branch substituir minha exclusão com sua versão modificada trivialmente?
Chris Bloom
1
Mesclar o outro branch com o seu não é uma má ideia? Por exemplo, mesclar master em um branch de recurso - isso não criará um novo commit para isso? Isso não resultará em um commit extra, uma vez que este branch de recurso se mesclar para master mais tarde?
Ross
55
Todos os seus commits mudaram de id, então o desvio não é verdadeiramente uma divergência.
Para resolver seu problema, você deve sobrescrever seu branch remoto:
Veja como nesta imagem C3 não é colocado como C3 após o rebase, mas como C3 '. Isso ocorre porque não é exatamente C3, mas tem todas as alterações de código.
Nesta outra imagem, você tem uma ideia do que um rebase é visto quando um controle remoto está envolvido, e por que há um desvio.
Em qualquer caso, depois de fazer o push forçado, ele dirá que fez uma (atualização forçada), você deve estar bem nesse ponto.
Verifique o link no topo e procure por "git push --force". Você verá uma explicação mais detalhada.
Sim. Acho que isso resolve o problema. Porém, force push pode não funcionar quando você está trabalhando em uma equipe, quando seu push pode substituir qualquer trabalho recente enviado por outros. Estou certo?
Hari Krishna Ganji
Pode não ter os efeitos desejados. Certifique-se de mesclar suas alterações 'fast forward' antes de fazer o rebase.
mimoralea
1
Tive sucesso com a divergência de rebase para um push ao fazer o seguinte:
Seu branch está à frente de 'origin / mybranch' por 3 commits.
APÓS EMPURRAR
mybranch está 3 à frente do branch e ainda tem uma mensagem de mesclagem de solicitação de pull aberta adicionada ao histórico de commits Merge branch mybranch de remoto em mybranch
Estou assumindo que isso é provavelmente o que o impulso de força faz, e não verifiquei.
Como os outros disseram, evite um rebase se você já tiver uma solicitação pull aberta. Estou fornecendo este exemplo como algo que funcionou para mim.
Isso pode ser corrigido sem um force push, rebaseando o branch de destino em seu branch local atual, mudando para seu branch de destino e, em seguida, rebaseando seu branch local no alvo. Isso não diverge, pois os commits que podem estar faltando são adicionados e não precisam mais ser criados. Exemplo para uma explicação mais fácil:
ramo principal é desenvolver
Você verifica um novo branch feature / doing_stuff
Um membro da equipe empurra um novo compromisso para desenvolver
Se você NÃO atualizou seu branch de desenvolvimento, então um "git checkout developers" && "git rebase feature / doing_stuff" funcionará corretamente, já que nenhum commit foi adicionado desde o seu checkout. No entanto, se você fez check-out do desenvolvimento e baixou o novo commit, então você verá essa divergência se tentar rebase devido a um novo commit ser visto. Uma solução fácil sem empurrar com força (geralmente não é uma boa ideia em um ambiente de equipe) é:
git checkout feature / doing_stuff
git rebase desenvolva
git checkout development
git rebase feature / doing_stuff
O rebase da etapa 2 traz o commit ausente para o feature / doing_stuff, portanto, quando a etapa 4 chega, ele está atualizado e não precisa criar um novo commit para a mudança.
Esta é uma solução que eu sei que funciona porque acabei de encontrar isso e executei as etapas acima para desenvolver o push com sucesso sem forçar. Eu trabalho em uma equipe de mais de 50 desenvolvedores, então é proibido forçar o envio de qualquer coisa que não seja meus próprios branches de teste, então eu tive que encontrar uma solução.
Respostas:
Quando você rebase um branch, você tem que reescrever os commits para qualquer commit que esteja acima dos commits no branch no qual você está rebase. Isso ocorre porque uma das propriedades de um commit é seu pai (ou pais). Quando você rebase, você está mudando o pai do commit local mais antigo em seu branch - e assim mudando os hashes de commit de todos os seus commits locais, uma vez que esta mudança borbulha pelos commits transitivamente.
Uma vez que você já fez push do branch, você deveria ter fundido no branch de origem, ao invés de rebasing contra ele. É possível "forçar o push" em seu novo branch (usando a
-f
bandeira), mas um push normal não funcionará, porque a integridade do histórico de branches será perturbada. Se você está colaborando com outras pessoas neste ramo, empurrar à força é uma má ideia, pois fará com que outros colaboradores fiquem muito confusos quando sua história de repente não coincidir.TL; DR - Se você não estiver colaborando, empurre o branch usando push -f. Se estiver, redefina a ramificação para o estado anterior e mescle na ramificação de origem.
fonte
Todos os seus commits mudaram de id, então o desvio não é verdadeiramente uma divergência.
Para resolver seu problema, você deve sobrescrever seu branch remoto:
http://git-scm.com/book/ch3-6.html
Explicação:
Veja como nesta imagem C3 não é colocado como C3 após o rebase, mas como C3 '. Isso ocorre porque não é exatamente C3, mas tem todas as alterações de código.
Nesta outra imagem, você tem uma ideia do que um rebase é visto quando um controle remoto está envolvido, e por que há um desvio.
Em qualquer caso, depois de fazer o push forçado, ele dirá que fez uma (atualização forçada), você deve estar bem nesse ponto.
Verifique o link no topo e procure por "git push --force". Você verá uma explicação mais detalhada.
fonte
Tive sucesso com a divergência de rebase para um push ao fazer o seguinte:
A atração resolveu a divergência.
ANTES de puxar
PULL output
APÓS puxar
APÓS EMPURRAR
Estou assumindo que isso é provavelmente o que o impulso de força faz, e não verifiquei.
Como os outros disseram, evite um rebase se você já tiver uma solicitação pull aberta. Estou fornecendo este exemplo como algo que funcionou para mim.
fonte
Isso pode ser corrigido sem um force push, rebaseando o branch de destino em seu branch local atual, mudando para seu branch de destino e, em seguida, rebaseando seu branch local no alvo. Isso não diverge, pois os commits que podem estar faltando são adicionados e não precisam mais ser criados. Exemplo para uma explicação mais fácil:
Se você NÃO atualizou seu branch de desenvolvimento, então um "git checkout developers" && "git rebase feature / doing_stuff" funcionará corretamente, já que nenhum commit foi adicionado desde o seu checkout. No entanto, se você fez check-out do desenvolvimento e baixou o novo commit, então você verá essa divergência se tentar rebase devido a um novo commit ser visto. Uma solução fácil sem empurrar com força (geralmente não é uma boa ideia em um ambiente de equipe) é:
O rebase da etapa 2 traz o commit ausente para o feature / doing_stuff, portanto, quando a etapa 4 chega, ele está atualizado e não precisa criar um novo commit para a mudança.
Esta é uma solução que eu sei que funciona porque acabei de encontrar isso e executei as etapas acima para desenvolver o push com sucesso sem forçar. Eu trabalho em uma equipe de mais de 50 desenvolvedores, então é proibido forçar o envio de qualquer coisa que não seja meus próprios branches de teste, então eu tive que encontrar uma solução.
fonte