Eliminar archivos confidenciales y sus confirmaciones del historial de Git


Me gustaría poner un proyecto Git en GitHub pero contiene ciertos archivos con datos confidenciales (nombres de usuario y contraseñas, como /config/deploy.rb para capistrano).

Sé que puedo agregar estos nombres de archivo a .gitignore, pero esto no eliminaría su historial dentro de Git.

Tampoco quiero volver a empezar borrando el /.directorio git.

¿Hay alguna forma de eliminar todos los rastros de un archivo en particular en tu historial de Git?

Author: Roberto Tyley, 2009-05-16

10 answers

Para todos los propósitos prácticos, el primero lo que debería preocuparle es CAMBIAR SUS CONTRASEÑAS! No está claro a partir de su pregunta si su repositorio git es completamente local o si ya tiene un repositorio remoto en otro lugar; si es remoto y no está protegido de otros, tiene un problema. Si alguien ha clonado ese repositorio antes de que arregles esto, tendrán una copia de tus contraseñas en su máquina local, y no hay manera de que puedas forzarlos a actualizar a su versión" fija " con él ido de la historia. La única cosa segura que puede hacer es cambiar su contraseña a otra cosa donde quiera que la haya usado.


Con eso fuera del camino, aquí está cómo arreglarlo. GitHub respondió exactamente esa pregunta como una FAQ :

