¿Cómo detener el seguimiento e ignorar los cambios en un archivo en Git?

1731

He clonado un proyecto que incluye algunos .csproj archivos. No necesito / me gusta que mis csprojarchivos locales sean rastreados por Git (o que aparezcan al crear un parche), pero claramente son necesarios en el proyecto.

Yo he añadido *.csproj a mi LOCAL .gitignore, pero los archivos ya están en el repositorio.

Cuando escribo el estado de git, muestra mis cambios a csproj que no estoy interesado en realizar un seguimiento o enviar parches.

¿Cómo elimino el "seguimiento" de estos archivos de mi repositorio personal (pero los mantengo en la fuente para poder usarlos) para que no vea los cambios cuando hago un estado (o creo un parche)?

¿Hay una manera correcta / canónica de manejar esta situación?

Joshua Ball
fuente
18
Una pregunta muy útil, pero tengo curiosidad por saber por qué no desea realizar un seguimiento de los cambios en el .csprojarchivo, que es una parte muy importante de cualquier proyecto. Cambios en el .csproj.userarchivo o en cualquier .Publish.XMLarchivo que entiendo totalmente sin seguimiento, pero estoy intrigado por qué no querría seguir el .csproj...
Owen Blacker
77
¿Quizás usan un IDE diferente?
Jarrett
3
Irónicamente, llegué a este hilo porque estoy buscando eliminar archivos .suo de un repositorio pero mantenerlos localmente. Para la posteridad, el desarrollo .Net requiere que guarde los archivos .csproj en el repositorio y esos cambios siempre deben ser rastreados a menos que desee sentir la ira de cualquier otro desarrollador en su proyecto. Si alguna vez no está seguro, eche un vistazo al repositorio de archivos de gitignore en GitHub: github.com/github/gitignore/blob/master/VisualStudio.gitignore
longda
1
@Cupcake, la pregunta a la que te has vinculado se escribió 15 días después de esta. ¿Quizás tienes otro en mente?
stephenmurdoch
Las preguntas canónicas de @marflar no necesariamente tienen que ser las más antiguas , solo las mejores . La que he vinculado tiene 20 respuestas, mientras que esta solo tiene 5.

Respuestas:

2129

Solo llamando git rm --cached a cada uno de los archivos que desea eliminar del control de revisión debería estar bien. Mientras sus patrones locales de ignorar sean correctos, no verá estos archivos incluidos en la salida del estado de git.

Tenga en cuenta que esta solución elimina los archivos del repositorio, por lo que todos los desarrolladores tendrían que mantener sus propias copias locales (sin revisión de revisión) del archivo

Para evitar que git detecte cambios en estos archivos, también debe usar este comando:

git update-index --assume-unchanged [path]

Lo que probablemente quieras hacer: (desde abajo @Ryan Taylor responde )

  1. Esto es para decirle a Git que desea su propia versión independiente del archivo o carpeta. Por ejemplo, no desea sobrescribir (o eliminar) los archivos de configuración de producción / preparación.

git update-index --skip-worktree <path-name>

La respuesta completa está aquí en esta URL: http://source.kohlerville.com/2009/02/untrack-files-in-git/

Antonio
fuente
187
"git rm --cached <file>" eliminaría <file> del control de versión y lo mantendría en el repositorio de trabajo. Si es lo que quieres ...
Jakub Narębski
51
Pero cuando otro extraiga el repositorio, ¿se eliminará su propio archivo * .csproj? Porque si queremos que el archivo no se rastree, pero no se elimine.
FMaz008 01 de
23
Si está tratando de eliminar TODOS los archivos en un directorio, combínelo con git ls-files: git ls-files | xargs git rm --cachedeso eliminará todo del índice git en un directorio dado sin eliminar los archivos reales.
Marco
129129
git rm --cached -r <dir>funciona de forma recursiva en una carpeta y todos los archivos que contiene.
Chris K
41
Esto detendrá el seguimiento del archivo, lo conservará localmente, pero hará que se elimine para cualquiera que lo retire
Edward Newell
249

Si lo hace git update-index --assume-unchanged file.csproj, git no comprobará los cambios en file.csproj automáticamente: eso evitará que aparezcan en estado git cada vez que los cambie. Por lo tanto, puede marcar todos sus archivos .csproj de esta manera, aunque tendrá que marcar manualmente los nuevos que le envíe el repositorio ascendente. (Si los tienes en tu .gitignoreo .git/info/exclude, entonces los que crees serán ignorados)

