Eliminar un archivo de un repositorio Git sin eliminarlo del sistema de archivos local

3048

Mi confirmación inicial contenía algunos archivos de registro. He agregado *loga mi .gitignore, y ahora quiero eliminar los archivos de registro de mi repositorio.

git rm mylogfile.log

eliminará un archivo del repositorio, pero también lo eliminará del sistema de archivos local.

¿Cómo puedo eliminar este archivo del repositorio sin eliminar mi copia local del archivo?

mveerman
fuente
14
Vale la pena señalar que la respuesta más votada es peligrosa para algunos. Si está utilizando un repositorio remoto que cuando presiona su local, luego extraiga aquellos archivos que eliminó de git solo SE ELIMINARÁN . Esto se menciona en una de las respuestas pero no se comenta.
RichieHH

Respuestas:

4356

Del archivo man :

Cuando --cached se proporciona, el contenido por etapas debe coincidir con la punta de la rama o el archivo en el disco, lo que permite que el archivo se elimine solo del índice.

Entonces, para un solo archivo:

git rm --cached mylogfile.log

y para un solo directorio:

git rm --cached -r mydirectory
bdonlan
fuente
151
Se pierde fácilmente porque no es tan autoexplicativo como svn rm --keep-local.
Martin
114
Pero, ¿cómo conservo los archivos en servidores remotos? Esto mantiene mi local, pero si presiono y extraigo de otro servidor, el archivo se elimina. También agregué un .gitignore para el archivo, pero aún así se elimina
Spankmaster79
66
Esto todavía elimina los archivos git pullsi está detrás de la confirmación despuésgit rm
Petr Peller
99
Vale la pena señalar que, después de ejecutar el comando en la respuesta, debe usar git commit -m "Commit message"y git push. Si tiene otros cambios por etapas (consulte con git status), también se confirmarán en este momento.
Sinjai
99
Como esta es la respuesta más aceptada y no hace lo que se pide, diré lo que hago. Uso el comando git rm --cached mylogfile.logy elimino el archivo del repositorio. Para evitar perder el archivo en un sistema productivo, hago una copia de seguridad del archivo y lo extraigo. El archivo se elimina como se mencionó anteriormente y debe copiarse nuevamente desde su copia de seguridad. Esto es bastante doloroso, pero no encontré una mejor solución para este problema.
Marcel Grolms
275

Para eliminar una carpeta completa del repositorio (como archivos Resharper), haga esto:

git rm -r --cached folderName

Había comprometido algunos archivos de intercambio y no quería que persistieran para otros usuarios del proyecto.

Sam Tyson
fuente
13
Solo una nota adicional para los visitantes futuros: no use una GUI para "sincronizar" la confirmación de vuelta al repositorio. Eso hará que los archivos vuelvan a su repositorio local. Debe hacer una Git Push repo branchpara eliminar realmente los archivos del control remoto.
RubberDuck
211

También puede eliminar archivos del repositorio en función de su .gitignore sin eliminarlos del sistema de archivos local:

git rm --cached `git ls-files -i -X .gitignore`

O, alternativamente, en Windows Powershell:

git rm --cached $(git ls-files -i -X .gitignore)
nulo
fuente
77
No funciona en Windows. git ls-files -i -X ​​.gitignore funciona, pero no sé cómo enviar los archivos a 'git rm'. ¿Sabes como hacer esto?
Erik Z
17
Funciona en Windows si usa Git Bash en lugar de cmd-console
Andreas Zita
17
Me gusta esto. Funcionó excepto que tenía algunos archivos que terminaban teniendo espacios en el nombre del archivo. He modificado solución para esto: git ls-files -i -X .gitignore | xargs -I{} git rm --cached "{}". Considere modificar o agregar esta solución a la respuesta aquí, porque es una gran herramienta para tener ...
mpettis
No lo intenté pero debería probarse si eliminará también archivos como los .gitkeepque conservan una carpeta vacía en el repositorio. P.ej. .gitignorecontener carpeta uploadsy el repositorio se ve obligado a realizar un seguimiento .gitkeep. Al eliminar todo del repositorio debajo, uploadstambién se eliminará .gitkeep.
Vladimir Vukanac
Esta sugerencia funcionó perfectamente en powershell: git rm --cached $ (git ls-files -i -X ​​.gitignore)
geekandglitter
89

