Comment puis-je remplir l'ID git commit dans un fichier lorsque je commets?
je voudrais créer git hook (s) qui remplira l'id de propagation de la propagation que je suis sur le point de faire dans un fichier (essentiellement la substitution de variables) dans mon code source. Est-ce possible avec Git? Ou est le fait qu'en résolvant la variable à l'id git, je vais changer le sha 1, se terminant ainsi avec un problème "poulet ou l'œuf".
9 réponses
la solution que j'ai utilisée pour une situation similaire est celle-ci:
- Mettre la chaîne
$Id$
quelque part dans le fichier que vous voulez avoir identifié (par exemple,test.html
), probablement dans un commentaire ou une autre section non fonctionnelle du fichier où il ne causera pas de problèmes. - Dans votre
.gitattributes
, marquez le fichier en question avec leident
mot clé (par exemple,*.html ident
).
Le résultat de cela est que lorsque git checkout
copie le fichier de l'objet base de données dans votre répertoire de travail, il étend le $Id$
chaîne de caractères à lire $Id: <sha-1 of file>$
et git add
inverse cette transformation quand vous voulez la Vérifier, donc les versions de ce fichier dans votre base de données d'objets ne contiennent que $Id$
, pas les formulaires élargis.
C'est un début, mais malheureusement, trouver le commit qui contient un fichier avec un hash n'est pas si facile, et pas nécessairement un-à-un. Donc, en plus, j'étiquette aussi ces fichiers avec le export-subst
attribut (par exemple,*.html ident export-subst
.gitattributes
), et ajouter une chaîne supplémentaire, comme $Format:%ci$ ($Format:%h$)
quelque part dans le fichier.
git checkout
et git add
n'affecte pas ces balises, donc les versions de mon dépôt ont toujours exactement cette chaîne. Pour obtenir ces balises étendues, vous devez utiliser git archive
pour créer une boule de goudron (or .zip) d'une version spécifique de votre projet, que vous utilisez ensuite pour déployer cette version - vous ne pourrez pas simplement copier les fichiers, ou make install
ou quoi que, depuis git archive
est la seule chose qui permettra d'élargir ces balises.
les deux balises que j'ai données comme exemple s'étendent à YYYY-MM-DD HH:MM:SS +TZOFFSET (HASH)
HASH
dans ce cas est le hachage de propagation réel, donc c'est plus utile.
Vous pouvez trouver d'autres potentiellement utile $Format:$
prescripteurs dans le git log
Page d'aide sous le --pretty-format
les prescripteurs.
vous pouvez créer un filtre qui effectue la substitution des fichiers sur commit et checkout. Ces filtres sont appelés "smudge" et "clean" et leur fonctionnement est contrôlé par .gitattributes
. Par exemple:
*.c filter=yourfilter
Ceci indique à git de lancer le yourfilter
filtre pour tous .c
fichiers. Vous devez alors dire à git ce que yourfilter
signifie:
git config --global filter.yourfilter.clean script1
git config --global filter.yourfilter.smudge script2
vous écririez alors un script (sed, Perl, Python, ou autre) pour remplacer une expression comme $LastSha$
$LastSha: <sha>$
à la caisse ("bavure"). L'autre script inverse l'extension avant commit ("clean").)
Rechercher dans le Pro Git livre pour "Keyword Expansion" pour un exemple détaillé.
il est impossible de faire ce que vous voulez: le hachage SHA-1 de la propagation est calculé sur l'ensemble du dépôt d'instantanés, y compris chaque fichier membre, donc il y a le problème du poulet et de l'œuf - pour calculer le hachage de la propagation, vous devez connaître le contenu de tous les fichiers qui le composent.
vous pouvez le faire avec le post-commit
crochet. Voici un extrait de git-scm site web
une fois le processus de propagation terminé, le crochet post-propagation s'exécute. Il ne prend aucun paramètre, mais vous pouvez facilement obtenir la dernière propagation en exécutant la tête git log -1. En général, ce script est utilisé pour la notification ou quelque chose de similaire.
il s'agirait d'obtenir la sortie de git log -1 HEAD
, puis en utilisant un outil comme sed
pour remplacer les variables dans votre fichier. Cependant, cela modifie votre répertoire de travail, et à moins que vous n'alliez jeter ces changements, alors vous finiriez avec un répertoire de travail modifié de façon permanente.
si vous voulez juste utiliser le hachage de propagation courant dans une variable quelque part dans votre code, vous pouvez juste exécuter git log -1 HEAD
ou cat .git/HEAD
et stockez la sortie dans votre variable
si vous voulez seulement l'id (hash) comme dans le titre de la question, vous pouvez utiliser le --format
drapeau. git log -1 HEAD --format=%H
OK, inspiré par la réponse de Jon Cairns, j'ai trouvé ce petit morceau que vous pourriez mettre dans votre Makefile.
version.h:
git log -n 1 --format=format:"#define GIT_COMMIT \"%h\"%n" HEAD > $@
ce n'est pas une solution tout à fait générale, mais elle pourrait s'avérer utile. Je connais un ou deux endroits où je l'utiliserai.
la clé ici est de mettre votre identifiant de révision dans un fichier dont Git ne se soucie pas. Voici un fragment d'un de mes projets:
. . . AssemblyCS="Properties/AssemblyInfo.cs" rev="$(git log -n 1 --date=short --format=format:"rev.%ad.%h" HEAD)" sed "$AssemblyCS" . . .
ce script est exécuté dans le cadre de mon processus de compilation (il peut aussi s'agir d'un hook post-commit). Dans ce cas Properties/AssemblyInfo.cs
.gitignore
alors que Properties/AssemblyInfo.cs.in
est sous contrôle de version. La construction utilise le .cs
filewh qui inclut un identifiant de révision qui se retrouve dans l'exécutable déployé.
comme d'autres l'ont mentionné, vous ne pouvez pas mettre le SHA-1 d'un commit lui-même dans le fichier pendant le même commit. Cela serait d'une utilité limitée de toute façon puisque en regardant deux fichiers que vous ne seriez pas immédiatement en mesure de dire ce qui est plus récent.
cela étant dit, il y a en fait un moyen de mettre automatiquement les informations de suivi de version dans les fichiers engagés. J'ai fait cela pour mon projet actuel (FrauBSD; une version de FreeBSD sur laquelle je travaille).
je l'ai réalisé sans l'aide d'un git-attributs de filtre. Alors que les filtres git-attributes permettent d'obtenir facilement le contraire (mettre l'information dans le ou les fichiers sur la commande), ce que je voulais était d'étendre certains mots-clés au moment de la propagation afin que les données soient dans le dépôt(par exemple, après un "git push origin master", github montre des valeurs étendues dans le ou les fichiers engagés). La réalisation de ce dernier s'est avérée extrêmement difficile avec un filtre git-attributs précisément parce qu'un simple" diff git " invoquera le filtre.propre attribut et, comme c'était le cas dans mon cas, si vous mettez des informations de date/heure dans l'extension, avoir la valeur change chaque fois que vous effectuez "git diff" est indésirable et inacceptable.
J'ai donc développé un crochet pre-commit et un crochet commit-msg qui, en agissant ensemble, résolvent le problème de savoir comment (spécifiquement dans le cas de FrauBSD) remplacer ce qui suit dans les fichiers engagés:
$FrauBSD$
avec quelque chose de similaire à ce qui suit avant l'enregistrement (les valeurs élargies vont en amont pour que les autres aillent à la caisse):
$FrauBSD: filepath AAAA-MM-JJ HH: MM: ZZ GMTOFFSET committer $
lorsque quelqu'un parcourt le fichier sur github ou effectue une vérification ou une fusion du(des) fichier (s), l'information étendue suit son cours.
NOTE: la valeur augmentée ne changera jamais sauf s'il y a un autre changement (non lié) qui accompagne, respectivement.
par exemple, voir la commit suivante dans laquelle je supprimer une nouvelle ligne d'un fichier. Le fichier commit contient à la fois la suppression de la nouvelle ligne de départ et une majoration de la date/heure dans le mot-clé $FrauBSD$:
https://github.com/freebsdfrau/FrauBSD/commit/060d943d86bb6a79726065aad397723a9c704ea4
Pour produire ce commit, j'ai fait ce que la plupart des [git] les développeurs sont familiarisés avec:
- licence vi
- Maj-G # aller à la fin du fichier
- dd # supprimer l'actuel ligne
- ZZ # enregistrez le fichier et quittez
- git diff # diff illustre le retrait de fuite de saut de ligne NOTE: diff does afficher un changement à $FrauBSD$ value [yet]
- git add LICENSE
- git diff # rien (pas de unstaged modifications)
- git diff --cached # diff illustre le retrait de fuite de saut de ligne NOTE: diff [encore] afficher un changement à la valeur $FrauBSD$
- git status # montre modifié Licence
- git commit # $ÉDITEUR vient
- Ctrl-Z # $RÉDACTEUR en arrière-plan, afin que nous puissions enquêter
- git diff --cached # diff [maintenant] montre $FrauBSD$ mise à jour ainsi que l'enlèvement de fuite de retour à la ligne
- fg # resume $ EDITOR
- : q! # quittez l'Éditeur sans modifications NOTE: parce que vous avez avorté le commit, $FrauBSD$ a été inversé
- git diff --cached # diff [nouveau] montre seulement de fuite de saut de ligne retrait
- git commit # cette fois, nous n'avortent pas
- BumpZZ # Insérer "Bosse", enregistrer et quitter
- le Fichier est engagé en tant que-est
REMARQUE: Rien ne doit être fait pour le fichier post-commit
C'est parce que j'ai les fichiers suivants dans mon projet:
- .git/hooks / pre-commit (lien symbolique vers ../../.crochets/pre-commit)
- .git/hooks / commit-msg (lien symbolique vers ../../.crochets/commit-msg)
- .crochets/pre-commit
- .crochets/commit-msg
- .filtres/fraubsd de mots-clés
La première révisions de laquelle vous pouvez obtenir ici:
"Ajouter des crochets/filtres de pré-commettre des bavures"
https://github.com/freebsdfrau/FrauBSD/commit/63fa0edf40fe8f5936673cb9f3e3ed0514d33673
NOTE: les filtres sont utilisés par les crochets (non utilisés dans git-attributs).
Et une mise à jour ici:
https-//github.com/freebsdfrau/FrauBSD/commit/b0a0a6c7b2686db2e8cdfb7253aba7e4d7617432
Ou vous pouvez voir la tête des révisions ici:
https - / github.com / freebsdfrau/FrauBSD/tree/master/.filtres
https - / github.com / freebsdfrau/FrauBSD/tree/master/.hooks
NOTE: colon modifié à-dans les URLs ci-dessus afin que je puisse poster plus de 2 liens (puisque la réputation est faible)
Profitez de, FreeBSDFrau
je cherchais quelque chose de similaire, en ce que je voulais une variable unique que je pourrais ajouter à la fin des fichiers de ressources (comme CSS/JS) dans notre face avant, ce qui nous permettrait de définir des temps de cache Très longs pour réduire la bande passante et augmenter les performances, mais les forcer facilement à être rechargés après n'importe quelle propagation. Essentiellement versioning fichier, mais totalement automatisé. Je m'en fichais que ce soit le MOST récente, tant qu'il était unique, automatisé, et cohérentes sur l'ensemble de notre application serveur.
notre script de déploiement utilise simplement "git clone" pour extraire une copie du code le plus récent dans nos serveurs app, mais nous restreignons l'accès via .htaccess pour les fichiers et les répertoires.
/.git/
répertoire contient un fichier appelé ORIG_HEAD
qui est mis à jour après toute fusion (ou toute autre dangereux opération) avec le numéro D'identification de son prédécesseur. Puisque nous utilisons git flow, c'est parfait car il met à jour chaque fois que nous poussons un release
ou fix
maître branche et à déployer.
vous pouvez le faire je suppose dans n'importe quel langage de script mais dans notre cas, PHP, Je l'ai fait comme ça...
define("MY_VERSION",substr(file_get_contents(realpath(__DIR__.'/../.git/ORIG_HEAD')),0,3));
votre chemin devrait évidemment être modifié pour vos propres besoins, mais cela se traduit par un 3 char assez unique id pour nos fins, qui est ajoutée à la fin de notre URL de ressource est maintenant.
espoir qui aide quelqu'un dans la même situation.
cat ./.git/refs/heads/${BRANCH}
pour associer le hash de commit actuel avec notre build