Tenho um colega que afirma git pull
ser prejudicial e fica chateado sempre que alguém o usa.
O git pull
comando parece ser a maneira canônica de atualizar seu repositório local. O uso git pull
cria problemas? Que problemas ele cria? Existe uma maneira melhor de atualizar um repositório git?
git pull --rebase
e definir esta estratégia como padrão para novos ramosgit config branch.autosetuprebase
--rebase
sinalizador paragit pull
sincronizar local com remoto e, em seguida, repete suas alterações locais sobre o local atualizado. Então, quando você pressiona, tudo o que está fazendo é anexar suas novas confirmações no final do controle remoto. Bem simples.Respostas:
Sumário
Por padrão,
git pull
cria confirmações de mesclagem que adicionam ruído e complexidade ao histórico do código. Além disso,pull
facilita não pensar em como suas alterações podem ser afetadas pelas alterações recebidas.O
git pull
comando é seguro desde que execute apenas mesclagens de avanço rápido. Segit pull
estiver configurado para fazer mesclagens de avanço rápido e quando uma mesclagem de avanço rápido não for possível, o Git sairá com um erro. Isso lhe dará a oportunidade de estudar as confirmações recebidas, pensar em como elas podem afetar as confirmações locais e decidir o melhor curso de ação (mesclagem, rebase, redefinição etc.).Com o Git 2.0 e mais recente, você pode executar:
para alterar o comportamento padrão para avançar apenas. Nas versões Git entre 1.6.6 e 1.9.x, você terá o hábito de digitar:
No entanto, com todas as versões do Git, recomendo configurar um
git up
alias como este:e usando em
git up
vez degit pull
. Prefiro esse alias aogit pull --ff-only
invés de:origin/*
galhos antigos que não existem mais a montante.Problemas com
git pull
git pull
não é ruim se for usado corretamente. Várias alterações recentes no Git tornaram mais fácil o usogit pull
adequado, mas infelizmente o comportamento padrão de uma planíciegit pull
tem vários problemas:git pull
Esses problemas são descritos em mais detalhes abaixo.
História não linear
Por padrão, o
git pull
comando é equivalente a execuçãogit fetch
seguido porgit merge @{u}
. Se houver confirmações não enviadas no repositório local, a parte degit pull
mesclagem criará uma confirmação de mesclagem.Não há nada de inerentemente ruim nos commits de mesclagem, mas eles podem ser perigosos e devem ser tratados com respeito:
É claro que existe um tempo e um lugar para mesclagens, mas entender quando as mesclagens devem e não devem ser usadas pode melhorar a utilidade do seu repositório.
Observe que o objetivo do Git é facilitar o compartilhamento e o consumo da evolução de uma base de código, para não registrar com precisão o histórico exatamente como ele se desenrolou. (Se você não concordar, considere o
rebase
comando e por que ele foi criado.) Os commits de mesclagem criados porgit pull
não transmitem semânticas úteis a outras pessoas - eles apenas dizem que alguém passou por push no repositório antes de concluir as alterações. Por que esses commit de mesclagem se não são significativos para os outros e podem ser perigosos?É possível configurar
git pull
para rebase em vez de mesclar, mas isso também tem problemas (discutido mais tarde). Em vez disso,git pull
deve ser configurado para fazer apenas mesclagens de avanço rápido.Reintrodução de confirmações rebatizadas
Suponha que alguém refaça um ramo e a força o empurre. Isso geralmente não deveria acontecer, mas às vezes é necessário (por exemplo, remover um arquivo de log 50GiB que foi acidentalmente confirmado e enviado por push). A mesclagem feita por
git pull
mesclará a nova versão da ramificação upstream na versão antiga que ainda existe no seu repositório local. Se você pressionar o resultado, garfos e tochas começarão a aparecer.Alguns podem argumentar que o problema real é a atualização forçada. Sim, geralmente é aconselhável evitar empurrões de força sempre que possível, mas às vezes são inevitáveis. Os desenvolvedores devem estar preparados para lidar com as atualizações de força, porque elas às vezes acontecem. Isso significa não mesclar cegamente os antigos commit por meio de um ordinário
git pull
.Surpreenda as modificações do diretório de trabalho
Não há como prever como será o diretório ou índice de trabalho até que
git pull
seja concluído. Pode haver conflitos de mesclagem que você precisa resolver antes de fazer qualquer outra coisa; pode introduzir um arquivo de log 50GiB no seu diretório de trabalho porque alguém o pressionou acidentalmente, pode renomear um diretório em que você está trabalhando etc.git remote update -p
(ougit fetch --all -p
) permite que você analise os comprometimentos de outras pessoas antes de decidir mesclar ou se refazer, permitindo que você forme um plano antes de tomar uma ação.Dificuldade para revisar os compromissos de outras pessoas
Suponha que você esteja no meio de fazer algumas alterações e que alguém queira que você revise alguns commits que eles acabaram de enviar.
git pull
A operação de mesclagem (ou rebase) do modifica o diretório e o índice de trabalho, o que significa que seu diretório e índice de trabalho devem estar limpos.Você pode usar
git stash
egit pull
, em seguida , mas o que você faz quando termina de revisar? Para voltar para onde você estava, você deve desfazer a mesclagem criada porgit pull
e aplicar o stash.git remote update -p
(ougit fetch --all -p
) não modifica o diretório ou índice de trabalho, portanto, é seguro executá-lo a qualquer momento, mesmo que você tenha feito mudanças de etapa e / ou etapas. Você pode pausar o que está fazendo e revisar o commit de outra pessoa sem se preocupar em esconder ou concluir o commit em que está trabalhando.git pull
não lhe dá essa flexibilidade.Rebaseando em uma ramificação remota
Um padrão de uso comum do Git é fazer um
git pull
para trazer as alterações mais recentes seguidas de umgit rebase @{u}
para eliminar o commit de mesclagem que foigit pull
introduzido. É o suficiente comum que Git tem algumas opções de configuração para reduzir estes dois passos para um único passo, dizendogit pull
para executar uma alteração de base em vez de um merge (verbranch.<branch>.rebase
,branch.autosetuprebase
epull.rebase
opções).Infelizmente, se você tiver um commit de mesclagem não empurrado que deseja preservar (por exemplo, um commit mesclando um ramo de recurso enviado
master
), nem um rebase-pull (git pull
combranch.<branch>.rebase
definido comotrue
) nem um merge-pull (ogit pull
comportamento padrão ) seguido por um rebase funcionará. Isso ocorre porquegit rebase
elimina mesclagens (lineariza o DAG) sem a--preserve-merges
opção A operação rebase-pull não pode ser configurada para preservar mesclagens e um pull de mesclagem seguido por umgit rebase -p @{u}
não eliminará a mesclagem causada pelo pull de mesclagem. Atualização: Git v1.8.5 adicionadogit pull --rebase=preserve
egit config pull.rebase preserve
. Issogit pull
ocorregit rebase --preserve-merges
depois de buscar as confirmações upstream. (Obrigado ao funkaster pelo heads-up!)Limpando ramificações excluídas
git pull
não remove ramificações de rastreamento remoto correspondentes às ramificações que foram excluídas do repositório remoto. Por exemplo, se alguém excluir uma ramificaçãofoo
do repositório remoto, você ainda veráorigin/foo
.Isso leva os usuários a ressuscitar acidentalmente os ramos mortos porque eles ainda pensam que estão ativos.
Uma alternativa melhor: use em
git up
vez degit pull
Em vez de
git pull
, recomendo criar e usar o seguintegit up
alias:Esse alias baixa todas as confirmações mais recentes de todas as ramificações upstream (removendo as ramificações inativas) e tenta avançar rapidamente a ramificação local para a confirmação mais recente na ramificação upstream. Se for bem-sucedido, não haverá confirmações locais, portanto não haverá risco de conflito de mesclagem. O avanço rápido falhará se houver confirmações locais (não pressionadas), dando a você a oportunidade de revisar as confirmações anteriores antes de tomar uma ação.
Isso ainda modifica seu diretório de trabalho de maneiras imprevisíveis, mas somente se você não tiver nenhuma alteração local. Ao contrário
git pull
,git up
nunca o levará a um prompt esperando que você corrija um conflito de mesclagem.Outra opção:
git pull --ff-only --all -p
A seguir, é uma alternativa ao
git up
alias acima :Esta versão do
git up
tem o mesmo comportamento que ogit up
alias anterior , exceto:-p
argumento que é passado parafetch
) que pode mudar nas versões futuras do GitSe você estiver executando o Git 2.0 ou mais recente
Com o Git 2.0 e mais recente, você pode configurar
git pull
para fazer mesclagens de avanço rápido por padrão:Isso faz
git pull
com que funcione como elegit pull --ff-only
, mas ainda não busca todos os commit upstream nem limpa osorigin/*
galhos antigos, então eu ainda prefirogit up
.fonte
git remote update -p
é equivalente agit fetch --all -p
. Eu tenho o hábito de digitargit remote update -p
porque era uma vezfetch
não tinha a-p
opção. Em relação à liderança!
, consulte a descrição dealias.*
ingit help config
. Ele diz: "Se a expansão do alias for prefixada com um ponto de exclamação, será tratada como um comando do shell".pull.ff
configuração que parece conseguir a mesma coisa, sem aliases.git up
parece uma alternativa interessante.git pull
.Minha resposta, tirada da discussão que surgiu no HackerNews:
Sinto-me tentado a responder à pergunta usando a Lei de Betteridge das manchetes: Por que é
git pull
considerado prejudicial? Não é.fonte
git pull
. No entanto, pode entrar em conflito com algumas práticas prejudiciais, como querer reescrever a história mais do que o estritamente necessário. Mas o git é flexível; portanto, se você quiser usá-lo de uma maneira diferente, faça isso de qualquer maneira. Mas isso é porque você (bem, Richard Hansen) quer fazer algo incomum no git, e não porquegit pull
é prejudicial.git rebase
e considerandogit pull
prejudiciais? Mesmo?git pull
sem a--rebase
opção é a direção da mesclagem criada. Quando você olha para o diff, todas as alterações nessa mesclagem agora pertencem à pessoa que puxou, e não à pessoa que fez as alterações. Eu gosto de um fluxo de trabalho em que a mesclagem é reservada para duas ramificações separadas (A -> B), para que a confirmação de mesclagem seja clara sobre o que foi introduzido, e o rebasing é reservado para se atualizar na mesma ramificação (remota A -> local A )Não é considerado prejudicial se você estiver usando o Git corretamente. Vejo como isso afeta você negativamente, considerando seu caso de uso, mas você pode evitar problemas simplesmente não modificando o histórico compartilhado.
fonte
git pull
não há nenhum tipo de problema. Ramificar no git é barato.A resposta aceita reivindica
mas a partir do Git 1.8.5 , que pós-data dessa resposta, você pode fazer
ou
ou
Os documentos dizem
Esta discussão anterior possui informações e diagramas mais detalhados: git pull --rebase --preserve-merges . Também explica por que
git pull --rebase=preserve
não é o mesmo quegit pull --rebase --preserve-merges
, o que não faz a coisa certa.Esta outra discussão anterior explica o que a variante preservar-mescla de rebase realmente faz, e como é muito mais complexa do que uma rebase regular: O que exatamente faz a "rebase - preservar-mescla" do git (e por quê?)
fonte
Se você vai para o antigo repositório git git-se o alias eles sugerem é diferente. https://github.com/aanand/git-up
git config --global alias.up 'pull --rebase --autostash'
Isso funciona perfeito para mim.
fonte