No se puede enviar a GitHub debido a un archivo grande que ya eliminé

272

Actualmente tengo

  1. Repo de GitHub vacío
  2. Repositorio del servidor SSH (principal)
  3. Repo local

El repositorio del servidor SSH fue el repositorio (sitio de producción) más actualizado, así que hice un clon de Git desde allí hasta el local. Luego intenté hacerle un git pusha GitHub.

Todo salió bien, pero luego dijo algo sobre filename.gz que era demasiado grande para GitHub. No necesitaba este archivo, así que ejecuté varios comandos de Git para eliminarlo de la caché de Git y luego lo devolví al servidor SSH.

No veo el archivo grande localmente, pero todavía está en el servidor SSH aunque git diffno devuelve nada y git push devuelve "Todo está actualizado" - Y aunque el archivo no es visible en el repositorio local cuando intento presionar para GitHub todavía recibo un error al respecto

remoto: error: el archivo fpss.tar.gz tiene 135.17 MB; esto excede el límite de tamaño de archivo de GitHub de 100 MB

Seguí los pasos en "solucionar el problema" que figuran en la ayuda de GitHub, ¿no debería haber sido suficiente?

¿Cómo está el archivo todavía en el éter cuando no es local o aparece en estado git / diff / push?

Kevin W.
fuente
2
El archivo todavía está allí en la historia. Debe destruir el historial, posiblemente aplastando las confirmaciones que agregaron y eliminaron el archivo.
Shahbaz
@Shahbaz Seguí los pasos bajo "solucionar el problema" que figuran en este sitio ... ¿no debería haber sido suficiente? help.github.com/articles/working-with-large-files
Kevin W.
El comando allí es más avanzado que mi conocimiento de git, por lo que realmente no puedo decirlo. De todos modos, si git log -- the_big_filete devuelve algo, entonces el archivo todavía está en el historial.
Shahbaz
@Shahbaz que no devuelve nada> <
Kevin W.
¿Podría ser que también está presionando otras ramas donde existe el archivo? Además, si el archivo todavía está en el servidor, ¿por qué git pushdiría que todo está actualizado? Dado que cambió la historia, debería haberse quejado de que el impulso no es posible y que tendría que forzarlo.
Shahbaz

Respuestas:

446

Puedes usar

git filter-branch --index-filter 'git rm -r --cached --ignore-unmatch <file/dir>' HEAD

Esto eliminará todo en el historial de ese archivo. El problema es que el archivo está presente en el historial.

Este comando cambia los valores hash de tus commits, lo que puede ser un problema real, especialmente en repositorios compartidos. No debe realizarse sin comprender las consecuencias.

MacGyver
fuente
23
Funcionó para mí, pero tuve que 'forzarlo': git filter-branch --index-filter 'git rm -r --cached --ignore-unmatch <file / dir>' -f HEAD
alexoviedo999
30
Este comando cambia los valores hash de tus commits, lo que puede ser un problema real, especialmente en repositorios compartidos. No debe realizarse sin comprender las consecuencias.
Chris
66
¿Se supone que debe reemplazar <archivo / directorio> con el nombre del archivo o directorio que está causando el problema?
David Rhoden
12
Tenga en cuenta que si desea aplicar estos cambios a TODAS las ramas, debe usar una --allbandera en lugar deHEAD
Nick Spreitzer
9
Estoy obteniendo:Rewrite 657560fa18c030bcfac9132ce1c3541e84a5bc2c (1/10) (0 seconds passed, remaining 0 predicted) /usr/lib/git-core/git-filter-branch: 1: eval: Syntax error: end of file unexpected
João Abrantes
69

Encontré el aplastamiento más útil que filter-branch. Hice lo siguiente:

  1. Eliminar localmente archivos grandes.
  2. Cometer los borrados locales.
  3. Número de vuelta X restablecimiento parcial de confirmaciones (para mí fue 3): git reset --soft HEAD~3.
  4. Luego, vuelva a comprometer todos los cambios juntos (también conocido como squash) git commit -m "New message for the combined commit"
  5. Empuje aplastado cometer.

Caso especial (del usuario @lituo): si lo anterior no funciona, entonces puede tener este caso. Commit 1 incluyó el archivo grande y la inserción de Commit 1 falló debido a un error de archivo grande. Commit 2 eliminó el archivo grandegit rm --cached [file_name]pero el envío de Commit 2 todavía falló. Puede seguir los mismos pasos anteriores, pero en lugar de usarHEAD~3, useHEAD~2.

