Pergunta

Eu gostaria de colocar um projeto Git no Github, mas ele contém certos arquivos com dados confidenciais (nomes de usuário e senhas, como /config/deploy.rb para capistrano).

Eu sei que posso adicionar esses nomes de arquivos a .gitignore, mas isso não removeria sua história no Git.

Também não quero começar de novo, excluindo o diretório /.git.

Existe uma maneira de remover tudo traços de um arquivo específico no seu histórico Git?

Foi útil?

Solução

Para todos os propósitos práticos, o primeiro coisa com que você deve se preocupar é Alterando suas senhas! Não está claro em sua pergunta se o seu repositório Git é totalmente local ou se você ainda tem um repositório remoto em outro lugar; Se for remoto e não garantido de outras pessoas, você tem um problema. Se alguém clonou esse repositório antes de corrigir isso, terá uma cópia de suas senhas na máquina local e não há como forçá -las a atualizar para sua versão "fixada" com ela desaparecendo da história. A única coisa segura que você pode fazer é alterar sua senha para outra coisa em todos os lugares em que a usou.


Com isso fora do caminho, veja como consertá -lo. Github respondeu exatamente essa pergunta como uma FAQ:

Nota para usuários do Windows: Use citações duplas (") em vez de singles neste comando

git filter-branch --index-filter \
'git update-index --remove filename' <introduction-revision-sha1>..HEAD
git push --force --verbose --dry-run
git push --force

Lembre -se de que, depois de empurrar esse código para um repositório remoto como o Github e outros clonarem esse repositório remoto, agora você está em uma situação em que está reescrevendo o histórico. Quando outros tentam abaixar suas mudanças mais recentes depois disso, eles receberão uma mensagem indicando que as alterações não podem ser aplicadas porque não é uma avançada rápida.

Para consertar isso, eles terão que excluir seu repositório existente e recarregá-lo novamente, ou seguir as instruções em "recuperação de rebase a montante" no MANPAGE DE GIT-REBASE.


No futuro, se você acidentalmente comete algumas alterações com informações confidenciais, mas percebe antes da Empurrando para um repositório remoto, existem algumas correções mais fáceis. Se você se compromete a adicionar as informações confidenciais, basta remover as informações confidenciais e executar:

git commit -a --amend

Isso alterará o commit anterior com novas alterações que você fez, incluindo remoções de arquivos inteiras feitas com um git rm. Se as alterações estiverem mais adiante na história, mas ainda não forem empurradas para um repositório remoto, você poderá fazer uma rebase interativa:

git rebase -i origin/master

Isso abre um editor com os compromissos que você fez desde o seu último ancestral comum com o repositório remoto. Mudar "Escolha" para "Editar" em qualquer linha que represente um commit com informações confidenciais e salve e saia. Git passará pelas mudanças e o deixará em um local onde puder:

$EDITOR file-to-fix
git commit -a --amend
git rebase --continue

Para cada alteração com informações confidenciais. Eventualmente, você acabará de volta em sua filial e poderá pressionar com segurança as novas alterações.

Outras dicas

Alterar suas senhas é uma boa ideia, mas para o processo de remoção de senha da história do seu repo, recomendo o BFG Repo-Cleaner, uma alternativa mais rápida e simples a git-filter-branch Projetado explicitamente para remover dados privados de repositórios Git.

Crie um private.txt Listagem de arquivos As senhas, etc, que você deseja remover (uma entrada por linha) e, em seguida, execute este comando:

$ java -jar bfg.jar  --replace-text private.txt  my-repo.git

Todos os arquivos sob um tamanho limite (1 MB por padrão) na história do seu repo serão digitalizados e qualquer string correspondente (que não está no seu Mais recentes comprometimento) será substituído pela string "*** removido ***". Você pode então usar git gc Para limpar os dados mortos:

$ git gc --prune=now --aggressive

O BFG é tipicamente 10-50x mais rápido do que a execução git-filter-branch E as opções são simplificadas e adaptadas em torno desses dois casos de uso comuns:

  • Removendo Arquivos grandes loucos
  • Removendo Senhas, credenciais & outro Dados privados

Divulgação completa: sou o autor do BFG Repo-Cleaner.

Eu recomendo Este script Por David Underhill, trabalhou como um encanto para mim.

Ele adiciona esses comandos, além disso, o ramo de filtro de Natacado para limpar a bagunça que deixa para trás:

rm -rf .git/refs/original/
git reflog expire --all
git gc --aggressive --prune

Script completo (todo o crédito para David Underhill)

#!/bin/bash
set -o errexit

# Author: David Underhill
# Script to permanently delete files/folders from your git repository.  To use 
# it, cd to your repository's root and then run the script with a list of paths
# you want to delete, e.g., git-delete-history path1 path2

if [ $# -eq 0 ]; then
    exit 0
fi

# make sure we're at the root of git repo
if [ ! -d .git ]; then
    echo "Error: must run this script from the root of a git repository"
    exit 1
fi

# remove all paths passed as arguments from the history of the repo
files=$@
git filter-branch --index-filter \
"git rm -rf --cached --ignore-unmatch $files" HEAD

# remove the temporary history git-filter-branch
# otherwise leaves behind for a long time
rm -rf .git/refs/original/ && \
git reflog expire --all && \
git gc --aggressive --prune

Os dois últimos comandos podem funcionar melhor se alterados para o seguinte:

git reflog expire --expire=now --all && \
git gc --aggressive --prune=now

Se você pressionou para o Github, o empurrão de força não é suficiente, exclua o repositório ou o suporte de contato

Mesmo se você forçar o empurrão um segundo depois, isso não é suficiente como explicado abaixo.

Os únicos cursos de ação válidos são:

  • O que vazou é uma credencial mutável como uma senha?

    • Sim: modifique suas senhas imediatamente e considere usar mais chaves OAuth e API!
    • Não (fotos nuas):

      • Você se importa se todos os problemas do repositório são nucleosos?

        • Não: exclua o repositório
        • sim:

          • suporte de contato
          • Se o vazamento for muito crítico para você, a ponto de você estar disposto a obter algum tempo de inatividade do repositório para tornar menos provável que vaze, Torne -o privado Enquanto você espera o apoio do Github para responder a você

Força empurrar um segundo depois não é suficiente porque:

Se você excluir o repositório em vez de apenas forçar pressionando, no entanto, as confirmações desaparecem mesmo da API imediatamente e dão 404, por exemplo, https://api.github.com/repos/cirosantilli/test-dangling-delete/commits/8c08448b5fbf0f891696819f3b2b2d653f7a3824 Isso funciona mesmo se você recriar outro repositório com o mesmo nome.

Para testar isso, criei um repo: https://github.com/cirosantilli/test-dangling e fez:

git init
git remote add origin git@github.com:cirosantilli/test-dangling.git

touch a
git add .
git commit -m 0
git push

touch b
git add .
git commit -m 1
git push

touch c
git rm b
git add .
git commit --amend --no-edit
git push -f

Veja também: Como remover um compromisso pendurado do Github?

Para ficar claro: a resposta aceita está correta. Experimente primeiro. No entanto, pode ser desnecessariamente complexo para alguns casos de uso, principalmente se você encontrar erros desagradáveis, como 'Fatal: Bad Revisão-Presune-Deepy', ou realmente não se importa com a história do seu repo.

Uma alternativa seria:

  1. CD para o ramo base do projeto
  2. Remova o código / arquivo sensível
  3. rm -rf .git/ # remova todas as informações git do seu código
  4. Vá para o Github e exclua seu repositório
  5. Siga este guia para empurrar seu código para um novo repositório como normalmente faria -https://help.github.com/articles/adding-an-existing-project-to-github-using-the-command-line/

É claro que isso removerá todos os ramos históricos e os problemas do seu repositório do GitHub e do seu repositório local. Se isso for inaceitável, você precisará usar uma abordagem alternativa.

Chame isso de opção nuclear.

Aqui está minha solução no Windows

Filtro de Git-Branch-Tree-filter "rm -f 'filedir/filename'" cabeça

git push -force

Certifique -se de que o caminho esteja correto, caso contrário, não funcionará

Espero que ajude

Usar Filtro do ramo:

git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch *file_path_relative_to_git_repo*' --prune-empty --tag-name-filter cat -- --all

git push origin *branch_name* -f

You can use git forget-blob.

The usage is pretty simple git forget-blob file-to-forget. You can get more info here

https://ownyourbits.com/2017/01/18/completely-remove-a-file-from-a-git-repository-with-git-forget-blob/

It will disappear from all the commits in your history, reflog, tags and so on

I run into the same problem every now and then, and everytime I have to come back to this post and others, that's why I automated the process.

Credits to contributors from Stack Overflow that allowed me to put this together

I've had to do this a few times to-date. Note that this only works on 1 file at a time.

  1. Get a list of all commits that modified a file. The one at the bottom will the the first commit:

    git log --pretty=oneline --branches -- pathToFile

  2. To remove the file from history use the first commit sha1 and the path to file from the previous command, and fill them into this command:

    git filter-branch --index-filter 'git rm --cached --ignore-unmatch <path-to-file>' -- <sha1-where-the-file-was-first-added>..

So, It looks something like this:

git rm --cached /config/deploy.rb
echo /config/deploy.rb >> .gitignore

Remove cache for tracked file from git and add that file to .gitignore list

In my android project I had admob_keys.xml as separated xml file in app/src/main/res/values/ folder. To remove this sensitive file I used below script and worked perfectly.

git filter-branch --force --index-filter \
'git rm --cached --ignore-unmatch  app/src/main/res/values/admob_keys.xml' \
--prune-empty --tag-name-filter cat -- --all
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top