¿Cómo puedo completar el ID de confirmación de Git en un file cuando me comprometo?

Me gustaría crear ganchos Git que llenen el id. De confirmación de la confirmación que estoy a punto de convertir en un file (básicamente sustitución de variables) en mi código fuente. ¿Es esto posible con Git? O es el hecho de que al resolver la variable a la id. Git, voy a cambiar el sha 1, terminando con un problema de "gallina o huevo".

La solución que he usado para una situación similar es esta:

  1. Coloque la cadena $Id$ en algún lugar del file que desea identificar (por ejemplo, test.html ), probablemente dentro de un comentario u otra sección no funcional del file donde no cause problemas.
  2. En sus .gitattributes , .gitattributes el file en cuestión con la palabra key ident (por ejemplo, *.html ident ).

El resultado de esto es que cuando git checkout copy el file de la database de objects en su directory de trabajo, expande $Id$ string para leer $Id: <sha-1 of file>$ , y git add invierte esa transformación cuando desea verificarlo, de modo que las versiones de ese file en su database de objects solo contienen $Id$ , no los formularios expandidos.

Es un comienzo, pero desafortunadamente, encontrar la confirmación que contiene un file con un hash específico no es tan fácil, y tampoco necesariamente uno a uno. Entonces, además, también etiqueto esos files con el atributo de export-subst (ej. *.html ident export-subst en .gitattributes ), y agrego una cadena adicional, como $Format:%ci$ ($Format:%h$) en algún lugar del file también.

git checkout y git add no afectan a estas tags, así que las versiones en mi repository siempre tienen exactamente esa cadena. Para poder expandir esas tags, debes usar git archive para crear una tar-ball (o .zip) de una versión específica de tu proyecto, que luego usarás para implementar esa versión; no podrás simplemente copie los files, o make install o lo que sea, ya que el git archive es lo único que expandirá esas tags.

Las dos tags que di como ejemplo se expanden a YYYY-MM-DD HH:MM:SS +TZOFFSET (HASH) , donde el HASH en este caso es el hash de confirmación real, por lo que es más útil.

Puede encontrar otros especificadores de $Format:$ potencialmente útiles en la página de ayuda de git log bajo los --pretty-format .

Puede crear un filter que haga la sustitución en los files en la confirmación y la salida. Estos se llaman filters "borrón" y "limpio" y su operación se controla a través de .gitattributes . Por ejemplo:

 *.c   filter=yourfilter 

Esto le dice a git que ejecute el filter yourfilter para todos los files .c . Entonces tienes que decirle a git lo que significa tu yourfilter :

 git config --global filter.yourfilter.clean script1 git config --global filter.yourfilter.smudge script2 

Luego, debe escribir un script (sed, Perl, Python o cualquier otro) para replace una expresión como $LastSha$ con $LastSha: <sha>$ al $LastSha: <sha>$ compra ("mancha"). La otra secuencia de commands invierte la expansión antes del compromiso ("limpiar").

Busque en el libro de Pro Git "Expansión de palabras key" para ver un ejemplo detallado.

Es imposible hacer lo que desee: el hash SHA-1 de commit se calcula sobre toda la instantánea del repository, incluido el file de cada miembro, por lo que existe el problema del huevo y la gallina: para calcular el hash de confirmación, debe conocer el contenido de todos los files Comprenderlo.

Puedes hacer esto con el gancho post-commit . Aquí hay un extracto del website de git-scm

Después de que se complete todo el process de confirmación, se ejecuta el enganche post-commit. No toma ningún parámetro, pero puede get fácilmente la última confirmación ejecutando git log -1 HEAD. En general, este script se usa para notificación o algo similar.

Sería un caso de get la salida de git log -1 HEAD , luego usar una herramienta como sed para replace variables en su file. Sin embargo, esto modifica su directory de trabajo y, a less que vaya a descartar esos cambios, terminará con un directory de trabajo permanentemente modificado.

Si solo quiere usar el hash de confirmación actual en alguna variable de su código, puede ejecutar git log -1 HEAD o cat .git/HEAD y almacenar el resultado en su variable