No estoy completamente seguro de qué son los archivos .csproj ... si son algo similar a las configuraciones de IDE (similar a los archivos .eclipse y .classpath de Eclipse), entonces sugeriría que simplemente nunca deberían controlarse en origen en todas. Por otro lado, si son parte del sistema de compilación (como Makefiles), entonces claramente deberían --- y una forma de recoger cambios locales opcionales (por ejemplo, desde un local.csproj a la config.mk) sería útil : divide la acumulación en partes globales y anulaciones locales.

araqnid
fuente
8
csproj es un archivo de proyecto de C #, que realiza un seguimiento de los archivos que se incluyen en su proyecto y otras pocas configuraciones, DEBE ser controlado por fuente para que el proyecto funcione
SparK
44
¡Esta es la única respuesta correcta aquí! He estado usando @araqnids answer durante años y funciona exactamente como se solicitó para resolver este problema.
NHDaly
¿Cuál es el significado del prefijo 'archivo' en el argumento del comando? ¿Por qué no es justo .csproj?
GreenAsJade
1
¿Hay alguna forma de detectar que esto se ha hecho para un archivo o para qué archivos se ha hecho en un repositorio? Estoy un poco nervioso por olvidar que hice esto, y luego me pregunto por qué diablos este archivo no se está actualizando, más adelante.
GreenAsJade
44
@GreenAsJade: git ls-files -vmostrará los archivos que se suponen sin cambios con un indicador en minúsculas (por ejemplo, en hlugar de lo habitual Hpara los archivos en caché).
Amadan
238

Hay 3 opciones, probablemente quieras # 3

1. Esto mantendrá el archivo local para usted, pero lo eliminará para cualquier otra persona cuando lo extraigan.

git rm --cached <file-name> o git rm -r --cached <folder-name>

2. Esto es para la optimización, como una carpeta con una gran cantidad de archivos, por ejemplo, SDK que probablemente nunca cambiarán. Le dice a git que deje de verificar esa enorme carpeta cada vez por cambios, localmente, ya que no tendrá ninguno. El assume-unchangedíndice se restablecerá y los archivos se sobrescribirán si hay cambios ascendentes en el archivo / carpeta (cuando se extrae).

git update-index --assume-unchanged <path-name>

3. Esto es para decirle a git que desea su propia versión independiente del archivo o carpeta. Por ejemplo, no desea sobrescribir (o eliminar) los archivos de configuración de producción / preparación.

git update-index --skip-worktree <path-name>

Es importante saber que git update-index no se propagará con git, y cada usuario tendrá que ejecutarlo de forma independiente.

Ryan Taylor
fuente
8
Esta respuesta es la más completa: ofrece varias soluciones con las ramificaciones de cada una. El caso específico con el que estoy trabajando tiene una contraseña incrustada en un archivo de configuración. Quiero propagar un archivo de plantilla y luego agregar la contraseña a mi copia. La copia con la contraseña debe ignorarse y no sobrescribirse.
bmacnaughton
1
¿Cómo puedo verificar, en mi local, qué archivos se aplican para 'asumir-sin cambios' o 'omitir-árbol de trabajo'?
Supawat Pusavanno
3
@SupawatPusavanno para ver qué archivos seleccionó previamente para asumir-sin cambios u omitir-worktree mire esta respuesta stackoverflow.com/questions/42363881/… - usa grepygit ls-files
Ryan Taylor
1
Muy buena respuesta. Pero git arroja un error cuando intento cambiar a una rama diferente: error: "Sus cambios locales en los siguientes archivos se sobrescribirán al finalizar la compra ..." y la solución es guardar los cambios antes de cambiar y desarmar cuando vuelves a la rama.
PhantomReference
@RyanTaylor: He intentado asumir sin cambios primero (no funcionó) y omitir el comando worktree (no funcionó), cuando verifico con el estado de git los archivos no se muestran significa que el comando funcionó. Pero cuando vuelvo a extraer el código del repositorio de origen de git it gives me error that your local changes would be overwrittenen esos 2 archivos, eso significa que no se está rastreando, ¿verdad?
NeverGiveUp161
152

Este es un proceso de dos pasos:

  1. Elimine el seguimiento del archivo / carpeta, pero manténgalos en el disco, utilizando

    git rm --cached 
    

    Ahora no se muestran como "cambiados" pero aún se muestran como

        untracked files in  git status -u  
    
  2. Añádelos a .gitignore

rjha94
fuente
56
No, esto eliminará el archivo del seguimiento, lo conservará localmente, pero hará que se elimine para cualquier persona que tire .
Edward Newell
1
En mi caso, accidentalmente agregué una carpeta que no quería rastrear, así que esto es lo que necesitaba.
Sonny
44
Sí, de hecho, es la respuesta incorrecta a la pregunta formulada, pero probablemente sea la respuesta correcta para la mayoría de las personas que encuentran esta pregunta en los resultados de búsqueda (como yo).
Andrew Spencer
95

