¿Cómo puedo hacer que git ignore futuras revisiones de un archivo?

140

He creado una versión predeterminada de un archivo incluido en un repositorio git. Es importante que cuando alguien clone el repositorio, obtenga una copia de este archivo. Sin embargo, me gustaría configurar git para que ignore los cambios en este archivo más adelante. .gitignorefunciona solo en archivos sin seguimiento.

Mi motivación es que este archivo contiene información específica de la máquina. Me gustaría proporcionar valores predeterminados, al tiempo que permitiría a las personas realizar cambios locales que no se retrasarán al repositorio de origen, creando conflictos de fusión cuando realizamos nuevos cambios.

En general, somos bastante vagos y usamos git add .mucho, así que estoy bastante seguro de que si no puedo decirle a Git que ignore este archivo, los cambios en él terminarán comprometiéndose y empujados.

Para resumir,

  1. Me gustaría crear un archivo, llamarlo default_values.txtque se agrega a mi repositorio git y se incluye cuando alguien clona ese repositorio.
  2. git add .no debe agregar default_values.txtal commit.
  3. Este comportamiento debe pasarse a cualquier clon del repositorio.
Bagazo
fuente
1
¿Se puede utilizar git hooks para tener un enlace de precompromiso que anularía un compromiso si el archivo modificado es default_values.txt (digamos)?
sateesh
1
Los puristas de Git dirían que no sean perezosos y usen el área de preparación correctamente, para eso es.
Xint0
Los puristas de Git dirían que use guiones borrosos / limpios. Es la solución más fácil de mantener.
Adam Dymitruk
1
Xint0: cierto. pero, ¿cómo evitar que otras personas se registren accidentalmente?
Alan

Respuestas:

115

Como muchos otros han mencionado, una buena solución moderna es:

git update-index --skip-worktree default_values.txt

Eso ignorará los cambios en ese archivo, tanto local como ascendente, hasta que decida permitirlos nuevamente con:

git update-index --no-skip-worktree default_values.txt

Puede obtener una lista de archivos marcados como omitidos con:

git ls-files -v . | grep ^S

Tenga en cuenta que --skip-worktree, a diferencia , el --assume-unchangedestado se perderá una vez que se extraiga un cambio ascendente.

humor
fuente
2
Si alguien más extrae el repositorio y edita el archivo, ¿se ignoran los cambios en su directorio? Espero que tengan que escribir --no-skip-worktreepara agregar sus cambios.
neaumusic
3
Lo que se hace con sus cambios es controlado por ellos. En otras palabras, tendrían que establecer skip-worktree en el archivo en su repositorio si no querían que se introdujeran sus cambios. Si se trata de un archivo destinado a ser enviado a todos y luego se ignoran todos los cambios posteriores, todos tendrían que seguir estas mismas instrucciones.
moodboom
3
Tenga en cuenta que es posible que tenga que deshacer el --skip-worktreeestado de un archivo antes de poder cambiar de rama si ese mismo archivo se rastrea en la otra rama.
moodboom
3
hmm, funciona ... después de hacer algún cambio en el archivo, no se mostró git status, pero cuando traté de pagar en una rama diferente, obtuve error: Your local changes to the following files would be overwritten by checkout: , incluso -f no ayudaerror: Entry 'wix-stores-merchant-app/demo/credentials.js' not uptodate. Cannot merge.
ykravv
1
Tengo estos alias a git ignorey git unignore.
Michael
48

Lo que estás buscando es git update-index --assume-unchanged default_values.txt.

Consulte los documentos para obtener más detalles: http://www.kernel.org/pub/software/scm/git/docs/git-update-index.html

tamasd
fuente
11
esto no funciona. aunque hace que git agregue. ignore el archivo en la rama local, un clon del archivo no tiene este comportamiento (si cambia default_values.txt en el archivo clonado, se agregará al commit con "git add")
Marc
66
Sí, porque lo está configurando solo para el repositorio local. No puede empujar este tipo de información.
tamasd
8
@Indradhanush: esta solución no satisface el criterio 3: "el comportamiento debe transmitirse a los clones del repositorio", por lo que no lo acepté. No significa que no sea una buena respuesta.
Marc
Nunca me di cuenta del tercer criterio. Porque no lo estaba buscando. :)
Indradhanush Gupta
3
Para archivos de configuración locales con configuraciones de aplicaciones privadas, es probable que desee usar en skip-worktreelugar de assume-unchangedmás información stackoverflow.com/questions/13630849/…
Aaron Hoffman
22

El enfoque que generalmente he visto es crear un archivo con un nombre diferente, por ejemplo: default_values_template.txt y poner default_values.txt en su .gitignore. Indique a las personas que copien default_values_template.txt a default_values.txt en sus espacios de trabajo locales y que realicen los cambios necesarios.

