Rebasing e o que significa rebasing push commits

109

Costuma-se dizer que você não deve rebasear commits que já fez push. O que poderia significar isso?

Hemant Kumar
fonte

Respostas:

80

O livro ProGit tem uma boa explicação .

A resposta específica à sua pergunta pode ser encontrada na seção intitulada " Os perigos do rebaseamento ". Uma citação dessa seção:

Quando você rebase coisas, você está abandonando commits existentes e criando novos que são semelhantes, mas diferentes. Se você enviar commits em algum lugar e outros puxá-los para baixo e trabalhar com base neles, e então você reescrever esses commits com rebase git e colocá-los novamente, seus colaboradores terão que re-fundir seus trabalhos e as coisas ficarão confusas quando você tentar coloque o trabalho deles de volta no seu.

Atualização: com
base em seu comentário abaixo, parece que você está tendo dificuldades com o fluxo de trabalho do Git. Aqui estão algumas referências que podem ajudar:

Tim Henigan
fonte
Obrigada pelo esclarecimento. Então, apenas para tornar meu entendimento mais claro, depois de empurrar certas mudanças, não devo usar git rebase(--interativo?) Para reescrever esse histórico, esta é a receita certa de falha. Por outro lado, se eu tiver rebaseado certas mudanças no tópico branch (do branch X) e empurrá-lo, é perfeitamente normal rebase novamente após outro desenvolvedor alterar o branch de tópico. Essencialmente, tenho usado mergepor algum tempo, mas estamos no mesmo barco que darwinweb.net/articles/86 e a história está quase inutilizável.
Hemant Kumar
@Hemant: Rebasear commits após empurrar para um repo público geralmente é uma má ideia. Dito isso, o conselho do artigo da darwinweb que você citou parece razoável se o seu fluxo de trabalho for semelhante ao deles. Veja minha resposta atualizada para uma lista de outras referências que podem ajudar.
Tim Henigan
Atualize um link para a página "ProGit" sobre "Private equipe conseguiu" para git-scm.com/book/en/...
Eimantas
Então, tecnicamente, git commits permanece o mesmo, mas "abandonar commits existentes e criar novos que são semelhantes, mas diferentes" são apenas o mesmo commit com sha1 id diferentes? bem, essa seria a única maneira óbvia que consigo imaginar de por que os colaboradores teriam que fundir novamente seus próprios trabalhos!
Ciasto piekarz
@Ciastopiekarz, isso ocorre porque você está reescrevendo a história no repositório upstream, e os repositórios locais de outros desenvolvedores podem ter indicações para isso. Agora, seus ponteiros estão obsoletos: o cliente git não tem alternativa a não ser usar ponteiros mais antigos e confiar no ser humano para resolver o resto. Esta é uma nova fusão e pode ser MUITO confusa, com muitas alterações confusas que devem ser resolvidas manualmente! Portanto, a recomendação de nunca realocar nada que já foi enviado para um repositório upstream. Este é um bom conselho e não deve ser ignorado, a menos que você seja um especialista com profundo conhecimento.
Forbin
240

Para entender isso, precisamos entender um pouco sobre como o git funciona. Um repositório git é uma estrutura de árvore, onde os nós da árvore são commits. Aqui está um exemplo de repositório muito simples: Quando você bifurca

ele tem quatro commits no branch master, e cada commit tem um ID (neste caso, a, b, c e d). Você notará que d é atualmente o último commit (ou HEAD) do branch master. insira a descrição da imagem aqui

Aqui, temos dois branches: master e my-branch. Você pode ver que master e my-branch contêm commits aeb, mas então eles começam a divergir: master contém c e d, enquanto my-branch contém e e f. b é considerado a "base de mesclagem" de my-branch em comparação com o master - ou mais comumente, apenas a "base". Faz sentido: você pode ver que my-branch foi baseado em uma versão anterior do master.