La respuesta aceptada todavía no funcionó para mí.

solía

git rm -r --cached.

git add.

git commit -m "arreglando .gitignore"

Encontré la respuesta desde aquí

Buddhika Hasthanayake
fuente
Ese enlace es muy útil, especialmente para eliminar recursivamente todos los archivos en el .gitignore
rmcsharry
99
He regresado aquí 3 veces, ¡espero poder comprometerme con la memoria antes de la próxima vez!
Harry Bosh
El comentario de @Edward Newell como en la respuesta anterior también se aplica aquí: "esto eliminará el archivo del seguimiento, lo preservará localmente, pero hará que se elimine para cualquier persona que tire ".
ToJo
47

¿Olvidaste tu .gitignore?

Si tiene todo el proyecto localmente pero olvidó agregarle git ignore y ahora está rastreando algunos archivos innecesarios, use este comando para eliminar todo

git rm --cached -r .

asegúrese de estar en la raíz del proyecto.

Entonces puedes hacer lo habitual

Añadir

git add .

Cometer

git commit -m 'removed all and added with git ignore'

empujar

git push origin master

Conclusión

Espero que esto ayude a las personas que tienen que hacer cambios a ellos .gitignoreo que se olvidaron de todo.

  • Elimina todo el caché
  • Mira tu .gitignore
  • Agrega los archivos que desea rastrear
  • Empuja a tu repositorio
Joe Lloyd
fuente
44
Cuando habla de eliminar o agregar, olvida decir cuándo y dónde. ¿Eliminar de la lista de pistas? Desde el repositorio? Desde el espacio del proyecto local? Retirar en el tirón? En commit? En empuje? Por desgracia, todos los autores aquí tienen el mismo problema.
Gangnus
3
@Gangnus No creo que nadie 'aclare' el punto que está tratando de hacer porque es completamente obvio que el archivo no se está eliminando del disco o del repositorio. Esta respuesta especifica el orden cronológico de los comandos. No es misterioso ni está mal explicado como su comentario sugeriría.
Anthony
El comentario de @Edward Newell como en la respuesta anterior también se aplica aquí: "esto eliminará el archivo del seguimiento, lo preservará localmente, pero hará que se elimine para cualquier persona que tire ".
ToJo
26

Como se señaló en otras respuestas, la respuesta seleccionada es incorrecta.

La respuesta a otra pregunta sugiere que puede ser necesario omitir el árbol de trabajo.

git update-index --skip-worktree <file>
the_new_mr
fuente
2
No, en realidad no: --skip-worktreese utiliza para mantener el archivo en el repositorio pero dejar de rastrear sus cambios . Como dice su respuesta: --skip-worktree es útil cuando le indica a git que no toque un archivo específico porque los desarrolladores deberían cambiarlo
Erdal G.
44
@ErdalG. Exactamente. Según la pregunta, quieren ignorar cualquier cambio en el archivo pero mantener el archivo en el repositorio
the_new_mr
De acuerdo con @the_new_mr --assume-unchangedy --skip-worktreetener un efecto similar, pero sus propósitos son completamente diferentes. El primero es para acelerar el rendimiento de git engañando a git para que no revise archivos particulares , mientras que el segundo es para ignorar cambios futuros en archivos particulares , que son adecuados para el tiempo de ejecución pero archivos esenciales.
Victor Wong
22

Para ahorrar algo de tiempo, las reglas que agrega a su .gitignore pueden usarse para eliminar múltiples archivos / carpetas, es decir

git rm --cached app/**/*.xml

o

git rm --cached -r app/widgets/yourfolder/

etc.

Peter
fuente
Esta es una muy buena solución porque, en caso de que quiera arreglar el gitignore paso a paso
cutiko
15

Para evitar el monitoreo de un archivo por git

git update-index --assume-unchanged [file-path]

Y para revertirlo, usa

git update-index --no-assume-unchanged [file-path]

Un repositorio para referirse a casos de uso similares https://github.com/awslabs/git-secrets

shijin
fuente
1
Revertir la propina fue un salvavidas, ¡gracias!
Hamman Samuel
9

Mucha gente te aconseja usar git update-index --assume-unchanged . De hecho, esta puede ser una buena solución, pero solo a corto plazo.

Lo que es probable que desee hacer es lo siguiente: git update-index --skip-worktree.

(La tercera opción, que probablemente no desee es: git rm --cachedmantendrá su archivo local, pero se marcará como eliminado del repositorio remoto).

