Compartilhar via


Remover um binário grande do histórico do Git para gerenciar o tamanho dos repositórios clonados

Azure DevOps Services | Servidor Azure DevOps | Azure DevOps Server 2022

O Git é um repositório de código-fonte distribuído popular (repositório) que permite que os usuários trabalhem com o repositório completo 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? Isso não é intuitivo e requer permissões elevadas. Esse requisito é esperado para algo que afeta cada usuário do repositório.

Como você pode reverter o repositório central com segurança?

Cenário de problema

Imagine que você cometa um arquivo grande, como um vídeo, no servidor do Git. Em um sistema de código-fonte tradicional, é conveniente armazenar tudo em um só lugar e, em seguida, baixar o que você precisa. Com o Git, todo o repositório é clonado no computador local de cada usuário. Com um arquivo grande, cada usuário do projeto também deve baixar os arquivos grandes.

A cada arquivo grande subsequente comprometido no servidor, o problema só aumenta. O repositório se torna muito grande para ser eficiente para seus usuários. Mesmo se você remover o arquivo grande do repositório local e se comprometer novamente, o arquivo ainda existirá no histórico do repositório. Como resultado, o arquivo ainda é baixado para o computador local de cada pessoa como parte do histórico.

Captura de tela que mostra a caixa de diálogo de Alterações do Team Explorer com um vídeo grande nas alterações incluídas.

Adicione um arquivo grande ao repositório local.

Captura de tela que mostra o servidor e os repositórios locais, ambos com uma cópia dos arquivos de vídeo grandes.

Após você fazer o commit no repositório local, o servidor também tem o arquivo grande.

Congelar o repositório

Para corrigir o problema de um repositório grande, você deve começar na origem. Nesse cenário, a origem é o repositório do servidor. Peça à equipe para parar de fazer push para o repositório. Se mais pushes ocorrerem durante esse processo, você deverá contabilizá-los para que não perca nenhum dado.

Importante

As etapas a seguir removem o vídeo do histórico do branch, mas o arquivo permanece no histórico do repositório quando você clona seu repositório do Azure Repos. Remover os arquivos do histórico do branch impede que os arquivos sejam atualizados, o que criou outra versão do arquivo grande em seu repositório.

Saiba mais sobre como gerenciar arquivos grandes no Git. Para obter uma explicação e solução alternativa para esse comportamento quando você usa repositórios Git do Azure Repos, veja Por que a clonagem do Visual Studio Team Services retorna objetos antigos não referenciados?.

Troca de base e push forçado

Se ninguém mais na equipe fez alterações no repositório, que geralmente ocorrem por meio de um push, você pode seguir o caminho fácil. Você essencialmente faz seu repositório local parecer da maneira que você deseja que ele fique (ou seja, sem o arquivo grande). Em seguida, você envia suas alterações ao servidor.

Talvez seja necessário clonar ou corrigir seu repositório local antes de começar esse trabalho. Esse processo pode resultar em perda de trabalho ou alterações, portanto, prossiga com cautela.

Por padrão, você pode modificar arquivos de projeto locais e enviar alterações por push para o servidor, mas não pode executar operações no nível do servidor, como exclusão ou rebasing. Para continuar, é necessário um force push (recomendado) ou permissões de administrador no repositório. Entre em contato com o administrador do projeto para solicitar essas permissões ou peça a alguém que já tenha ajuda. Para obter mais informações, consulte Definir permissões de repositório Git.

Captura de tela que mostra o prompt de comando: git push --force permissions.

Em seguida, você precisa basear novamente o repositório.

  1. Use git log para encontrar os valores de hash SHA (algoritmo de hash seguro) das confirmações mais recentes. Você precisará dessas informações em breve porque precisa saber o commit bom mais recente. Você pode obter essas informações abrindo um prompt de comando do Git e inserindo:

    git log

    Como alternativa, você pode obter o hash SHA exibindo o histórico do branch no Visual Studio Team Explorer.

    Captura de tela que mostra a opção Visualizar Histórico do branch principal.

  2. Abra um prompt de comando do Git.

    Captura de tela que mostra a ação Abrir Prompt de Comando na caixa de diálogo Sincronização.

  3. Localize o número de hash SHA de interesse.

    Captura de tela que mostra o prompt de comando para a confirmação de vídeo.

    Você precisa do SHA que começa 25b4.

    Lembre-se de que o Git usa ponteiros para determinar em qual ponto do repositório o HEAD ou o branch atual está localizado. O estado do repositório no qual você está interessado está localizado em algum momento no passado.

  4. Para voltar no tempo e tornar o estado anterior o novo estado atual, use o git rebase comando:

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

    Captura de tela que mostra o uso da rebase para remover o arquivo de vídeo.

    A chave -i proporciona segurança extra porque traz o histórico em um editor. (Este artigo usa uma implementação do Git que apresenta o editor vi clássico na linha de comando no Windows. Você pode se lembrar se trabalhou com um sistema baseado em Unix.)

  5. Para este exemplo, você insere:

    git rebase -i 25b4

  6. Depois que o editor aparecer, remova todas as pick linhas, exceto a ramificação que você deseja manter como sua nova cabeça. Quando tudo parecer correto, em vi, digite :w\<enter\> para salvar ou entre !q\<enter\> para sair sem salvar.

    Captura de tela que mostra o prompt de comando - git rebase -i 25b4 pick command.

    Altere as linhas que você não deseja mais.

    Captura de tela que mostra o prompt de comando - git rebase -i 25b4 descartar.

  7. Altere pick para drop conforme mostrado. Em seguida, insira :w (in vi) para salvar e insira :q! para iniciar a rebase.

    Agora, insira git log novamente. O branch problemático deve estar ausente do log. Se estiver, você estará pronto para a etapa final, que exige permissões de administrador do projeto:

    git log

    Captura de tela que mostra os repositórios locais e de servidor após a rebase.

    A commit do vídeo grande agora foi removida do repositório local.

  8. Insira o seguinte comando:

    git push --force

    Captura de tela que mostra o prompt de comando – git push --force.

    Captura de tela que mostra o resultado do comando de prompt - git push --force.

    Esse comando força o repositório a sobrescrever o repositório no servidor.

    Use este comando com cuidado porque você pode facilmente perder dados no servidor.

    Captura de tela que mostra um push forçado mostrando o conteúdo a ser mantido, sem o arquivo de vídeo grande.