Según mi respuesta aquí: /programming/6313126/how-to-remove-a-directory-in-my-github-repository

Para eliminar la carpeta / directorio o archivo solo del repositorio de git y no del local, intente con 3 simples pasos.


Pasos para eliminar el directorio

git rm -r --cached File-or-FolderName
git commit -m "Removed folder from repository"
git push origin master

Pasos para ignorar esa carpeta en las próximas confirmaciones

Para ignorar esa carpeta de las próximas confirmaciones, cree un archivo en la raíz llamado .gitignore y coloque el nombre de esa carpeta en él. Puedes poner tantos como quieras

El archivo .gitignore se verá así

/FolderName

eliminar directorio

eirenaios
fuente
@gaurav me alegro de que haya ayudado!
eirenaios
69

Además, si ha confirmado datos confidenciales (por ejemplo, un archivo que contiene contraseñas), debe eliminarlos completamente del historial del repositorio. Aquí hay una guía que explica cómo hacerlo: http://help.github.com/remove-sensitive-data/

BoD
fuente
13
Esta respuesta debe incluir los comandos necesarios para completar esta tarea en lugar de vincular a otro sitio web.
Florian Lemaitre
1
También me gustaría señalar que encontré que usar la herramienta de limpieza de repositorios git bfg es más fácil y rápido.
Lubed Up Slug
64

Una solución más genérica:

  1. Editar .gitignorearchivo

    ECHO mylogfile.log >> .gitignore

  2. Eliminar todos los elementos del índice.

    git rm -r -f --cached .

  3. Reconstruir índice.

    git add .

  4. Hacer un nuevo compromiso

    git commit -m "Removed mylogfile.log"

mAsT3RpEE
fuente
2
¿Esto realmente eliminará el archivo?
Mr_and_Mrs_D
66
¿De GitHub? NO. Si ya presionó a github, no lo eliminará del sitio. Pero actualizará su repositorio git local.
mAsT3RpEE
55
El comentario que eliminó fue más eliminado en realidad :) El problema con la solución rm --cashedes que eventualmente eliminará el archivo cuando se tire, ¿verdad? Y esto no es lo que la gente quiere cuando dice "Eliminar un archivo del repositorio sin eliminarlo del sistema de archivos local ". Ahora, ¿por qué la solución arriba aceptada está más allá de mí? ¿Probablemente el OP estaba trabajando solo y nunca lo hizo? No sé. Entiendo la github "una vez empujado siempre allí" cuestión OFC
Mr_and_Mrs_D
No creo que haya una solución al 100% a menos que le pregunte a Github. Por ahora quédate con esto. Copie el archivo, agregue a gitignore, haga git rm -r real, confirme, presione, restaure el archivo. ¿Lograste encontrar otra solución?
mAsT3RpEE
99
Mi problema no es github: es que el archivo se eliminará de los compañeros de trabajo cuando lo extraigan . Yo no quiero que el archivo que desea eliminar. Esto me ha causado grandes problemas en el pasado. Entonces, me preguntaba si realmente hay una solución que realmente no elimine el archivo. Vea también el comentario en la respuesta aceptada: stackoverflow.com/questions/1143796/…
Mr_and_Mrs_D
24

Git te permite ignorar esos archivos asumiendo que no han cambiado. Esto se hace ejecutando el git update-index --assume-unchanged path/to/file.txtcomando. Una vez marcado un archivo como tal, git ignorará por completo cualquier cambio en ese archivo; no se mostrarán al ejecutar git status o git diff, ni se comprometerán nunca.