¿Diferencia entre las dos primeras opciones?

  • assume-unchangedes permitirle temporalmente ocultar modificaciones de un archivo. Si desea ocultar las modificaciones realizadas a un archivo, modifique el archivo, luego revise otra rama, tendrá que usarno-assume-unchanged luego probablemente escondirá las modificaciones realizadas.
  • skip-worktree te seguirá, sea cual sea la rama que pagues, ¡con tus modificaciones!

Caso de uso de assume-unchanged

Asume que este archivo no debe modificarse, y le da una salida más limpia al hacerlo git status. Pero cuando se desprotege en otra rama, debe restablecer el indicador y confirmar o ocultar los cambios antes de hacerlo. Si tira con esta opción activada, deberá resolver conflictos y git no se fusionará automáticamente. En realidad, solo oculta modificaciones ( git statusno le mostrará los archivos marcados).

Me gusta usarlo cuando solo quiero detener el seguimiento de los cambios por un tiempo + confirmar un montón de archivos ( git commit -a) relacionados con la misma modificación.

Caso de uso de skip-worktree

Tiene una clase de configuración que contiene parámetros (por ejemplo, contraseñas incluidas) que sus amigos deben cambiar de acuerdo con su configuración.

  • 1: Cree una primera versión de esta clase, complete los campos que puede completar y deje otros vacíos / nulos.
  • 2: Comprometerlo y enviarlo al servidor remoto.
  • 3: git update-index --skip-worktree MySetupClass.java
  • 4: Actualice su clase de configuración con sus propios parámetros.
  • 5: Vuelva a trabajar en otra funcionalidad.

Las modificaciones que hagas te seguirán sea cual sea la rama. Advertencia: si sus amigos también quieren modificar esta clase, tienen que tener la misma configuración, de lo contrario, sus modificaciones se enviarían al repositorio remoto. Al tirar, la versión remota del archivo debe sobrescribir la suya.

PD: haz uno u otro, pero no ambos, ya que tendrás efectos secundarios indeseables. Si desea probar con otro indicador, primero debe desactivar el último.

belka
fuente
7

Para decirle a Git que no rastree los cambios en su archivo / carpeta local (lo que significa que el estado de git no detectará cambios en él), haga lo siguiente:

git update-index --skip-worktree path/to/file

Y para decirle a Git que rastree los cambios en su versión local una vez más (para que pueda confirmar los cambios), haga lo siguiente:

git update-index --no-skip-worktree path/to/file
Ruto Collins
fuente
1

respuesta de una línea git update-index --assume-unchanged [path]

Úselo siempre que tenga un archivo que esté en el repositorio central y también en el repositorio local. Debe realizar cambios en ese archivo pero no debe estar preparado / confirmado en el repositorio central. Este archivo no debe agregarse en.gitignore . Debido a que los administradores del sistema introducen nuevos cambios en el archivo, los desarrolladores principales deben distribuirse entre todos los repositorios locales.

El mejor ejemplo: archivo de configuración para conexiones de base de datos . En un repositorio central, tendrá todo el nombre de usuario, contraseña, host, puerto con valores de un servidor de base de datos de producción. Pero en el desarrollo local, debe usar solo un servidor de base de datos de desarrollo local o cualquier otro (que su equipo haya configurado). En este caso, desea realizar cambios en el archivo de configuración, pero no debe comprometerse con el repositorio central.

Mejor

Seenivasan
fuente
0

Supongo que está preguntando cómo eliminar TODOS los archivos en una carpeta específica o la carpeta bin, en lugar de seleccionar cada archivo por separado.

Puede usar este comando:

git rm -r -f /<floder-name>\*

asegúrese de estar en el directorio principal de ese directorio.
Este comando "borrará" recursivamente todos los archivos que están en las carpetas bin / o build /. Con la palabra eliminar me refiero a que git fingirá que esos archivos se "eliminan" y no se rastrearán esos archivos. El git realmente marca esos archivos para estar en modo de eliminación.

Asegúrate de tener tu .gitignore listo para los próximos commits.
Documentación: git rm

Vraj Pandya
fuente
0

El problema puede ser causado por el orden de operación. Si modificó el .gitignore primero, luego git rm --cached xxx, es posible que deba continuar encontrando este problema.

Solución correcta:

  1. git rm - caché xxx
  2. modificado el .gitignore

Orden invariante!

¡La recarga de .gitignore después de la modificación!

thearyong
fuente
0

Supongo que está tratando de eliminar un solo archivo de git tacking. para eso recomendaría el siguiente comando.

git update-index --asumir-sin cambios

Ex - git update-index --asum-sin cambios .gitignore .idea / compiler.xml

