¿Puedo 'confirmar' un archivo e ignorar sus cambios de contenido?

355

Cada desarrollador de mi equipo tiene su propia configuración local. Esa información de configuración se almacena en un archivo llamado devtargets.rbque se utiliza en nuestras tareas de compilación de rake. Sin embargo, no quiero que los desarrolladores se golpeen entre sí el archivo de devtargets del otro.

Mi primer pensamiento fue poner ese archivo en la .gitignorelista para que no esté comprometido con git.

Entonces comencé a preguntarme: ¿es posible confirmar el archivo, pero ignorar los cambios en el archivo? Entonces, confirmaría una versión predeterminada del archivo y luego, cuando un desarrollador lo cambie en su máquina local, git ignoraría los cambios y no aparecería en la lista de archivos modificados cuando realiza un estado git o git commit .

¿Es eso posible? Sin duda sería una buena característica ...

Derick Bailey
fuente
1
Consulte también stackoverflow.com/questions/3318043/… sobre un tema similar.
VonC

Respuestas:

458

Claro, hago exactamente esto de vez en cuando usando

git update-index --assume-unchanged [<file> ...]

Para deshacer y comenzar a rastrear nuevamente (si olvidó qué archivos no se rastrearon, consulte esta pregunta ):

git update-index --no-assume-unchanged [<file> ...]

Documentación relevante :

- [no-] asumir-sin cambios
Cuando se especifica este indicador, los nombres de objeto registrados para las rutas no se actualizan. En cambio, esta opción establece / desactiva el bit "asumir sin cambios" para las rutas. Cuando el bit "asumir sin cambios" está activado, el usuario promete no cambiar el archivo y le permite a Git suponer que el archivo del árbol de trabajo coincide con lo que está registrado en el índice. Si desea cambiar el archivo de árbol de trabajo, debe desactivar el bit para decirle a Git. Esto a veces es útil cuando se trabaja con un gran proyecto en un sistema de archivos que tiene una lstat(2)llamada de sistema muy lenta (por ejemplo, cifs).

Git fallará (con gracia) en caso de que necesite modificar este archivo en el índice, por ejemplo, al fusionar en una confirmación; por lo tanto, en caso de que el archivo supuesto no rastreado se cambie en sentido ascendente, deberá manejar la situación manualmente.

Fallar con gracia en este caso significa que si hay algún cambio en ese archivo (cambios legítimos, etc.) cuando realiza una extracción, dirá:

$ git pull
…
From https://github.com/x/y
   72a914a..106a261  master     -> origin/master
Updating 72a914a..106a261
error: Your local changes to the following files would be overwritten by merge:
                filename.ext

y se negará a fusionarse.

En ese momento, puede superar esto al revertir sus cambios locales, aquí hay una manera:

 $ git checkout filename.ext

luego tire nuevamente y vuelva a modificar su archivo local, o podría configurarlo –no-assume-unchangedy puede hacer un alijo y fusión normales, etc. en ese punto.

Rob Wilkerson
fuente
10
¿Este comando hace su trabajo localmente en la carpeta .git? Quiero decir, si ejecuto este comando para un archivo config.php, ¿se propagará a otros usuarios que estén usando el repositorio?
Magus
16
@ Magus: No. Esto solo funcionará para usted.
Rob Wilkerson
3
Y poco después querrá saber cómo determinar si se supone que un archivo no ha cambiado: stackoverflow.com/questions/2363197/…
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
10
Los cambios en los archivos ignorados de esta manera se pierden cuando se usa "git stash". ¿Hay alguna manera de evitar eso?
Alexis
55
Esto no git update-index --assume-unchangedes para lo que sirve. public-inbox.org/git/…
jsageryd
97

La forma preferida de hacer esto es usar git update-index --skip-worktree <file>, como se explica en esta respuesta :