Pero no soy una clase de envoltura
fuente
2
Funcionó para mí, solo tuve que volver a fusionar los cambios de los tres commits nuevamente en mi repositorio local antes de que funcionara el squash push.
dasWesen
55
Esto es MUCHO mejor que la respuesta principal. La respuesta principal arruina todo tu historial de confirmaciones.
manic.coder
No solucionó mi problema
Hirak Sarkar
3
Esta es, de lejos, la única respuesta que corrige archivos grandes no comprometidos o comprometidos, ¡sin destruir completamente el repositorio! Votado para que pueda moverse a la cima :-)
Ælex
1
@ pero no soy una clase de contenedor: ¡muchas gracias! esto funcionó a las mil maravillas :)
mil maravillas POOJA GUPTA
64

Aquí hay algo que encontré súper útil si ya has estado jugando con tu repositorio antes de pedir ayuda. Primer tipo:

git status

Después de esto, debería ver algo en la línea de

On branch master
Your branch is ahead of 'origin/master' by 2 commits.
  (use "git push" to publish your local commits)

nothing to commit, working tree clean

¡La parte importante son los "2 commits"! Desde aquí, adelante y escriba:

git reset HEAD~<HOWEVER MANY COMMITS YOU WERE BEHIND>

Entonces, para el ejemplo anterior, uno escribiría:

git reset HEAD~2

Después de escribir eso, su "estado de git" debería decir:

On branch master
Your branch is up to date with 'origin/master'.

nothing to commit, working tree clean

Desde allí, puede eliminar el archivo grande (suponiendo que aún no lo haya hecho), y debería poder volver a confirmar todo sin perder su trabajo.
Sé que esta no es una respuesta súper elegante, ¡pero espero que ayude!

Shreya
fuente
11
Ganador. Solución simple, limpia, efectiva, construida con git. El amor responde así.
Reece Daniels
3
Esta es la mejor solución que existe.
wrahool
40

Si el archivo se agregó con su confirmación más reciente y no se ha insertado en el repositorio remoto , puede eliminar el archivo y modificar la confirmación, tomada desde aquí :

git rm --cached giant_file
    # Stage "giant_file" for removal with "git rm"
    # Leave it on disk with "--cached". if you want to remove it from disk
    # then ignore the "--cached" parameter
git commit --amend -CHEAD
    # Commit the current tree without the giant file using "git commit"
    # Amend the previous commit with your change "--amend" 
    # (simply making a new commit won't work, as you need
    # to remove the file from the unpushed history as well)
    # Use the log/authorship/timestamp of the last commit (the one we are
    # amending) with "-CHEAD", equivalent to --reuse-message=HEAD
git push
    # Push our rewritten, smaller commit with "git push"