(Desde https://help.github.com/articles/ignoring-files )

Por lo tanto, no lo elimina, sino que ignora los cambios para siempre. Creo que esto solo funciona localmente, por lo que los compañeros de trabajo aún pueden ver cambios a menos que ejecuten el mismo comando que el anterior. (Sin embargo, aún tengo que verificar esto).

Nota: Esto no responde la pregunta directamente, sino que se basa en preguntas de seguimiento en los comentarios de las otras respuestas.

Rystraum
fuente
2
Hm, hago esto pero veo que el archivo se puede sobrescribir si alguien más lo modifica en el repositorio.
AlxVallejo
17

Si solo desea eliminar un archivo y no eliminarlo del repositorio local y remoto, use este comando:

git update-index --assume-unchanged  file_name_with_path
Afraz Ahmad
fuente
2
Si bien esta es una buena respuesta, es importante tener en cuenta que esto no "destraba" un archivo en el sentido de que las personas usualmente usan esa palabra con Git, donde un archivo no rastreado es uno que no está en el historial del repositorio y nunca ha sido . Lo que hace esta respuesta es mantener el archivo en el repositorio pero evitar que Git se dé cuenta de que se han realizado cambios en él. Eso tiene algunas diferencias significativas: lo más importante es que el archivo todavía está presente para otros, y si alguien más lo modifica y usted lo extrae, su copia local puede sobrescribirse sin confirmación.
Soren Bjornstad
8

Las respuestas anteriores no funcionaron para mí. Solía filter-brancheliminar todos los archivos comprometidos.

Eliminar un archivo de un repositorio git con:

git filter-branch --tree-filter 'rm  file'

Eliminar una carpeta de un repositorio git con:

git filter-branch --tree-filter 'rm -rf directory'

Esto elimina el directorio o archivo de todas las confirmaciones.

Puede especificar una confirmación utilizando:

git filter-branch --tree-filter 'rm -rf directory' HEAD

O un rango:

git filter-branch --tree-filter 'rm -rf vendor/gems' t49dse..HEAD

Para llevar todo al control remoto, puede hacer:

git push origin master --force
Martijn Mellens
fuente
2
Esto, combinado con git rm -r --cached NAMEes el truco para sacarlo de su repositorio git local y evitar que afecte a cualquiera que tira después (mediante la supresión de la historia del archivo o directorio desde git.)
notbad.jpeg
1
Esto reescribe el historial de git y tendrías que presionar - fuerza después, esto está un poco fuera de alcance con la pregunta, supongo. En un repositorio famoso público, no puede simplemente cambiar la línea de la historia de esa manera, ya que todos los que ya hayan clonado el repositorio tendrán problemas al retirarlo.
Guillaume Perrot
0

Ignore los archivos, elimine los archivos de git, actualice git (para la eliminación).

Nota: esto no trata con el historial de información confidencial.

Este proceso definitivamente requiere algo de comprensión de lo que está sucediendo con git. Con el tiempo, después de ganar eso, aprendí a hacer procesos como:

1) Ignorar los archivos

  • Agregue o actualice el proyecto .gitignorepara ignorarlos, en muchos casos, como el suyo, el directorio principal, p. Ej.log/ , será la expresión regular a utilizar.
  • cometer e impulsar ese .gitignorecambio de archivo (no estoy seguro de si se necesita empujar, no hay daño si se hace).

2) Eliminar los archivos de git (solo).

  • Ahora elimine los archivos de git (solo) con git remove --cached some_dir/
  • Compruebe que todavía permanecen localmente (¡deberían!).

3) Agregue y confirme ese cambio (¡esencialmente este es un cambio para "agregar" eliminando cosas, a pesar del comando "agregar" que de otro modo sería confuso)

  • git add .
  • git commit -m"removal"
Michael Durrant
fuente