Partilhar via


Saiba como remover um binário grande do seu histórico do Git para gerenciar o tamanho dos repositórios clonados

Serviços de DevOps do Azure | Azure DevOps Server 2022 - Azure DevOps Server 2019

O Git ganhou muita popularidade nos últimos anos como um repositório de código-fonte distribuído que permite que os usuários trabalhem com o repositório completo enquanto estão em um estado desconectado. Os benefícios do git estão bem documentados, mas o que acontece se você precisar "reverter o relógio" no repositório primário? Fazer isso não é tão intuitivo e requer permissões elevadas, como você pode esperar para algo que afeta todos os usuários do repositório.

Então, como pode-se restaurar o repositório central com segurança?

Cenário Problemático

Imagina que envias um ficheiro grande, como um vídeo, para o teu servidor git. Em um sistema de código-fonte tradicional, é conveniente armazenar tudo em um só lugar e, em seguida, puxar para baixo o que você precisa. No entanto, com o git, todo o repositório é clonado para o computador local de cada usuário. Com um arquivo grande, cada usuário no projeto precisará baixar o(s) arquivo(s) grande(s) também. A cada ficheiro grande subsequente enviado para o servidor, o problema só aumenta, até que o repositório seja demasiado grande para ser eficiente para os seus utilizadores. Para piorar a situação, mesmo que você remova o infrator do repositório local e confirme novamente, o arquivo ainda existirá no histórico do repositório, o que significa que ele ainda será baixado para o computador local de todos como parte do histórico.

Caixa de diálogo Alterações do Team Explorer mostrando vídeo grande nas alterações incluídas

Adicionando arquivo grande ao repositório local

Servidor e repositórios locais, ambos com uma cópia dos grandes arquivos de vídeo

Depois de fazer commit do repositório local, o servidor também terá o arquivo grande

Congelar o repositório

Importante

Os passos seguintes removerão o vídeo do histórico da branch, mas o arquivo permanecerá no seu repositório quando clonares o seu repositório dos Azure Repos. Remover os arquivos do seu histórico de ramificações impede que os arquivos sejam atualizados, o que criará outra versão do arquivo grande em seu repositório. Saiba mais sobre como gerenciar arquivos grandes no Git e veja esta postagem de blog para obter uma explicação detalhada e solução alternativa para esse comportamento ao usar repositórios Git do Azure.

Para corrigir isso, você tem que começar na fonte, que, neste caso, é o repositório do servidor. Peça à equipe para parar de enviar para o repositório, mas se outros pushes acontecerem durante esse processo, você terá que contabilizá-los também, para não perder nenhum dado.

Rebase e forçar o push

Se ninguém mais na equipe tiver feito alterações no repositório - geralmente por push - você pode seguir o caminho mais fácil, no qual você essencialmente faz com que seu repositório local pareça da maneira que você deseja (ou seja, sem o arquivo grande) e, em seguida, force suas alterações no servidor.

Nota: Talvez seja necessário clonar ou corrigir seu repositório local antes de iniciar este trabalho. Isso pode resultar em perda de trabalho ou alterações, portanto, prossiga com cautela.

Por padrão, você provavelmente só tem a capacidade de alterar seus arquivos de projeto e repositório locais e enviar suas alterações para o servidor, portanto, você não tem a capacidade de fazer outras alterações, como exclusões ou rebaseamento, no nível do servidor. Portanto, você precisará adquirir permissões de push forçado do projeto (preferencial) junto ao seu administrador ou encontrar alguém que as tenha e esteja disposto a ajudar. Para obter mais informações sobre permissões git, clique aqui.

Prompt de comando - git push --force permissions.

Em seguida, você precisa rebasear o repositório.

  1. Mas primeiro, use git log para encontrar os valores de hash SHA das confirmações mais recentes - você precisará dessas informações em um momento. Isto porque precisamos de conhecer o bom compromisso mais recente. Você obtém essas informações abrindo um prompt de comando git e digitando:

git log

Como alternativa, você pode obter o hash SHA exibindo o histórico de ramificações no Visual Studio Team Explorer.

Ramo principal Ver Histórico

  1. Agora, abra um prompt de comando do Git.

Caixa de diálogo Sincronização - Ação de Abrir Linha de Comando

  1. Encontre o número de hash SHA de interesse.

Prompt de comando - Selecione confirmação de vídeo

  1. Você irá necessitar do SHA que começa com "25b4"

Lembre-se de que o git usa ponteiros para determinar onde no repositório o cabeçalho ou ramificação atual estão localizados. Por causa disso, o estado do repositório em que você está interessado estará em algum momento no passado. Para 'voltar no tempo' e tornar esse estado desejado anterior o novo estado atual, você precisará usar o comando git rebase:

git rebase -i <SHA hash of desired new current branch>

Rebase para remover o arquivo de vídeo

O -i switch fornece um pouco de segurança extra, porque ele vai trazer o histórico em um editor (Minha implementação do git na linha de comando no Windows traz o editor vi clássico, que você pode se lembrar se você trabalhou com um sistema baseado em Unix.)

  1. Para o nosso exemplo, você digitaria:

git rebase -i 25b4

  1. Quando o editor aparecer, remova todas as linhas de 'escolha', exceto a ramificação que você deseja manter como sua nova cabeça. Quando tudo parecer como você quer, em vi, digite ":w<enter>" para salvar ou "!q<enter>" para sair sem salvar.

Prompt de Comando - comando git rebase -i 25b4 pick

Vai alterar a(s) linha(s) que já não deseja