assume-unchangedestá diseñado para casos en los que es costoso verificar si se ha modificado un grupo de archivos; cuando configura el bit, git (por supuesto) asume que los archivos correspondientes a esa parte del índice no se han modificado en la copia de trabajo. Por lo tanto, evita un lío de llamadas estadísticas. Este bit se pierde cada vez que cambia la entrada del archivo en el índice (por lo tanto, cuando el archivo se cambia en sentido ascendente).

skip-worktreees más que eso: incluso cuando git sabe que el archivo ha sido modificado (o necesita ser modificado por un reinicio, duro o similar), fingirá que no lo ha sido, en su lugar, usará la versión del índice. Esto persiste hasta que se descarta el índice.

Para deshacer esto, use git update-index --no-skip-worktree <file>

Desde git versión 2.25.1, esta tampoco es la forma recomendada, citando:

Los usuarios a menudo intentan usar los bits de asumir-sin cambios y omitir-trabajo para decirle a Git que ignore los cambios en los archivos que se rastrean. Esto no funciona como se esperaba, ya que Git aún puede verificar los archivos de árbol de trabajo contra el índice al realizar ciertas operaciones. En general, Git no proporciona una forma de ignorar los cambios en los archivos rastreados, por lo que se recomiendan soluciones alternativas.

Por ejemplo, si el archivo que desea cambiar es algún tipo de archivo de configuración, el repositorio puede incluir un archivo de configuración de muestra que luego puede copiarse en el nombre ignorado y modificarse. El repositorio puede incluso incluir un script para tratar el archivo de muestra como una plantilla, modificándolo y copiándolo automáticamente.

1615903
fuente
¿Funciona esto en todos los usuarios que finalizan la compra del repositorio? ¿Obtendrán ciertos archivos pero ya no podrán agregar cambios, por error, a menos que lo indiquen explícitamente?
mmm
2
@momomo la bandera se almacena en el índice, así que no, es solo para un solo usuario. Vea la respuesta de erjiang para algo que funciona en todos los usuarios.
1615903
Estoy tratando de averiguar cuál debería ser el contenido del archivo. Comenté la respuesta a la que se refirió, pero no obtuve respuesta. ¿Dónde se supone que debe ubicarse y cuál es su contenido? ¿Tú sabes?
mmm
No te estoy siguiendo. El comando se utiliza para ignorar un archivo específico que especifique en el comando. El contenido de ese archivo no es relevante.
1615903
1
La documentación de Git dice específicamente que no se use git update-index --skip-worktreepara este propósito.
bk2204
43

La práctica común parece ser crear un devtargets.default.rby confirmarlo, y luego indicar a cada usuario que copie ese archivo devtargets.rb(que está en la lista .gitignore). Por ejemplo, CakePHP hace lo mismo para su archivo de configuración de base de datos que naturalmente cambia de máquina a máquina.

erjiang
fuente
66
No puede .gitignore un archivo que se está rastreando. .gitignore solo tiene un efecto para los archivos que no están en el índice.
CB Bailey
1
Estaba tratando de evitar hacer esto, aunque realmente no tengo una buena razón. lo estamos haciendo ahora y creo que es difícil recordar que necesito crear mi propia versión sin ".default" en el nombre.
Derick Bailey
11
@DerickBailey Pero para ser justos, es más fácil recordar copiar el archivo que recordar usar la --assume-unchangedopción para todos los que clonan el repositorio.
Dan
1
@DerickBailey, también puede configurar su construcción de rastrillo de manera predeterminada devtargets.default.rbsi devtargets.rbno existe.
Luke
@erjang, ¿qué hay en ese archivo devtargets.default.rb? ¿Un ejemplo?
mmm
2

Para usuarios de IntelliJ IDEA: si desea ignorar los cambios para un archivo (o archivos), puede moverlo a otro Change Set.

  • Dirígete a Local Changes( Cmd + 9)
  • Seleccione los archivos que desea ignorar
  • F6 para moverlos a otro Change Set
Eugene
fuente