J'aimerais ajouter un fichier généré automatiquement au même commit en utilisant un hook pré-ou post-commit dans Git, en fonction des fichiers modifiés dans ce commit. Comment pourrais-je m'y prendre?
J'ai essayé cela comme un crochet de pré-commit, mais pas de chance:
#!/bin/sh
files=`git diff --cached --name-status`
re="<files of importance>"
if [[ $files =~ $re ]]
then
echo "Creating files"
exec bundle exec create_my_files
exec git add my_files
exec git commit --amend -C HEAD
fi
Cela les ajoute avec succès au référentiel, mais ne les ajoute pas à la validation. J'ai également essayé d'utiliser les deux dernières lignes d'exécution dans un hook post-commit avec l'inspection pré-commit, mais ce n'est pas bon non plus.
Comme git add ne fonctionnait pas non plus pour moi dans un pré-commit, j'ai suivi l'idée de mark d'utiliser un fichier .commit et de scinder le processus en pré-et post-commit.
Voici un code qui devrait être facile à comprendre
Dans le pré-commit:
- Touchez un fichier .commit ou quelque chose. (assurez-vous d'ajouter ceci à .gitignore)
#!/bin/sh
echo
touch .commit
exit
Dans le post-commit:
si .commit existe, vous savez qu'un commit vient d'avoir lieu mais un post-commit n'a pas encore été lancé. Donc, vous pouvez faire votre génération de code ici . En outre, testez pour .commit et s'il existe:
- ajouter les fichiers
- commit --amend -C HEAD --no-verify (évite les boucles)
- supprimer le fichier .commit
#!/bin/sh
echo
if [ -a .commit ]
then
rm .commit
git add yourfile
git commit --amend -C HEAD --no-verify
fi
exit
J'espère que cela facilitera le suivi de l'idée de Mark pour les personnes disposant de peu de connaissances élémentaires.
Il est possible de faire ce que vous voulez en utilisant des hooks de pré-commit. Nous faisons quelque chose de similaire pour un déploiement de heroku (compiler coffeescript en javascript). Votre script ne fonctionne pas parce que vous avez utilisé la commande exec
de manière incorrecte.
De la page de manuel :
La fonction intégrée exec est utilisée pour remplacer l’image de processus shells en cours d’exécution par une nouvelle commande. En cas de succès, exec ne revient jamais. exec ne peut pas être utilisé dans un pipeline.
Seule votre première commande exec est en cours d'exécution. Après cela, votre script est pratiquement terminé.
Essayez quelque chose comme ceci (en tant que hook pré-commit):
#!/bin/sh
files=`git diff --cached --name-status`
re="<files of importance>"
if [[ $files =~ $re ]]
then
echo "Creating files"
bundle exec create_my_files
git add my_files
fi
Vous pouvez utiliser une combinaison de script avant et après validation.
Dans le pré-commit:
Dans le post-commit:
si .commit existe, vous savez qu'un commit vient de se produire, mais aucun post-commit n'a encore été exécuté. Donc, vous pouvez faire votre génération de code ici. En outre, testez pour .commit et s'il existe:
C’est à peu près le processus que j’utilise pour stocker un fichier .metadata dans le référentiel généré à partir de metastore.
Si quelqu'un connaît un meilleur moyen, je suis tout ouïe mais cela semble fonctionner pour le moment.
#!/bin/sh
#
# .git/hooks/pre-commit
#
git add file.xyz
Cela a bien fonctionné pour moi. Cela fera partie du commit actuel.
git version 1.7.12.4 (Apple Git-37)
Vous pouvez utiliser update-index
:
git update-index --add my_files
Pourquoi ne pas écrire un script post-commit
à la place qui génère vos fichiers, puis avoir that do (quelque chose dans les lignes de) git add my_files; git commit --amend
.
Si les fichiers sont générés automatiquement et qu'ils peuvent être générés n’importe où (ce qui est implicite dans votre volonté de les créer dans le hook pré-commit Git), vous ne devriez pas les placer sous contrôle de source. Vous ne devez contrôler que les fichiers source. Les fichiers générés doivent être générés dans le cadre des scripts de construction.
La seule raison de placer un fichier généré sous contrôle de source est lorsqu'il nécessite la génération de ressources uniques/privilégiées (telle qu'un logiciel sous licence) ou s'il nécessite un laps de temps considérable pour la générer.
Ajoutée
De http://git-scm.com/docs/githooks :
pre-commit Ce hook est appelé par git commit, et peut être contourné avec Option --no-verify. Il ne prend aucun paramètre et est appelé avant obtention du journal de validation proposé message et faire un commit. Sortie avec un statut non nul de ce script provoque le git commit à avorter.
Le hook de pré-validation par défaut, quand activé, capture l'introduction de lignes avec des espaces et des avortements à la fin le commit quand une telle ligne est trouvée.
Tous les hooks git commit sont appelés avec la variable d'environnement GIT_EDITOR =: si la commande ne va pas Ouvrez un éditeur pour modifier le fichier message de validation.
Le hook de pré-validation a pour objectif d'être une vérification échec-succès de l'état de l'espace de travail et du contenu de la validation, avant d'effectuer la validation. Tenter de modifier le contenu du commit ne fonctionnera pas.
Ma recommandation serait d’ajouter deux étapes à vos scripts de génération: (1) une étape qui construira tous les fichiers périmés à générer (et les ajoutera à l’espace de travail), et (2) une étape qui vérifiera que tous les fichiers générés sont à jour et renverra un code d'état différent de zéro. Votre hook pré-commit Git devrait exécuter la deuxième étape. Vos développeurs doivent être formés pour exécuter la première étape si nécessaire.
J'avais le même besoin et cette approche a plutôt bien fonctionné pour moi:
#!/bin/sh
files='git diff --cached --name-only'
re="<files of importance>"
if [[ $files =~ $re ]]
then
echo "Creating files"
create_my_files && git add my_files
fi
où "create_my_files" devrait être exécutable, par exemple, s'il s'agit d'un fichier python, vous pouvez l'exécuter en tant que "python create_my_files && git add_files"
et il est vrai que vous n'avez pas besoin d'un engagement préalable à nouveau (cela créerait une boucle infinie méchante: p)
Oui, vous pouvez ajouter des fichiers générés automatiquement sur le commit en utilisant git hooks! Mais cela nécessite un script compliqué.
Ici vous pouvez trouver le problème résolu. Là, il met à jour la version du fichier à chaque commit, ajoute un nouveau fichier modifié et modifie le commit à votre guise. Cela fonctionne pleinement: https://github.com/evandrocoan/.versioning
Ensuite, vous venez de remplacer l'algorithme 'Version File Replacement' sur le fichier 'updateVersion.sh', par votre algorithme. Peut-être devriez-vous changer quelques choses, par exemple, supprimer la limitation de branche, car le script ne s'exécutera que si vous vous trouvez dans la branche 'develop'.
De plus, cela ne changera que le fichier spécifié, s'il est mis en scène. Si le fichier n'est pas mis en scène, alors il ne fera rien que le commit normal/habituel. Plus précisément, il imprime ce qu’il fait à chaque étape.
Je vais expliquer, cette astuce. C'est assez délicat. Sur le prepare-commit-msg-hook, il détecte si le fichier souhaité est en cours de traitement et validé. Après cela, il crée un fichier d'indicateur et arrête le programme prepare-commit-msg-hook . Plus tard, il vérifie si le fichier d'indicateur existe. Si oui, cela modifie les fichiers du commit.
Attention, cela créerait une boucle infinie car cela ferait appel à nouveau à prepare-commit-msg-hook (comme nous le modifions). Mais cela ne se produit pas à cause du fichier de drapeau. Lorsque le programme prepare-commit-msg-hook est exécuté et trouve le fichier de drapeau, il "sait" ce qui se passe. Il suffit ensuite de supprimer le fichier indicateur et de ne pas le créer à nouveau. En le faisant, cela empêchera le hook post-commit de modifier à nouveau les commits, permettant ainsi à celui-ci de se terminer définitivement.