Versão do artigo: Enterprise Server 2.17
Remover dados confidenciais do repositório
Se você fizer commit de dados confidenciais, como uma senha ou chave SSH em um repositório Git, poderá removê-los do histórico. Para remover completamente os arquivos não desejados do histórico do repositório, use o comando "git filter-branch" ou a ferramenta de código aberto BFG Repo-Cleaner.
O comando git filter-branch
e o BFG Repo-Cleaner regravam o histórico do repositório, o que altera os SHAs dos commits existentes que você altera e quaisquer commits dependentes. Os SHAs do commit alterados podem afetar as pull requests abertas no repositório. Recomendamos que você faça merge ou feche todas todas as pull requests abertas antes de remover os arquivos do repositório.
Você pode remover o arquivo com o commit mais recente com git rm
. Para obter mais informações sobre como remover um arquivo que foi adicionado com o commit mais recente, consulte "Remover arquivos do histórico do repositório".
Aviso: depois de fazer push de um commit para o GitHub Enterprise, considere todos os dados do commit como comprometidos. Se tiver feito o commit de uma senha, altere-a! Se tiver feito commit de uma chave, crie outra.
Este artigo explica como fazer commits com dados confidenciais que não podem ser acessados de nenhum branch ou tag no repositório do GitHub Enterprise. No entanto, é importante destacar que esses commits talvez ainda possam ser acessados em clones ou bifurcações do repositório diretamente por meio de hashes SHA-1 em visualizações em cache no GitHub Enterprise e por meio de qualquer pull request que faça referência a eles. Você não pode fazer nada em relação aos clones e às bifurcações do repositório, mas você pode remover permanentemente as visualizações em cache e as referências aos dados confidenciais em pull requests no GitHub Enterprise entrando em contato com o seu administrador do site do GitHub Enterprise.
Remover um arquivo do histórico do repositório
Usar o BFG
O BFG Repo-Cleaner é uma ferramenta desenvolvida e mantida pela comunidade de código aberto. Ele fornece uma alternativa mais rápida e simples ao git filter-branch
para remover dados não desejados. Por exemplo: para remover o arquivo com dados confidenciais sem alterar o commit mais recente, execute:
$ bfg --delete-files YOUR-FILE-WITH-SENSITIVE-DATA
Para substituir todo o texto relacionado no passwords.txt
sempre que ele for encontrado no histórico do repositório, execute:
$ bfg --replace-text passwords.txt
Consulte as instruções completas de download e uso na documentação do BFG Repo-Cleaner.
Usar o filter-branch
Aviso: se você executar o código git filter-branch
depois de fazer stash das alterações, não conseguirá recuperar as alterações com outros comandos de stash. Antes de executar git filter-branch
, recomendamos que você desfaça o stash de quaisquer alterações feitas. Para desfazer o stash do último conjunto de alterações no qual você fez stash, execute git stash show -p | git apply -R
. Para obter mais informações, consulte Ferramentas do Git - Fazendo Stash.
Para demonstrar como o git filter-branch
funciona, mostraremos como remover o arquivo com dados confidenciais do histórico do repositório e adicioná-lo ao .gitignore
para impedir a repetição acidental do commit.
-
Se você ainda não tiver uma cópia local do repositório com dados confidenciais no histórico, faça um clone do repositório no computador local.
$ git clone https://hostname/YOUR-USERNAME/YOUR-REPOSITORY > Initialized empty Git repository in /Users/YOUR-FILE-PATH/YOUR-REPOSITORY/.git/ > remote: Counting objects: 1301, done. > remote: Compressing objects: 100% (769/769), done. > remote: Total 1301 (delta 724), reused 910 (delta 522) > Receiving objects: 100% (1301/1301), 164.39 KiB, done. > Resolving deltas: 100% (724/724), done.
-
Acesse o diretório de trabalho do repositório.
$ cd YOUR-REPOSITORY
-
Execute o seguinte comando substituindo
PATH-TO-YOUR-FILE-WITH-SENSITIVE-DATA
pelo caminho do arquivo que deseja remover, não apenas o nome do arquivo. Esses argumentos vão:- Forçar o Git a processar, mas não fazer checkout, do histórico completo de cada branch e tag
- Remover o arquivo especificado, bem como qualquer commit vazio gerado como resultado
- Sobrescrever as tags existentes
$ git filter-branch --force --index-filter \ "git rm --cached --ignore-unmatch PATH-TO-YOUR-FILE-WITH-SENSITIVE-DATA" \ --prune-empty --tag-name-filter cat -- --all > Rewrite 48dc599c80e20527ed902928085e7861e6b3cbe6 (266/266) > Ref 'refs/heads/master' was rewritten
Observação: se o arquivo com dados confidenciais existir em qualquer outro caminho (porque foi movido ou renomeado), execute esse comando nesses caminhos também.
-
Adicione o arquivo com dados confidenciais ao
.gitignore
para impedir a repetição acidental do commit.$ echo "YOUR-FILE-WITH-SENSITIVE-DATA" >> .gitignore $ git add .gitignore $ git commit -m "Add YOUR-FILE-WITH-SENSITIVE-DATA to .gitignore" > [master 051452f] Add YOUR-FILE-WITH-SENSITIVE-DATA to .gitignore > 1 files changed, 1 insertions(+), 0 deletions(-)
-
Verifique se você removeu todo o conteúdo desejado do histórico do repositório e fez checkout de todos os branches.
-
Quando estiver satisfeito com o estado do repositório, force o push das alterações locais para sobrescrever o repositório do GitHub Enterprise e todos os branches presentes no push:
$ git push origin --force --all > Counting objects: 1074, done. > Delta compression using 2 threads. > Compressing objects: 100% (677/677), done. > Writing objects: 100% (1058/1058), 148.85 KiB, done. > Total 1058 (delta 590), reused 602 (delta 378) > To https://hostname/YOUR-USERNAME/YOUR-REPOSITORY.git > + 48dc599...051452f master -> master (forced update)
-
Para remover o arquivo com dados confidenciais das versões com tag, você também precisará forçar o push das tags do Git:
$ git push origin --force --tags > Counting objects: 321, done. > Delta compression using up to 8 threads. > Compressing objects: 100% (166/166), done. > Writing objects: 100% (321/321), 331.74 KiB | 0 bytes/s, done. > Total 321 (delta 124), reused 269 (delta 108) > To https://hostname/YOUR-USERNAME/YOUR-REPOSITORY.git > + 48dc599...051452f master -> master (forced update)
-
Entre em contato com o seu administrador do site do GitHub Enterprise e solicite a remoção das visualizações em cache e das referências aos dados confidenciais em pull requests no GitHub Enterprise.
-
Peça para os colaboradores fazerem rebase, e não merge, nos branches criados a partir do histórico antigo do repositório. Um commit de merge poderia reintroduzir o histórico antigo completo (ou parte dele) que você acabou de se dar ao trabalho de corrigir.
-
Depois de algum tempo e de verificar que o
git filter-branch
não teve nenhum efeito colateral indesejado, você poderá forçar a remoção de todas as referências e a coleta como lixo de todos os objetos do repositório local com os seguintes comandos (usando o Git 1.8.5 ou mais recente):$ git for-each-ref --format="delete %(refname)" refs/original | git update-ref --stdin $ git reflog expire --expire=now --all $ git gc --prune=now > Counting objects: 2437, done. > Delta compression using up to 4 threads. > Compressing objects: 100% (1378/1378), done. > Writing objects: 100% (2437/2437), done. > Total 2437 (delta 1461), reused 1802 (delta 1048)
Observação: você também pode conseguir isso fazendo push do histórico filtrado em um repositório novo ou vazio e, em seguida, criando um clone usando o GitHub Enterprise.
Evitar commits acidentais no futuro
Há alguns truques simples para evitar fazer commit de coisas não desejadas:
- Use um programa visual, como o GitHub Desktop e o gitk, para fazer commit das alterações. Nos programas visuais, geralmente é mais fácil ver exatamente quais arquivos serão adicionados, excluídos e modificados em cada commit.
- Evite os comandos catch-all
git add .
egit commit -a
na linha de comando— usegit add filename
egit rm filename
para fazer stage de arquivos individuais. - Use o
git add --interactive
para revisar e fazer stage das alterações em cada arquivo de forma individual. - Use o
git diff --cached
para revisar as alterações que você incluiu no stage para commit. Esse é o diff exato que ogit commit
produzirá, contanto que você não use o sinalizador-a
.