Pankaj Sonani
fuente
0

Para ignorar cualquier cambio en todos los archivos (de cierto tipo) en un directorio, tuve que combinar algunos de estos enfoques, de lo contrario, los archivos se crearon si no existían previamente.

A continuación, "excludedir" es el nombre del directorio en el que no deseo ver los cambios.

Primero, elimine cualquier archivo nuevo existente de su caché de seguimiento de cambios (sin eliminarlo de su sistema de archivos).

git status | grep "new file:" | cut  --complement -d " " -f1-4 | grep "^excludedir" | xargs git rm --cache

Puedes hacer lo mismo con modified:. renamed:es un poco más complicado, ya que tendrá que mirar el ->bit de publicación para el nuevo nombre de archivo y hacer el ->bit previo como se describe a deleted:continuación.

deleted: los archivos resultan un poco más complicados, ya que parece que no puede actualizar el índice de un archivo que no existe en el sistema local

echo .deletedfiles >> .gitignore
git status | grep "deleted:" | cut  --complement -d " " -f1-4 | grep "^excludedir" > .deletedfiles
cat .deletedfiles | xargs -d '\n' touch
cat .deletedfiles | xargs -d '\n' git add -f
cat .deletedfiles | xargs -d '\n' git update-index --assume-unchanged
cat .deletedfiles | xargs -d '\n' rm

El último comando en la lista anterior eliminará los archivos nuevamente de su sistema de archivos, así que siéntase libre de omitir eso.

Luego, bloquee el seguimiento de cambios desde ese directorio

git ls-files excludedir/ | xargs git update-index --skip-worktree
git update index --skip-worktree excludedir/
mpag
fuente
0

Se dio un enfoque casi libre de comandos git en esta respuesta :

Para ignorar ciertos archivos para cada repositorio local :

  1. Cree un archivo ~/.gitignore_global, por ejemplo, touch ~/.gitignore_globalen su terminal.
  2. Corre git config --global core.excludesfile ~/.gitignore_globalpor una vez.
  3. Escriba las rutas de archivo / directorio que desea ignorar ~/.gitignore_global. por ejemplo modules/*.H, que se supondrá que está en su directorio de trabajo, es decir $WORK_DIR/modules/*.H.

Para ignorar ciertos archivos para un único repositorio local :

  1. Realice el tercer paso anterior para el archivo .git/info/excludedentro del repositorio, es decir, escriba las rutas de archivo / directorio en las que desea ignorar .git/info/exclude. por ejemplo modules/*.C, que se supondrá que está en su directorio de trabajo, es decir $WORK_DIR/modules/*.C.
Ingeniero libre de herpes
fuente
0

Aplicar .gitignore al presente / futuro

Este método aplica el comportamiento estándar .gitignore y no requiere especificar manualmente los archivos que deben ignorarse .

No puede usar --exclude-from=.gitignore más: / - Aquí está el método actualizado:

Consejo general: comience con un repositorio limpio : todo está comprometido, nada pendiente en el directorio o índice de trabajo, ¡ y haga una copia de seguridad !

#commit up-to-date .gitignore (if not already existing)
#this command must be run on each branch
git add .gitignore
git commit -m "Create .gitignore"

#apply standard git ignore behavior only to current index, not working directory (--cached)
#if this command returns nothing, ensure /.git/info/exclude AND/OR .gitignore exist
#this command must be run on each branch
git ls-files -z --ignored --exclude-standard | xargs -0 git rm --cached

#optionally add anything to the index that was previously ignored but now shouldn't be:
git add *

#commit again
#optionally use the --amend flag to merge this commit with the previous one instead of creating 2 commits.

git commit -m "re-applied modified .gitignore"

#other devs who pull after this commit is pushed will see the  newly-.gitignored files DELETED

Si también necesita purgar los archivos recién ignorados del historial de confirmaciones de la rama o si no desea que los archivos ignorados recientemente se eliminen de futuras extracciones , consulte esta respuesta .

goofología
fuente
-1

Después de buscar mucho tiempo, encuentre la manera de hacerlo. alias un comando git en .gitconfig.like en el proyecto de estudio de Android, antes de que la rama de pago revierta el archivo de configuración y luego lo omita, después de que la rama de pago use el sedarchivo de configuración de cambio a mi configuración local. checkoutandmodifylocalproperties = !git update-index --no-skip-worktree local.properties && git checkout local.properties && git checkout $1 && git update-index --skip-worktree local.properties && sed -i '' 's/.*sdk.dir.*/sdk.dir=\\/Users\\/run\\/Library\\/Android\\/sdk/g' local.properties && :

chinaanihchen
fuente