2012-04-09 29 views
168

Estaba trabajando en un repositorio en mi cuenta de GitHub y este es un problema con el que tropecé. proyectoEliminar la carpeta y su contenido del historial de git/GitHub

  • Node.js con una carpeta con algunos paquetes instalados NGP
  • Los paquetes estaban en node_modules carpeta
  • añadió que la carpeta de repositorio git y empujó el código para github (no estaba pensando en el NPM parte en ese momento)
  • dado cuenta de que realmente no necesita que la carpeta sea una parte del código
  • eliminados de esa carpeta, empujado

En esa instancia, el tamaño del repositorio de git total era alrededor de 6MB donde el código real (todos excepto esa carpeta) era solo alrededor de 300 KB.

Ahora, lo que estoy buscando al final es una manera de deshacerse de los detalles de esa carpeta de paquetes desde la historia de git, así que si alguien la clona, ​​no tiene que descargar 6mb de historial donde los únicos archivos reales que obtendrán a partir del último compromiso sería de 300 KB.

Busqué posibles soluciones para esto y probado estos 2 métodos

El Gist parecía que funcionaba en donde después de ejecutar el script, mostró que se deshizo de esa carpeta y luego mostró que se modificaron 50 commits diferentes. Pero no me dejó presionar ese código. Cuando traté de presionarlo, decía Branch up to date pero mostraba que 50 confirmaciones se modificaron con un git status. Los otros 2 métodos tampoco ayudaron.

Ahora bien, aunque demostró que se deshizo del historial de esa carpeta, cuando verifiqué el tamaño de ese repositorio en mi servidor local, todavía estaba alrededor de 6MB. (También eliminé la carpeta refs/original, pero no vi el cambio en el tamaño del repositorio).

Lo que quiero aclarar es si hay una manera de deshacerse no solo del historial de confirmaciones (que es lo único que creo que pasó) sino también de los archivos que git sigue asumiendo que uno quiere deshacer.

Digamos que se presenta una solución para esto y se aplica en mi servidor local pero no se puede reproducir en ese repositorio de GitHub, ¿es posible clonar ese repositorio, revertir al primer compromiso realizar el truco y empujarlo (o lo hace ¿Quiere decir que git todavía tendrá un historial de todos esos commits? - aka. 6MB).

Mi objetivo final es básicamente encontrar la mejor manera de deshacerse de los contenidos de la carpeta de git para que el usuario no tenga que descargar 6MB de cosas y aún posiblemente tenga las otras confirmaciones que nunca tocaron los módulos carpeta (que es más o menos todos) en la historia de git.

¿Cómo puedo hacer esto?

+0

Si alguna de las siguientes respuestas resuelve su problema, quizás deba considerar aceptar una como respuesta a su pregunta. https://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work – starbeamrainbowlabs

Respuesta

320

Si usted está aquí para copiar y pegar código:

Este es un ejemplo que elimina node_modules de la historia

git filter-branch --tree-filter 'rm -rf node_modules' --prune-empty HEAD 
git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d 
echo node_modules/ >> .gitignore 
git add .gitignore 
git commit -m 'Removing node_modules from git history' 
git gc 
git push origin master --force 
+13

También tuve que ejecutar 'git gc' después de ejecutar los comandos para liberar todo el espacio utilizado por las referencias eliminadas . – pagliuca

+12

Vale la pena señalar que si necesita impulsar esto en sentido ascendente, es probable que necesite forzar una actualización no rápida utilizando 'git push origin master --force' – DaveStephens

+10

¡Esta debería ser la respuesta aceptada! – prakharsingh95

5

copia completa & pasta receta, simplemente añadiendo los comandos en los comentarios (para el solución copiar-pegar), después de ellos la prueba:

git filter-branch --tree-filter 'rm -rf node_modules' --prune-empty HEAD 
echo node_modules/ >> .gitignore 
git add .gitignore 
git commit -m 'Removing node_modules from git history' 
git gc 
git push origin master --force 

después de esto, puede eliminar los "node_modules /" línea de .gitignor e

106

Me parece que la opción --tree-filter utilizada en otras respuestas puede ser muy lenta, especialmente en repositorios más grandes con muchas confirmaciones.

Aquí es el método que utilizo para eliminar completamente un directorio de la historia git utilizando la opción --index-filter, que corre mucho más rápido:

# Make a fresh clone of YOUR_REPO 
git clone YOUR_REPO 
cd YOUR_REPO 

# Create tracking branches of all branches 
for remote in `git branch -r | grep -v /HEAD`; do git checkout --track $remote ; done 

# Remove DIRECTORY_NAME from all commits, then remove the refs to the old commits 
# (repeat these two commands for as many directories that you want to remove) 
git filter-branch --index-filter 'git rm -rf --cached --ignore-unmatch DIRECTORY_NAME/' --prune-empty --tag-name-filter cat -- --all 
git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d 

# Ensure all old refs are fully removed 
rm -Rf .git/logs .git/refs/original 

# Perform a garbage collection to remove commits with no refs 
git gc --prune=all --aggressive 

# Force push all branches to overwrite their history 
# (use with caution!) 
git push origin --all --force 
git push origin --tags --force 

Puede comprobar el tamaño del repositorio antes y después de la gc con :

git count-objects -vH 
+2

¿podría explicar por qué es mucho más rápido? – knocte

+6

@knocte: de los documentos (https://git-scm.com/docs/git-filter-branch). "--index-filter: ... es similar al filtro de árbol pero no revisa el árbol, lo que lo hace mucho más rápido" –

+9

¿Por qué no es esta la respuesta aceptada? Es tan completo –

18

Además de la respuesta populares above me gustaría añadir algunas notas para de Windows -sistemas. El comando

git filter-branch --tree-filter 'rm -rf node_modules' --prune-empty HEAD 
  • funciona perfectamente sin ninguna modificación! Por lo tanto, no debe utilizar Remove-Item, del o cualquier otra cosa en lugar de rm -rf.

  • Si necesita especificar una ruta a un archivo o directorio utilización barras inclinadas como ./path/to/node_modules

+1

Es el comando perfecto y más simple también en Linux. – peterh

+0

Esto no funcionará en Windows si el directorio contiene a. (punto) en el nombre. –

+2

Y encontré la solución. Use comillas dobles para el comando rm de esta manera: "rm -rf node.modules". –

7

El mejor y más exacta método que encontré fue a descargar el archivo bfg.jar: https://rtyley.github.io/bfg-repo-cleaner/

A continuación, ejecute los comandos:

git clone --bare https://project/repository project-repository 
cd project-repository 
java -jar bfg.jar --delete-folders node_modules 
git reflog expire --expire=now --all && git gc --prune=now --aggressive 
git push --mirror https://project/new-repository 

Si desea eliminar los archivos a continuación, utilizar la opción de borrar archivos en su lugar:

java -jar bfg.jar --delete-files *.pyc 
+1

muy fácil :) si quiere asegurarse de que solo se elimine una carpeta específica, esto ayudará: https://stackoverflow.com/questions/21142986/remove-filenames-from-specific-path – emjay

0

Quité el bin y obj carpetas de viejos proyectos de C# utilizando git en las ventanas. Tenga cuidado con

git filter-branch --tree-filter "rm -rf bin" --prune-empty HEAD 

Se destruye la integridad de la instalación git eliminando la carpeta usr/bin en la carpeta de instalación de Git.

Cuestiones relacionadas