Si solo quiere el id (hash) como en el título de la pregunta, puede usar el indicador --format . git log -1 HEAD --format=%H

La key aquí es poner su ID de revisión en algún file que a Git no le importe. Aquí hay un fragment de uno de mis proyectos:

 .
 .
 .
 AssemblyCS = "Propiedades / AssemblyInfo.cs"
 rev = "$ (git log -n 1 --date = short --format = formatting:" rev.% ad.% h "HEAD)"
 sed "$ AssemblyCS"
 .
 .
 .

Este script se ejecuta como parte de mi process de compilation (también podría ser un enlace post-commit). En este caso, Properties/AssemblyInfo.cs está en .gitignore mientras que Properties/AssemblyInfo.cs.in está bajo control de versión. La creación utiliza el file .cs incluye una ID de revisión que termina en el ejecutable desplegado.

Como han mencionado otros, no puede poner el SHA-1 de una confirmación en el file durante la misma confirmación. De todos modos, esto sería de uso limitado, ya que si mira dos files, no podrá saber de inmediato cuál es más nuevo.

Una vez dicho esto, de hecho hay una manera de poner la información de seguimiento de la versión en files comprometidos automáticamente. Hice esto para mi proyecto actual (FrauBSD, una bifurcación de FreeBSD en la que estoy trabajando).

Lo logré no usando un filter de attributes git. Mientras que los filters de attributes de git hacen que sea fácil lograr lo contrario (poner la información en los files al finalizar la compra), lo que quería era expandir ciertas palabras key en el momento de la confirmación para que los datos lleguen al repository ( por ejemplo, después de un "maestro de origen de git push", github muestra los valores expandidos en el (los) file (s) confirmado (s)). Lograr lo último resultó extremadamente difícil con un filter de attributes git precisamente porque un simple "git diff" invocará el atributo filter.clean y, como era el problema en mi caso, si está poniendo información de date / hora en la expansión, tener el el cambio de valor cada vez que realiza "git diff" es indeseable e inaceptable.

Así que he desarrollado un gancho pre-commit y un gancho commit-msg que, actuando en set, resuelven el problema de cómo (específicamente en el caso FrauBSD) replace lo siguiente en los files comprometidos:

$ FrauBSD $

Con algo similar a lo siguiente antes del check-in (los valores expandidos van en sentido ascendente para que otros puedan realizar el pago):

$ FrauBSD: filepath YYYY-MM-DD HH: MM: ZZ GMTOFFSET committer $

Cuando alguien está navegando por el file en github o realiza un pago o una fusión de los files, la información expandida se acompaña durante el viaje.

NOTA: El valor expandido nunca cambiará a less que haya otro cambio (no relacionado) que lo acompañe, respectivamente.

Por ejemplo, consulte la siguiente confirmación en la que simplemente elimino una nueva línea final de un file. La confirmación contiene tanto la eliminación de la línea nueva final como un aumento a la date / hora en la palabra key $ FrauBSD $:

https://github.com/freebsdfrau/FrauBSD/commit/060d943d86bb6a79726065aad397723a9c704ea4

Para producir ese compromiso, hice lo que la mayoría de los desarrolladores de [git] están familiarizados:

  1. vi LICENCIA
  2. Shift-G # ir al final del file
  3. dd # borrar la línea actual
  4. ZZ # save file y salir
  5. git diff # diff muestra la eliminación de la nueva línea final NOTA: diff no muestra un cambio en $ FrauBSD $ value [yet]
  6. git agregar LICENCIA
  7. git diff # nada (sin cambios no registrados)
  8. git diff –cached # diff muestra la eliminación de la nueva línea final NOTA: diff [todavía] no muestra un cambio en $ FrauBSD $ value
  9. El estado # de git muestra LICENCIA modificada
  10. git commit # $ EDITOR aparece
  11. Ctrl-Z # pone $ EDITOR en el background para que podamos investigar
  12. git diff –cached # diff [now] muestra $ FrauBSD $ update así como la eliminación de la nueva línea final
  13. fg # resume $ EDITOR
  14. : q! # quit Editor sin cambios NOTA: Debido a que abortó la confirmación, $ FrauBSD $ se revirtió
  15. git diff –cached # diff [again] muestra solo la eliminación de la línea nueva
  16. git commit # esta vez no abortaremos
  17. BumpZZ # Insertar "Bump", save y salir
  18. El file está comprometido como está