Nota para usuarios de Windows: use comillas dobles ( " ) en lugar de simples en este comando

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

Tenga en cuenta que una vez que ha enviado este código a un repositorio remoto como GitHub y otros tienen clonado ese repositorio remoto, ahora estás en una situación en la que estás reescribiendo la historia. Cuando otros intenten bajar sus últimos cambios después de esto, recibirán un mensaje que indica que los cambios no se pueden aplicar porque no es un avance rápido.

Para arreglar esto, tendrán que eliminar su repositorio existente y volver a clonarlo, o seguir las instrucciones en "RECUPERANDO DE REBASE ASCENDENTE" en la página de manual git-rebase.


En el futuro, si accidentalmente confirme algunos cambios con información sensible, pero nota antes de enviar a un repositorio remoto, hay algunas correcciones más fáciles. Si la última confirmación es la que agrega la información confidencial, simplemente puede eliminar la información confidencial y luego ejecutar:

git commit -a --amend

Que modificará la confirmación anterior con cualquier cambio nuevo que hayas hecho, incluyendo la eliminación completa de archivos hecha con un git rm. Si los cambios están más atrás en la historia pero aún no se envían a un control remoto repositorio, puede hacer un rebase interactivo:

git rebase -i origin/master

Que abre un editor con las confirmaciones que ha realizado desde su último ancestro común con el repositorio remoto. Cambie " pick "a" edit " en cualquier línea que represente un commit con información confidencial, y guarde y salga. Git recorrerá los cambios y te dejará en un lugar donde puedas:

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

Para cada cambio con información sensible. Eventualmente, usted terminará de nuevo en su rama, y usted puede empujar con seguridad el nuevo cambio.

 370
Author: natacado,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-26 12:16:07

Cambiar sus contraseñas es una buena idea, pero para el proceso de eliminación de contraseñas del historial de su repositorio, recomiendo el BFG Repo-Cleaner, una alternativa más rápida y simple a git-filter-branch diseñada explícitamente para eliminar datos privados de los repositorios Git.

Cree un archivo private.txt que enumere las contraseñas, etc., que desea eliminar (una entrada por línea) y luego ejecute este comando:

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

Todos los archivos bajo un tamaño de umbral (1MB por defecto) en el historial de su repositorio serán escaneado, y cualquier cadena coincidente (que no esté en su última confirmación) será reemplazada por la cadena "***REMOVED***". Luego puede usar git gc para limpiar los datos muertos:

$ git gc --prune=now --aggressive

El BFG es típicamente 10-50x más rápido que ejecutar git-filter-branch y las opciones se simplifican y adaptan en torno a estos dos casos de uso comunes:

  • Eliminar Archivos grandes locos
  • Eliminando Contraseñas, Credenciales y otras Privadas datos

Revelación completa: Soy el autor del Repo-Cleaner de BFG.

 70
Author: Roberto Tyley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-11 06:41:03

Recomiendoeste guion de David Underhill, funcionó como un encanto para mí.

Agrega estos comandos además de la rama de filtro de natacado para limpiar el desorden que deja atrás:

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

Guión completo (todo crédito a 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

Los dos últimos comandos pueden funcionar mejor si se cambian a lo siguiente:

git reflog expire --expire=now --all && \
git gc --aggressive --prune=now
 16
Author: Jason Goemaat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-01-14 03:53:50

Si ya has empujado a GitHub, los datos se ven comprometidos incluso si los empujas un segundo más tarde porque:

Para probar esto, he creado un repo: https://github.com/cirosantilli/test-dangling y hecho:

git init
git remote add origin [email protected]: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

Si elimina el repositorio sin embargo, las confirmaciones desaparecen incluso de la API inmediatamente y dan 404, e. g.https://api.github.com/repos/cirosantilli/test-dangling-delete/commits/8c08448b5fbf0f891696819f3b2b2d653f7a3824 Esto funciona incluso si recreas otro repositorio con el mismo nombre.

Así que mi curso de acción recomendado es:

  • Cambie sus credenciales

  • Si eso no es suficiente (por ejemplo, fotos desnudas):

    • eliminar el repositorio
    • póngase en contacto con el soporte
 10
Author: Ciro Santilli 新疆改造中心 六四事件 法轮功,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-24 21:23:06

Para ser claros: La respuesta aceptada es correcta. Pruébalo primero. Sin embargo, puede ser innecesariamente complejo para algunos casos de uso, particularmente si encuentra errores desagradables como 'fatal: bad revision pr prune-empty', o realmente no le importa el historial de su repositorio.

Una alternativa sería:

  1. cd a la rama base del proyecto
  2. Elimine el código / archivo sensible
  3. rm-rf .git / # Eliminar toda la información de git de su código
  4. Vaya a github y elimine su repositorio
  5. Siga esta guía para enviar su código a un nuevo repositorio como lo haría normalmente - https://help.github.com/articles/adding-an-existing-project-to-github-using-the-command-line/

Esto, por supuesto, eliminará todas las ramas del historial de confirmaciones y los problemas tanto de tu repositorio de github como de tu repositorio de git local. Si esto es inaceptable, tendrá que utilizar un enfoque alternativo.

Llame a esto la opción nuclear.

 8
Author: lostphilosopher,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-01-25 23:38:51

Aquí está mi solución en windows

Git filter-branch tree tree-filter "rm-f' filedir / filename '" HEAD

Git push force force

Asegúrese de que la ruta es correcta de lo contrario no funcionará

Espero que ayude

 6
Author: vertigo71,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-02 19:19:31

Use filter-branch :

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
 5
Author: Shiv Krishna Jaiswal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-17 14:50:54

Puede usar git forget-blob.

El uso es bastante simple git forget-blob file-to-forget. Puede obtener más información aquí

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

Desaparecerá de todas las confirmaciones en tu historial, reflog, etiquetas, etc.

Me encuentro con el mismo problema de vez en cuando, y cada vez que tengo que volver a este post y otros, es por eso que automatizé el proceso.

Créditos a colaboradores de Stack Overflow que me permitieron armar esto

 4
Author: nachoparker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-23 07:41:12

He tenido que hacer esto un par de veces hasta la fecha. Tenga en cuenta que esto solo funciona en 1 archivo a la vez.

  1. Obtiene una lista de todas las confirmaciones que modificaron un archivo. El que está en la parte inferior será el primer commit:

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

  2. Para eliminar el archivo del historial use el primer commit sha1 y la ruta al archivo del comando anterior, y rellénelos en este comando:

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

 2
Author: b01,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-21 18:23:36

Entonces, se ve algo como esto:

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

Elimine la caché para el archivo rastreado de git y agregue ese archivo a la lista .gitignore

 1
Author: przbadu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-16 04:53:08