Prompt de Comando - git rebase -i comando drop 25b4

  1. Altere "pick" para "drop" como mostrado e, em seguida, digite ":w" (em vi) para salvar e ":q!" para iniciar a rebase

Agora digite git log novamente - o ramo problemático deve estar ausente do registo. Se estiver, você está pronto para a etapa final, que requer permissões de administrador do projeto.

git log

Repositórios locais e de servidor após a rebase

Note que o commit para o vídeo de grande porte deixou de estar presente no repositório local

  1. Tipo: git push --force

Prompt de comando - git push --force

Linha de Comando - git push --force result

Este comando forçará o repositório a sobrescrever o repositório no servidor.

Use com cuidado, pois você pode facilmente perder dados no servidor!!

Forçar envio mostrando o conteúdo a manter, sem o ficheiro de vídeo

Observe que você deve autenticar no servidor para que isso funcione

Se estiver a utilizar os Repositórios do Azure, poderá ter de configurar uma credencial alternativa que não utilize carateres especiais (como o "@" num endereço de correio eletrónico). Para fazer isso, siga as instruções aqui.

Agora, a ramificação será permanentemente eliminada do servidor, e clones e sincronizações subsequentes por membros da equipe do projeto não baixarão os arquivos grandes que você estava tentando remover. Os usuários precisarão puxar para baixo do servidor para se certificar de que eles estão em sincronia com o novo estado de repositório do servidor.

Se os usuários tiverem confirmações mais recentes

Se outros usuários já se comprometeram com o repositório do servidor, você terá uma consideração adicional. Você deseja remover a ramificação que contém o(s) arquivo(s) grande(s), mas não deseja perder as alterações feitas pela equipe. Para resolver isto, ao abrir o editor como parte do rebase, observe cuidadosamente os commits. Certifique-se de que os commits que você deseja manter estão listados nas linhas 'pick'; Exclua os que você deseja remover, como onde um arquivo grande foi adicionado.

Observe que, após a rebaseagem, os outros usuários da equipe também precisarão rebasear para que todos tenham uma cópia consistente do repositório do servidor. Esta é uma dor para todos e normalmente deve ser evitada. Assim, se você precisar remover um push, como observado aqui, é importante coordenar com a equipe. Para obter detalhes completos sobre rebase, consulte a documentação oficial de rebase aqui.

A chave é certificar-se de que você sabe quais compromissos são desejados e indesejados. Estude o log do git ou o histórico em seu IDE (como o Visual Studio) e anote meticulosamente os hashes SHA a serem mantidos e os que devem ser lançados.

Em cenários em que o arquivo grande já existe há algum tempo e houve ramificações e mesclagens subsequentes, você poderá remover o arquivo usando a git filter-branch opção. Se você quiser experimentar, siga as instruções aqui.

Considerações sobre as melhores práticas

Ele economiza muito trabalho para garantir que arquivos grandes permaneçam fora do repositório principal em primeiro lugar. Com isso em mente, aqui estão algumas práticas recomendadas de bom senso para a equipe ter em mente:

Fazer

  • Confirme alterações com frequência. Você sempre pode corrigi-los mais tarde com um squash ou rebase.
  • Utilize ramificações para isolar as suas alterações. As filiais são baratas e privadas, e a fusão é simples. Você também pode fazer backup de alterações em uma ramificação enviando-a para o servidor.
  • Use uma convenção de nomenclatura ao publicar ramificações de tópicos. Nomeie a ramificação "users/<alias>/<branchname>". Isso ajudará a agrupar suas filiais e tornará mais fácil para outras pessoas identificarem o "proprietário".
  • Não se esqueça de enviar as suas alterações. Commit != Checkin. (Commit + Push) == Checkin.
  • Considere usar .gitignore para binários grandes para que eles não sejam adicionados ao repositório em primeiro lugar - mais informações aqui.
  • Considere usar o controle de versão NuGet ou TFS para armazenar seus binários grandes.

O que não fazer

  • Não faça rebase depois de ter feito push. Rebasear commits já enviados no git pode ser ruim porque força todos os outros no repositório a rebasear as suas mudanças locais - e eles não vão ficar satisfeitos se precisarem fazer isso. Rebasear compromissos empurrados em seu próprio ramo pessoal, mesmo que empurrado, não é um negócio significativo, a menos que outras pessoas estejam puxando esses compromissos.
  • Não carregue binários no seu repositório. O Git não compacta arquivos binários da mesma forma que o TFVC e, como todos os repositórios têm todo o histórico, a adição de arquivos binários significa um aumento permanente.

Resumo

Às vezes, elementos indesejáveis, como arquivos grandes, são adicionados a um repositório e precisam ser removidos para manter o repositório limpo e leve. Você pode fazer isso colocando o repositório local em ordem usando o git rebase comando e, em seguida, usando o git push --force comando para substituir o repositório do servidor pelo repositório local.

Autores: Edward Fry e Jesse Houwing | Conecte-se com os autores e ALM | DevOps Rangers aqui

(c) 2015 Microsoft Corporation. Todos os direitos reservados.ÿEste documento é fornecido "as-is." As informações e opiniões expressas neste documento, incluindo URL e outras referências a sites da Internet, podem ser alteradas sem aviso prévio. Você assume o risco de usá-lo.

Este documento não lhe fornece direitos legais sobre nenhuma propriedade intelectual em qualquer produto Microsoft. Poderá copiar e utilizar o presente documento para efeitos de referência pessoal a título interno.