Laurence Gonsalves
fuente
hmmm ... ¿tal vez podría escribir un gancho para copiar automáticamente default_values_template a default_values ​​si default_values ​​no existe?
Marc
2
Esta es la forma más común de resolver esto en mi experiencia. Es más o menos el camino de menor resistencia, ya que "simplemente funciona", y puede hacer que su código verifique fácilmente si existe el archivo de configuración local y proporcione un error útil si no es así.
Jani Hartikainen
Creo que la solución es hacer algo como esto, preferiblemente con un script ejecutado cada vez que extrae o clona. Una idea sería que cualquier cosa con una extensión particular (digamos .basefile) se copie en un archivo con la extensión eliminada y luego el nombre del archivo se agregue a .gitignore en ese directorio. Entonces crearía un archivo default_values.txt.basefile y lo confirmaría. No tengo las habilidades de git o perl para hacer esto, pero le preguntaré a un amigo que sí y le haré saber cómo funciona.
Marc
1
@AdamDymitruk: Sí, puede usarse limpiar / manchar en este caso, pero no está nada claro que esa sea la mejor opción. Por ejemplo, esto hará que sea bastante difícil si la gente realmente quiere cambiar el archivo, ya que la limpieza / mancha se interpondrá en el camino. De hecho, preferiría el enfoque descrito aquí.
sleske
1
Tomo una señal de git (específicamente git hooks) y uso el .samplesufijo. Así que en tu casodefault_values.txt.sample
tir38
5

Eche un vistazo a las secuencias de comandos borrosas / borrosas. De esta manera, puede controlar el archivo de la versión, pero cuando está desprotegido, lo "borrará" reemplazando los datos genéricos / de posición con datos específicos de la máquina en el archivo.

Cuando lo confirmes, lo "limpiarás" reemplazando la información específica de la máquina con información genérica o de posición.

Los scripts de difuminado / limpieza deben ser deterministas en el sentido de que aplicarlos varias veces, en diferentes órdenes, será el equivalente a ejecutar el último de la secuencia.

Lo mismo se puede aplicar con las contraseñas si necesita exponer su repositorio, pero el contenido puede contener información confidencial.

Adam Dymitruk
fuente
¿Los guiones de Clean and Smudge son locales o parte del repositorio?
Alan
si. :) ... es decir, puede compartir la limpieza a través del repositorio, pero no es una buena idea cuando contienen datos confidenciales como contraseñas de producción. Si eso no es una preocupación, git requiere que habilites explícitamente el script. De lo contrario, las personas podrían hacer cosas maliciosas a través de github y otros repositorios compartidos para otros usuarios.
Adam Dymitruk
Necesito leer un poco más sobre esto. Básicamente, quiero configurar un proyecto que tenga un valor predeterminado user.jsonque deba sobrescribirse con los créditos de cada desarrollador, pero no quiero que el desarrollador verifique accidentalmente sus créditos.
Alan
Buscaría en Google para encontrar secuencias de comandos de ejemplo de manchas limpias. Mira lo que viene. Además, salta a la sala de git irc en freenode. Obtendrá ayuda de inmediato.
Adam Dymitruk
3

He resuelto esto definiendo el filtro "limpio" para simplemente capturar el contenido del archivo en el índice.

git show :path/to/myfile solo debe imprimir el contenido del índice para el archivo especificado, de modo que podamos usarlo en un script para reemplazar la copia de trabajo con la copia intacta en el índice:

#! /bin/sh

git show :$1

Establezca eso como el filtro "limpio" para el archivo en cuestión (suponiendo que lo haya puesto en "discard_changes"):

$ git config filter.ignore_myfile.clean "discard_changes path/to/myfile"
$ echo "path/to/myfile filter=ignore_myfile" >> .gitattributes

Desafortunadamente, no puedo encontrar una manera de hacer esto generalizable a múltiples archivos, ya que no hay forma de saber qué archivo estamos procesando desde el script limpio. Por supuesto, no hay nada que le impida agregar una regla de filtro diferente para cada archivo, pero es un poco confuso.

Haddon CD.
fuente
1

Encontré una solución que funciona para mi equipo. Compartimos nuestros githooks a través de enlaces simbólicos y después de agregar un archivo de plantilla a git, agregué un enlace de precompromiso que verifica si el archivo de plantilla ha sido modificado y, de ser así, yo git reset -- templatefile.txt. Si es el único archivo modificado, también aborto la confirmación.

codificador de frutas
fuente
-1

Sugiero buscar en submódulos. Si coloca los archivos específicos de la máquina en un submódulo, git add debería ignorarlo.

ivanpro
fuente
esta es una buena idea, pero también tengo que poner el repositorio de un solo archivo en el servidor git, que es menos que óptimo, solo porque estamos usando github y tenemos un número limitado de repositorios.
Marc
@Marc echa un vistazo a Visual Studio Team Services, proyectos privados gratuitos ilimitados y repositorios git. Tableros Kanban, seguimiento de errores y elementos de trabajo, asociar registros con elementos de trabajo, administrar sprints si estás en scrum u otros tipos de proyectos. Además de que tiene excelentes herramientas de compilación para compilar contra múltiples plataformas, hay muchas cosas que mencionar que son gratuitas. Algunas personas lo critican porque es Microsoft, pero sin duda supera lo que Github tiene para ofrecer en términos de herramientas, aparte de solo el alojamiento de repositorios. Hay límites de lo que puede hacer de forma gratuita, pero rara vez los supero.
Aran Mulholland
@Marc Una cosa más que me parece muy útil es que puedo configurar tantas cuentas como quiera, así que si estoy escribiendo un proyecto para un cliente que quiere tener el control de origen, puedo crear una cuenta, usarla para planificar, diseñar y ejecutar el proyecto y cuando haya terminado, puedo transferir la propiedad de la cuenta al cliente.
Aran Mulholland