Você deve autenticar no servidor para que essa ação funcione.

Se você estiver usando o Azure Repos, talvez seja necessário configurar uma credencial alternativa que não use caracteres especiais. Um exemplo é o símbolo em (@) em um endereço de email. Para fazer essa tarefa, siga as instruções em Autenticação com o Azure Repos.

Agora o branch foi permanentemente removido do servidor. Clones e sincronizações subsequentes feitas por membros da equipe do projeto não baixarão os arquivos grandes que você estava tentando remover. Os usuários precisam efetuar pull do servidor para verificar se estão em sincronia com o novo estado do repositório do servidor.

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

Se outros usuários enviarem confirmações por push para o repositório do servidor, você terá outra consideração. Você deseja remover o branch que contém os arquivos grandes, mas não deseja perder as alterações feitas pela equipe. Para resolver essa situação, ao abrir o editor como parte do rebasing, examine cuidadosamente os commits. Verifique se os commits que você deseja reter estão listados nas pick linhas. Exclua os que você deseja remover, como o local em que um arquivo grande foi adicionado.

Depois de fazer o rebasing, os outros usuários da equipe também precisam fazer o rebasing para que todos tenham uma cópia consistente do repositório do servidor. Este trabalho é entediante para todos, e você quer evitá-lo. Se você precisar remover um push, precisará coordenar com a equipe. Para obter mais informações sobre o rebasing, consulte o branching do Git – Rebasing.

A chave é garantir que você saiba as confirmações desejadas e as confirmações que não deseja. Estude o git log ou o histórico em seu ambiente de desenvolvimento integrado (como o Visual Studio). Anote meticulosamente os hashes SHA que devem ser mantidos e os hashes que devem ser removidos.

Em cenários em que o arquivo grande é antigo e houve ramificações e mesclagens subsequentes, você pode remover o arquivo usando a opção git filter-branch . Para obter mais informações, consulte Removendo dados confidenciais de um repositório.

Considerações sobre práticas recomendadas

Certifique-se de que arquivos grandes fiquem fora do repositório principal para salvar os membros da equipe do trabalho extra. Aqui estão algumas práticas recomendadas de senso comum para a equipe ter em mente.

Coisas para fazer

  • Confirme as alterações com frequência. Você sempre pode corrigi-los mais tarde com um squash ou rebase.
  • Utilize branches para isolar suas alterações. As filiais são baratas e privadas, e a mesclagem é simples. Você também pode fazer backup de alterações em um branch enviando-as por push para o servidor.
  • Use uma convenção de nomenclatura ao publicar ramificações de tópicos. Nomeie a ramificação users/<alias>/<branchname>. Esse nome ajuda a agrupar seus branches e facilita para que outras pessoas identifiquem o dono.
  • Lembre-se de enviar suas alterações por push. Use Commit != Checkin e (Commit + Push) == Checkin.
  • Considere usar .gitignore para binários grandes para que eles não sejam adicionados ao repositório. Para obter mais informações, consulte Ignorando arquivos.
  • Considere usar o controle de versão do NuGet ou do Team Foundation Server para armazenar seus binários grandes.

Coisas a serem evitadas

  • Não faça rebase depois de realizar o push. Rebase de confirmações já enviadas no Git pode ser ruim porque força todos os outros no repositório a fazer rebase de suas alterações locais. Os membros da equipe podem não ficar felizes se precisarem fazer essa tarefa. Rebasing confirmações enviadas por push em seu próprio branch pessoal, mesmo que enviadas por push, não é um problema, a menos que outras pessoas estejam puxando essas confirmações.
  • Não faça commit de binários em seu repositório. O Git não compacta arquivos binários da maneira que o Controle de Versão do Team Foundation faz. Como todos os repositórios têm todo o histórico, realizar o commit de arquivos binários significa inchaço permanente.

Resumo

Às vezes, elementos indesejáveis, como arquivos grandes, são adicionados a um repositório e devem ser removidos para manter o repositório limpo e leve. Você pode fazer essa tarefa colocando seu repositório local em ordem. Use o git rebase comando e use o git push --force comando para substituir o repositório do servidor com seu repositório local.