¿Cómo eliminar un archivo del historial de Git?

91

Hace algún tiempo agregué información (archivos) que deben ser privados. Eliminarlo del proyecto no es un problema, pero también necesito eliminarlo del githistorial.

Yo uso Git y Github (cuenta privada).

Nota: En este hilo se muestra algo similar, pero aquí hay un archivo antiguo que se agregó a una rama de características, esa rama se fusionó con una rama de desarrollo y finalmente se fusionó con la maestra, ya que se hicieron muchos cambios. Entonces no es lo mismo y lo que se necesita es cambiar el historial y ocultar esos archivos por privacidad.

Marcos R. Guevara
fuente
3
Tendrías que reescribir la historia. Por ejemplo, git rebaseentoncesgit push -f
Cory Kramer
El filter-branchmétodo descrito en el duplicado sugerido hará lo que desee.
1615903
También stackoverflow.com/a/17890278 que apunta al BFG que puede ser más rápido que usargit filter-branch
Hasturkun
pero vaya más rápido y haga lo mismo, y necesito usar java. Leí @Hasturkun
Marcos R. Guevara

Respuestas:

114

Encontré esta respuesta y me ayudó:

git filter-branch --index-filter "git rm -rf --cached --ignore-unmatch path_to_file" HEAD

Lo encontré aquí https://myopswork.com/how-remove-files-completely-from-git-repository-history-47ed3e0c4c35

Petro Franko
fuente
5
Advertencia: esto crea un montón de confirmaciones y provoca divergencias. Probablemente tengas que empujar a la fuerza después, pero estaba demasiado asustado.
sudo
1
Secundando lo que dijo @sudo, pero esto funcionó para mi nueva rama con la que me comprometí accidentalmente .env. Solución rápida y precisa.
Joe Scotto
1
De hecho, ¡un simple empuje de fuerza funciona! Yo también estaba asustado pero todo lo respaldaba.
wutBruh
1
También puede especificar un rango de confirmaciones como último argumento. Si la confirmación en cuestión fue reciente, haz<previous_hash>..HEAD y ahorre algo de tiempo.
Victor Sergienko
después de esto funciona solo para mí git push --force
Sebastian Schmal
48

Si ha confirmado recientemente ese archivo, o si ese archivo ha cambiado en una o dos confirmaciones, le sugiero que use rebasey cherrypickpara eliminar esa confirmación en particular.

De lo contrario, tendría que reescribir todo el historial.

git filter-branch --tree-filter 'rm -f <path_to_file>' HEAD

Cuando esté satisfecho con los cambios y se haya asegurado debidamente de que todo parece estar bien, debe actualizar todas las sucursales remotas:

git push origin --force --all

Nota: - Es una operación compleja y debe ser consciente de lo que está haciendo. Primero intente hacerlo en un repositorio de demostración para ver cómo funciona. También debe informar a otros desarrolladores, de modo que no realicen ningún cambio mientras tanto.

hspandher
fuente
después de reescribir todo el historial, para mantener los cambios en el repositorio (github), ¿qué se debe hacer?
Marcos R. Guevara
gracias, esperaré a hacerlo, y lo probaré con un repositorio de demostración, lo actualizaré con todo lo que se hizo aquí.
Marcos R. Guevara
Por error, olvidé agregar --all. Ahora dice todo actualizado cada vez que vuelvo a ejecutar push con ambos argumentos. Y el archivo no se elimina de otras ramas. ¿Qué debería hacer ahora?
Reeshabh Ranjan
¿Por qué su sugerencia usa en --tree-filterlugar de me --index-filtergusta en la respuesta de @ PetroFranko?
einpoklum
14
  • elimine el archivo y reescriba el historial de la confirmación que realizó con el archivo eliminado (esto creará un nuevo hash de confirmación desde el archivo que confirmó):

    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

  • ahora fuerza empujar el repositorio:

    git push origin --force --all

  • ahora dile a tus colaboradores que lo hagan rebase.

suhailvs
fuente
7
  • En primer lugar, agréguelo a su .gitignorearchivo y no olvide enviar el archivo :-)
  • Puede usar este sitio: http://gtiignore.io para generar el .gitignorepara usted y agregar la ruta requerida a sus archivos / carpetas binarios

  • Una vez que haya agregado el archivo .gitignore, puede eliminar el archivo binario "antiguo" con BFG.


How to remove big files from the repository

Puede utilizar git filter-brancho BFG. https://rtyley.github.io/bfg-repo-cleaner/

BFG Repo-Cleaner

una alternativa a git-filter-branch.

El BFG es una alternativa más simple y rápida a git-filter-branch para limpiar los datos incorrectos de su historial de repositorio de Git:

* Eliminación de archivos Crazy Big *
* Eliminación de contraseñas, credenciales y otros datos privados

Ejemplos (del sitio oficial)

En todos estos ejemplos, bfg es un alias de java -jar bfg.jar.

# Delete all files named 'id_rsa' or 'id_dsa' :
bfg --delete-files id_{dsa,rsa}  my-repo.git

ingrese la descripción de la imagen aquí

CodeWizard
fuente
6

Leí este artículo de GitHub , que me llevó al siguiente comando (similar a la respuesta aceptada, pero un poco más robusto):

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
pantalones-vancy
fuente
4

git-repo-filter

gitrecomienda usar git-filter-repo (cuando git filter-branchse ejecuta el comando). Hay una larga lista de por qué es mejor que cualquier otra alternativa ( https://github.com/newren/git-filter-repo#why-filter-repo-instead-of-other-alternatives ), mi experiencia es que es muy sencillo y muy rápido.

Este comando elimina el archivo de todas las confirmaciones en todas las ramas:

git filter-repo --path <path to the file or directory> --invert-paths

Se pueden especificar varias rutas utilizando varios --pathparámetros. Puede encontrar documentación detallada aquí: https://www.mankier.com/1/git-filter-repo

Tibor Takács
fuente