Então, digamos que my-branch ficou obsoleto e você deseja atualizá-lo com a versão mais recente do master. Em outras palavras, my-branch precisa conter c e d. Você poderia fazer um merge, mas isso faz com que o branch contenha commits de merge estranhos que tornam a revisão da solicitação pull muito mais difícil. Em vez disso, você pode fazer um rebase.

insira a descrição da imagem aqui

Quando você rebase, git encontra a base de seu branch (neste caso, b), encontra todos os commits entre aquela base e HEAD (neste caso, eef), e reproduz esses commits no HEAD do branch você está baseando em (neste caso, mestre). Na verdade, o Git cria novos commits que representam a aparência de suas alterações em cima do master: no diagrama, esses commits são chamados de e ′ e f ′. Git não apaga seus commits anteriores: e e f são deixados intactos, e se algo der errado com o rebase, você pode voltar para o jeito que as coisas costumavam ser.

Quando muitas pessoas diferentes estão trabalhando em um projeto simultaneamente, as solicitações pull podem ficar obsoletas rapidamente. Uma solicitação pull "desatualizada" é aquela que não está mais atualizada com a linha principal de desenvolvimento e precisa ser atualizada antes de ser incorporada ao projeto. O motivo mais comum pelo qual as solicitações pull ficam obsoletas é devido a conflitos: se duas solicitações pull modificarem linhas semelhantes no mesmo arquivo e uma solicitação pull for mesclada, a solicitação pull não mesclada agora terá um conflito. Às vezes, uma solicitação pull pode ficar obsoleta sem conflitos: talvez as alterações em um arquivo diferente na base de código exijam alterações correspondentes em sua solicitação pull para se adequar à nova arquitetura, ou talvez o branch foi criado quando alguém acidentalmente mesclou testes de unidade com falha ao ramo mestre. Independentemente do motivo,

pseudoCoder
fonte
68

Rebasing reescreve a história. Se ninguém sabe sobre essa história, então tudo bem. Se, no entanto, essa história for conhecida publicamente, então reescrever a história no Git funciona da mesma forma que funciona no mundo real: você precisa de uma conspiração.

É realmente difícil manter conspirações juntas, então é melhor evitar rebasear agências públicas em primeiro lugar.

Note que não são exemplos de conspirações de sucesso: o puramo do repositório git do Junio C. Hamano (o repositório oficial do Git SCM) é rebased freqüência. A maneira como isso funciona é que praticamente todo mundo que usa putambém está inscrito na lista de discussão do desenvolvedor Git, e o fato de o pubranch ser rebaseizado é amplamente divulgado na lista de discussão e no site do Git.

Jörg W Mittag
fonte
4
+1. Acho que o pubranch de git.git é um exemplo extremamente útil de como usar rebase em um fluxo de trabalho (público). Para aqueles que não estão familiarizados com ele, a idéia geral é rebasear branches de tópico que não possuem nenhum commit next(o branch instável antes de mesclar para master), então reconstruir o pubranch reiniciando para next, e fundindo todos os branches de tópico. (Fonte: Documentation / howto / keep-git.txt git.kernel.org/?p=git/git.git;a=blob;f=Documentation/howto/… )
Cascabel
25
+1 para "reescrever a história no Git funciona da mesma forma que no mundo real: você precisa de uma conspiração"
Sleeper Smith
"Um anúncio público não é necessário, pois pu é um ramo descartável, conforme descrito acima." git-scm.com/docs/gitworkflows Fazemos algo semelhante no trabalho, "TEMP-something-latest" é um branch descartável que é uma combinação das mudanças mais recentes, pode ser uma fusão de vários branches de recursos, pode ser excluído e recriados em qualquer momento e não devem ser desenvolvidos.
pilkch
6

Um rebase altera o histórico do seu repositório. Se você enviar commits para o mundo, isto é, torná-los disponíveis para outros, e então mudar sua visão do histórico de commits, torna-se difícil trabalhar com qualquer pessoa que tenha seu histórico antigo.

Rebase considerado prejudicial é uma boa visão geral, eu acho.

dsolimano
fonte