Git: ¿Cómo eliminar un archivo de una confirmación histórica?

113

Me he comprometido con la identificación 56f06019 (por ejemplo). En esa confirmación, accidentalmente cometí un archivo grande (50Mb). En otra confirmación agrego el mismo archivo pero en el tamaño correcto (pequeño). Ahora mi repositorio cuando clono es demasiado pesado :( ¿Cómo eliminar ese archivo grande del historial de repositorios para reducir el tamaño de mi repositorio?

marioosh
fuente
en mi caso, no es un archivo grande, sino un archivo de configuración que contiene créditos de la base de datos. Estaba estudiando git, en ese momento desconocía .gitignore.
Rashi
1
relacionado help.github.com/articles/…
Trevor Boyd Smith

Respuestas:

165

El capítulo 9 del libro Pro Git tiene una sección sobre la eliminación de objetos .

Permítanme describir brevemente los pasos aquí:

git filter-branch --index-filter \
    'git rm --cached --ignore-unmatch path/to/mylarge_50mb_file' \
    --tag-name-filter cat -- --all

Como la opción de rebase descrita anteriormente, filter-branches la operación de reescritura. Si tiene un historial publicado, tendrá que --forceimpulsar las nuevas referencias.

El filter-branchenfoque es considerablemente más poderoso que el rebaseenfoque, ya que

  • le permite trabajar en todas las ramas / referencias a la vez,
  • cambia el nombre de las etiquetas sobre la marcha
  • funciona limpiamente incluso si ha habido varias confirmaciones de fusión desde la adición del archivo
  • funciona limpiamente incluso si el archivo fue (re) agregado / eliminado varias veces en el historial de (una) rama (s)
  • no crea nuevas confirmaciones no relacionadas, sino que las copia mientras modifica los árboles asociados con ellas. Esto significa que se conservan cosas como confirmaciones firmadas, notas de confirmación, etc.

filter-branch también mantiene copias de seguridad, por lo que el tamaño del repositorio no disminuirá de inmediato a menos que expire los reflogs y la recolección de basura:

rm -Rf .git/refs/original       # careful
git gc --aggressive --prune=now # danger
sehe
fuente
1
Vale la pena señalar que esto no parece funcionar en Windows cmd.exe. Sin embargo, parece funcionar bien bajo cygwin.
Nombre falso
2
Conseguí que la rama de filtro de git anterior funcionara usando comillas dobles en lugar de comillas simples (en Windows Server 2012 cmd.exe)
JCii
1
Lo que funcionó para mí fue esta línea de comando de rama de filtro. git filter-branch --force --index-filter 'git rm --ignore-unmatch --cached PathTo/MyFile/ToRemove.dll' -- fbf28b005^.. Entonces rm --recursive --force .git/refs/originaly rm --recursive --force .git/logs luego utilicé git prune --expire now y git gc --aggressive Esto funcionó mejor para mí que los pasos exactos enumerados anteriormente. Gracias por incluir el enlace al libro de Git Pro, ya que fue invaluable.
dacke.geo
Después del comando filter-branch, la única forma en que podía bajar el tamaño de la carpeta .git era seguir el comando que se encuentra aquí: stackoverflow.com/questions/1904860/… git -c gc.reflogExpire = 0 -c gc. reflogExpireUnreachable = 0 -c gc.rerereresolved = 0 \ -c gc.rerereunresolved = 0 -c gc.pruneExpire = ahora gc "$ @"
Steve Ardis
Para reducir el repositorio, utilicé los comandos enumerados en git filter-branch doc: git-scm.com/docs/…
Ludovic Ronsin
0

Necesitará git rebase en el modo interactivo; vea un ejemplo aquí: ¿Cómo puedo eliminar una confirmación en GitHub? y cómo eliminar confirmaciones antiguas .

Si su confirmación está en HEAD menos 10 confirmaciones:

$ git rebase -i HEAD~10

Después de la edición de su historial, debe presionar el historial "nuevo", debe agregar el +to force (consulte la refspec en las opciones de inserción ):

$ git push origin +master

Si otras personas ya han clonado su repositorio, les informará, porque acaba de cambiar el historial.

Loïc d'Anterroches
fuente
3
Eso no elimina el archivo grande del historial. Además, la forma canónica de forzar el empuje es git push --forceo git push -f(que no requiere que las personas conozcan el objetivo de empuje de la rama)
consulte el
Según la pregunta, el nuevo archivo es exactamente el mismo que el antiguo, es decir, la misma ruta. Es por eso que no puede usar directamente git rmen la ruta.
Loïc d'Anterroches
2
@sehe, si haces una rebase eliminando la confirmación con el archivo enorme, se habrá ido para siempre.
vonbrand
@vonbrand solo de esa rama que rebasó. No estoy asumiendo que la rama 'desde' se elimine. Pero sí, si elimina una rama de árbol de revisión, que le ayudará a: _
sehe
@sehe, claro, tienes que perseguir todas las ramas que contienen el commit infractor. Si es antes de algunos problemas en el repositorio, tendrá que reorganizar mucho. Pero rebase es la herramienta para esto.
vonbrand
0

Intenté usar la siguiente respuesta en Windows https://stackoverflow.com/a/8741530/8461756

Las comillas simples no funcionan en Windows, necesita comillas dobles.

Seguir funcionó para mí.

git filter-branch --force --index-filter "git rm --cached --ignore-unmatch PathRelativeRepositoryRoot / bigfile.csv" - --todos

Después de eliminar el archivo grande, pude enviar mis cambios a github master.

Sandeep Dixit
fuente
0

Puede usar un comando simple para eliminar

 git rm -r -f app/unused.txt 
 git rm -r -f yourfilepath
mini desarrollador
fuente