BlueMoon93
fuente
1
Esta solución no funcionará ya que el archivo ya no está en el índice git (resulta como una untrackedlista de archivos en git status.
loretoparisi
No pasa nada Después de aplicar esto, redujo el número total de archivos, pero después de mostrar el proceso en un 99%, se atascó nuevamente. ¿Alguna sugerencia de lo que me estoy perdiendo?
Código de
44
¿Qué significa -CHEAD?
Aerin
1
¿Qué sucede si quiero probar esto desde una confirmación específica, no desde la última confirmación? Lo intenté git rm --cached giant_file commit_idpero no funcionó :(
puifais
@puifais Volvería a la confirmación anterior, seguiría estos pasos y luego me fusionaría con la actual. No estoy seguro de si este es el mejor enfoque, no soy un experto en Git
BlueMoon93
13

Tuve un problema similar y utilicé el paso anterior para eliminar el archivo. Funcionó perfectamente.

Luego recibí un error en un segundo archivo que necesitaba eliminar: remote: error: File <path/filename> is 109.99 MB; this exceeds GitHub's file size limit of 100.00 MB

Intenté el mismo paso, obtuve un error: "A previous backup already exists in <path/filename>"

De la investigación en este sitio web utilicé el comando:git filter-branch --force --index-filter "git rm --cached --ignore-unmatch <path/filename>" --prune-empty --tag-name-filter cat -- --all

Funcionó muy bien y se eliminaron los archivos grandes.

Increíblemente, el impulso aún falló con otro error: error: RPC failed; curl 56 OpenSSL SSL_read: SSL_ERROR_SYSCALL, errno 104 fatal: The remote end hung up unexpectedly

Esto lo solucioné modificando directamente el archivo de configuración .git: postBuffer = 999999999

Después de eso, ¡el empuje se hizo realidad!

Andre Odendaal
fuente
1
un problema adicional que tuve que lidiar con la eliminación de un archivo grande (como arriba) fue que una de las carpetas tenía un carácter hash #. Esto causó ningún problema en absoluto para el funcionamiento normal git sin embargo, para la git rmque necesitaba para dar el nombre completo de la ruta del repositorio para el archivo y para escapar de la # con una barra invertida para conseguir que el trabajo
jacanterbury
Esto funcionó para mí también. Evité el reset hardpaso al final de la página con un simple empujón. czettner.com/2015/07/16/…
Monte Hayward
Esto funcionó después de ejecutar también 'git push -f origin'
kezzos
12

¿Por qué GitHub rechaza mi repositorio, incluso después de eliminar el archivo grande?

Git almacena el historial completo de su proyecto, por lo que incluso si 'elimina' un archivo de su proyecto, el repositorio de Git todavía tiene una copia del archivo en su historial, y si intenta pasar a otro repositorio (como uno alojado en GitHub) entonces Git requiere el repositorio remoto tenga el mismo historial que su repositorio local (es decir, los mismos archivos grandes en su historial).

¿Cómo puedo hacer que GitHub acepte mi repositorio?

Debe limpiar el historial de Git de su proyecto localmente, eliminar los archivos grandes no deseados de todo el historial, y luego usar solo el historial 'limpiado' en el futuro. Los ID de confirmación de Git de las confirmaciones afectadas cambiarán.

¿Cómo limpio archivos grandes de mi repositorio de Git?

La mejor herramienta para limpiar archivos grandes no deseados del historial de Git es el BFG Repo-Cleaner : es una alternativa más simple y rápida agit-filter-branch diseñada específicamente para eliminar archivos no deseados del historial de Git.

Siga cuidadosamente las instrucciones de uso , la parte central es solo esto:

$ java -jar bfg.jar --strip-blobs-bigger-than 100M my-repo.git

Cualquier archivo de más de 100 MB de tamaño (que no esté en su última confirmación) se eliminará del historial de su repositorio de Git. Luego puede usar git gcpara limpiar los datos muertos:

$ git gc --prune=now --aggressive

El BFG suele ser al menos 10-50x más rápido que el funcionamiento git-filter-branch, y generalmente es mucho más fácil de usar.

Divulgación completa: soy el autor del BFG Repo-Cleaner.

Roberto Tyley
fuente
1
Mi caso tuvo complicaciones adicionales que impidieron el aplastamiento. La herramienta BFG funcionó muy bien. Gracias.
dantopa
Esta es una solución fenomenal
SexualPotatoes
5

He probado todos los métodos anteriores, pero ninguno de ellos funciona para mí.

Entonces se me ocurrió mi propia solución.

  1. En primer lugar, necesita un repositorio local limpio y actualizado. Eliminar todos los archivos grandes de mierda.

  2. Ahora cree una nueva carpeta FUERA de su carpeta de repositorio y use "Git create repository here" para convertirlo en un nuevo repositorio de Git, llamémoslo new_local_repo. ¡Eso es todo! Todos los métodos anteriores dicen que tienes que limpiar el historial ..., bueno, estoy harto de eso, ¡creemos un nuevo repositorio que no tenga ningún historial!

  3. Copie los archivos de su antiguo y jodido repositorio local al nuevo y hermoso repositorio. Tenga en cuenta que el logotipo verde en el icono de la carpeta desaparecerá, ¡esto es prometedor porque este es un nuevo repositorio!

  4. Comprometerse con la sucursal local y luego empujar a la nueva sucursal remota. Llamémoslo new_remote_branch. Si no sabe cómo presionar desde un nuevo repositorio local, búsquelo en Google.

  5. Felicidades! Has enviado tu código limpio y actualizado a GitHub. Si ya no necesita la rama maestra remota, puede hacer su new_remote_branch como nueva rama maestra. Si no sabes cómo hacerlo, búscalo en Google.

  6. Último paso, es hora de eliminar el viejo repositorio local jodido. En el futuro solo usará new_local_repo.

Shuaibin Chang
fuente
4

Tengo el mismo problema y ninguna de las respuestas me funciona. Resolví los siguientes pasos:

1. Encuentra qué commit (s) contiene el archivo grande

git log --all -- 'large_file`

La confirmación inferior es la confirmación más antigua en la lista de resultados.

2. Encuentra el que está justo antes del más antiguo.

git log

Supongamos que tienes:

commit 3f7dd04a6e6dbdf1fff92df1f6344a06119d5d32

3. Git rebase

git rebase -i 3f7dd04a6e6dbdf1fff92df1f6344a06119d5d32

Consejos :

  1. Elemento de la lista
  2. Solo elijo dropque los commits contengan el archivo grande.
  3. Puede encontrar conflictos durante el rebase, solucionarlos y usar git rebase --continuepara continuar hasta que lo termine.
  4. Si algo salió mal durante el rebase, úselo git rebase --abortpara cancelarlo.
William Hu
fuente
1

La solución para mantener los archivos / carpetas grandes dentro de la carpeta de trabajo

Esta es la línea que funcionó para resolver el problema que se pregunta aquí (de la respuesta 1):

git filter-branch --index-filter 'git rm -r --cached --ignore-unmatch <file/dir>' HEAD

Este comando también elimina el archivo / directorio si el archivo / directorio está dentro del árbol de trabajo.

Si desea mantener el archivo / carpeta dentro del árbol de trabajo, le propongo seguir los siguientes pasos.

  1. Después de ese error ejecutar git reset HEAD^
  2. Agregue el archivo / carpeta en cuestión en el archivo `` .gitignore```.

  3. Proceda como de costumbre, lo git add .que podría capturar otros archivos / carpetas pero debe capturar el .gitignorearchivo. Lo siguiente es git commit -m"message"y finalmentegit push origin <branch_name>

Kiprono Elijah Koech
fuente
0

Esto funcionó para mí. documentación de github Squashing Git Commits git reset origin / master

git checkout master && git pull;
git merge feature_branch;
git add . --all;
git commit -m "your commit message"

encuentra documentación aquí

Njoroge Mathu
fuente
0

Así que me encontré con una situación particular: cloné un repositorio de gitlab, que contenía un archivo de más de 100 mb, pero fue eliminado en algún momento del historial de git. Luego, cuando agregué un nuevo repositorio privado de Github e intenté avanzar al nuevo repositorio, recibí el infame error 'archivo demasiado grande'. En este punto, ya no tenía acceso al repositorio original de gitlab. Sin embargo, todavía pude acceder al nuevo repositorio privado de github usando bfg-repo-cleanerun repositorio LOCAL en mi máquina:

$ cd ~
$ curl https://repo1.maven.org/maven2/com/madgag/bfg/1.13.0/bfg-1.13.0.jar > bfg.jar
$ cd my-project
$ git gc
$ cd ../
$ java -jar bfg.jar --strip-blobs-bigger-than 100M my-project
$ cd my-project
$ git reflog expire --expire=now --all && git gc --prune=now --aggressive
$ git remote -v # confirm origin is the remote you want to push to
$ git push origin master
Donato
fuente
0

A veces, el archivo se mantiene en el historial de seguimiento, pruebe los siguientes pasos:

  1. git commit, Si está viendo el modo de creación con el archivo grande en la lista, haga lo siguiente:
  2. git filter-branch --index-filter 'git rm -r --cached --ignore-unmatch filename' HEAD. Debería ver un montón de reescrituras en su consola que termina con:

    rm 'nombre de archivo' y

    la última línea Ref fue reescrita.

Está hecho.

DR árbol
fuente
-1

Estoy agregando a la primera respuesta.

git filter-branch --index-filter 'git rm -r --cached --ignore-unmatch' HEAD

Habrá algún conflicto de fusión desde el origen / maestro.

Su rama y 'origen / maestro' han divergido, y tienen 114 y 109 confirmaciones diferentes cada uno, respectivamente. (use "git pull" para fusionar la rama remota en la suya)

Por favor ejecuta esto

git reset - origen duro / maestro

Desechará todos mis cambios por etapas y por etapas, olvidará todo en mi sucursal local actual y lo hará exactamente igual que origen / maestro.

RAHUL KUMAR
fuente