NOTA: No es necesario hacer nada en el file post-commit

Eso es porque tengo los siguientes files en mi proyecto:

  • .git / hooks / pre-commit (enlace simbólico a ../../.hooks/pre-commit)
  • .git / hooks / commit-msg (enlace simbólico a ../../.hooks/commit-msg)
  • .hooks / pre-commit
  • .hooks / commit-msg
  • .filters / fraubsd-keywords

Las revisiones iniciales que puede get aquí:

"Agregar ganchos / filters para precomstackr manchas"

https://github.com/freebsdfrau/FrauBSD/commit/63fa0edf40fe8f5936673cb9f3e3ed0514d33673

NOTA: Los filters son utilizados por los ganchos (no se usan en git-attributes).

Y una actualización aquí:

https – // github.com/freebsdfrau/FrauBSD/commit/b0a0a6c7b2686db2e8cdfb7253aba7e4d7617432

O puede ver las revisiones principales aquí:

https – // github.com/freebsdfrau/FrauBSD/tree/master/.filters

https – // github.com/freebsdfrau/FrauBSD/tree/master/.hooks

NOTA: los dos puntos cambiaron a – en las URL anteriores para poder publicar más de 2 enlaces (ya que la reputación es baja)

Disfruta, FreeBSDFrau

OK, inspirado por la respuesta de Jon Cairns, se me ocurrió este pequeño fragment que podrías poner en tu Makefile.

 version.h: git log -n 1 --format=format:"#define GIT_COMMIT \"%h\"%n" HEAD > $@ 

No es una solución completamente general, pero podría ser útil. Conozco un lugar o dos donde lo usaré.

Estaba buscando algo similar, en el sentido de que quería una variable única que pudiera agregar al final de los files de resources (como CSS / JS) en nuestra interfaz, lo que nos permitiría establecer times de caching muy largos para networkingucir el ancho de banda y boost performance, pero fácilmente forzarlos a volver a cargarse después de cualquier confirmación. Esencialmente el control de versiones de files pero totalmente automatizado. No me importó que fuera el MÁS reciente, siempre que fuera único, automatizado y consistente en todos nuestros serveres de aplicaciones.

Nuestro script de deployment solo usa 'git clone' para desplegar una copy del código más reciente en nuestros serveres de aplicaciones, pero restringimos el acceso a través de .htaccess a esos files y directorys.

El directory /.git/ contiene un file llamado ORIG_HEAD que se actualiza después de cualquier combinación (o cualquier otra operación peligrosa ) con el ID de confirmación de su pnetworkingecesor. Dado que usamos gitflow, esto es perfecto porque se actualiza cada vez que presionamos una release o una fix a la twig principal y lo implementamos.

Puedes hacer esto, estoy asumiendo en cualquier lenguaje de scripting, pero en nuestro caso, PHP, lo hice así …

 define("MY_VERSION",substr(file_get_contents(realpath(__DIR__.'/../.git/ORIG_HEAD')),0,3)); 

Obviamente, su ruta debe ser ajustada para sus propios fines, pero esto da como resultado una id. Única de 3 char para nuestros propósitos que ahora se agrega al final de nuestra URL de resources.

Espero que ayude a alguien en la misma situación.

Estaba buscando una respuesta a esta pregunta. La Id. De compromiso ya está escrita en un file, solo tiene que saber dónde searchla. Después de realizar una confirmación en la twig principal, puede encontrar el hash de confirmación en ./.git/refs/heads/master De modo que en nuestra solución de entrega continua (descarga la carpeta .git junto con el código fuente) simplemente podemos cat ./.git/refs/heads/${BRANCH} para asociar el hash de confirmación actual con nuestra compilation