Faire git auto-commit

155

Je voudrais utiliser git pour enregistrer toutes les modifications dans un fichier.

Existe-t-il un moyen d'activer git 'commit' pour qu'il se produise automatiquement chaque fois qu'un fichier est mis à jour - il y a donc un nouveau commit pour chaque modification d'un fichier?

Idéalement, j'aimerais que mes utilisateurs ne sachent même pas que git fonctionne dans les coulisses. Un utilisateur pourrait alors potentiellement «annuler» les modifications d'un fichier - et cela pourrait être réalisé en retirant une version précédente de git.

git-noob
la source
9
Il serait plus facile d'utiliser un système de fichiers de contrôle de
William Pursell
1
SparkleShare était assez impressionnant à ce sujet.
theode
SparkleShare semble être une excellente option, mais il détruit tout dossier .git dans le git principal
insigne
Vous pouvez utiliser github.com/jw0k/gwatch . Cela fonctionne sous Windows et Linux.
rubix_addict
@rubix_addict Pourquoi n'avez-vous pas posté cela comme réponse?
Tobias Kienzler

Réponses:

127

Sous Linux, vous pouvez utiliser inotifywait pour exécuter automatiquement une commande chaque fois que le contenu d'un fichier est modifié.

Edit: la commande suivante valide le fichier.txt dès son enregistrement:

inotifywait -q -m -e CLOSE_WRITE --format="git commit -m 'autocommit on change' %w" file.txt | sh
JesperE
la source
2
Comment pouvez-vous faire cela pour un dossier entier (pas seulement un seul fichier?)
Anderson Green
2
Utilisez l' -rindicateur pour inotifywait, mais notez que le noyau a une limite sur le nombre de montres inotifywait qu'il peut configurer. man inotifywaitvous en dira plus.
JesperE
14
y a-t-il une option dans Windows ..?
Chandan Pasunoori
50

La réponse précédente inotifywait est excellente, mais ce n'est pas une solution tout à fait complète. Tel qu'il est écrit, il s'agit d'une validation unique pour un changement unique dans un fichier. Cela ne fonctionne pas dans le cas courant où la modification d'un fichier crée un nouvel inode avec le nom d'origine. inotifywait -m suit apparemment les fichiers par inode, pas par nom. De plus, une fois que le fichier a été modifié, il n'est pas préparé pour git commit sans git add ou git commit -a . En faisant quelques ajustements, voici ce que j'utilise sur Debian pour suivre toutes les modifications apportées à mon fichier de calendrier:

/etc/rc.local:


su -c /home/<username>/bin/gitwait -l <username>

/ home / <nom d'utilisateur> / bin / gitwait:


#!/bin/bash
#
# gitwait - watch file and git commit all changes as they happen
#

while true; do

  inotifywait -qq -e CLOSE_WRITE ~/.calendar/calendar

  cd ~/.calendar; git commit -a -m 'autocommit on change'

done

Cela pourrait être généralisé pour attendre une liste de fichiers et / ou répertoires, et les processus inotifywait correspondants , et redémarrer chaque inotifywait lorsqu'un fichier est modifié.

Lester Buck
la source
8
Lester pourriez-vous expliquer comment généraliser cela à un annuaire?
Diego
29

Les réponses précédentes recommandant inotifywait pour ce travail m'ont orienté dans la bonne direction lorsque j'avais moi-même ce problème, alors j'ai écrit un petit script. Premièrement, cela ne pouvait regarder que des dossiers entiers de manière récursive (le contraire de l'exemple de Lester Buck), mais ensuite je voulais aussi regarder un fichier ailleurs, alors je l'ai développé.

Le résultat est un script actuellement appelé gitwatch, car c'est ce qu'il fait: il regarde un fichier ou un dossier pour les changements (en utilisant inotifywait), et les valide dans un référentiel git.

Vous pouvez trouver le script, plus d'informations et des instructions sur github: https://github.com/nevik/gitwatch

Nevik Rehnel
la source
4
petit script utile là-bas. Je vais en prendre note.
iwein
intéressant pourrait être utile pour les sites magento. Je le teste mais je n'arrive pas à le faire pousser automatiquement
NoSixties
16

git-wip est une excellente solution qui fonctionne bien pour moi. «WIP» signifie «travail en cours». Chaque fois que vous exécutez 'git wip', les modifications sont validées dans une branche distincte. Il peut être exécuté sur la ligne de commande, mais il existe des extensions pour vim et emacs pour exécuter automatiquement git-wip à chaque fois qu'un fichier est écrit.

rafak
la source
12

Je voulais faire cela dans Windows et j'ai trouvé que le meilleur moyen était d'utiliser Directory Monitor pour vérifier les changements, puis quand il a détecté un changement, exécutez-le:

Programme: cmd.exe

Paramètres: /CC:\pathToBatchFile.bat

Ce fichier de commandes contenait:

c:
cd c:\gitRepoDirectory\
(if exist "%PROGRAMFILES(X86)%" (
"%PROGRAMFILES(X86)%\git\bin\sh.exe" --login -i -c "git commit -am AutoCommitMessage"
) else (
"%PROGRAMFILES%\git\bin\sh.exe" --login -i -c "git commit -am AutoCommitMessage"
))

J'ai également essayé d'avoir une autre commande pour ajouter des fichiers ( "%PROGRAMFILES(X86)%\git\bin\sh.exe" --login -i -c "git add *.*"), mais je ne pense pas que cela fonctionne correctement.

J'ai également créé un hook post-commit contenant:

#!/bin/sh
git.exe pull -v --progress  "origin"
git.exe push    --progress  "origin" master:master
curl.exe -s https://webserverdomain.com/updateFromGitHook.x?r=repoName

(S'il y avait des conflits, cela abandonnerait le pull et le push, mais il n'y avait pas de moyen clair de dire que cela s'était produit - à la fin, nous avons abandonné toute l'idée à cause de ce seul défaut.)

Cette commande curl a indiqué à mon serveur qu'il avait besoin de tirer sur le code. Tout ce qui était nécessaire pour le gérer en php était:

<?
$r = $_GET['r'];
if (!empty($c)) {
    //use system instead of exec if you want the output to go back to the git client
    exec("cd /path/to/repo/parent/$r; sudo git reset --hard HEAD; sudo git pull;");
    echo "\n\nServer: Updated\n\n";
} else {
    echo "\n\nServer: UPDATE FAILED\n\n";
}
?>

Le seul problème avec cela était qu'il devait être exécuté par l'utilisateur root au lieu de l'utilisateur apache, donc j'ai également dû créer un fichier /etc/sudoers.d/contenant:

www-data ALL = NOPASSWD: /usr/bin/git

Pour moi, je pense que cela a fonctionné assez solidement. Directory Monitor peut être configuré pour s'exécuter au démarrage et démarrer minimisé, et il peut surveiller plusieurs dossiers différents

Redzarf
la source
Aussi sous Windows, je ne peux pas faire fonctionner git sous LocalSystem, donc si vous créez votre propre service de surveillance, vous devrez l'exécuter sous un utilisateur qui peut réellement exécuter Git. Il se peut que je manque juste quelques paramètres / config, mais il est probablement plus agréable de configurer un nouveau compte git commit de toute façon
Whelkaholism
8
#!/bin/bash
git commit -a -m "autoupdate `date +%F-%T`"
git push

autopushing avec la date et l'heure actuelles.

web-rider
la source
8

Inotify semble vraiment être le bon outil pour le travail.

Il existe un outil appelé incron qui pourrait être exactement ce que vous recherchez. Vous pouvez spécifier des fichiers ou des dossiers (et des types d'événement, comme «modifier», «créer», «dissocier») dans quelque chose comme un crontab, et une commande à exécuter lorsqu'un tel événement se produit.

Contrairement à inotifywait (qui serait l'analogue du cron du pauvre sleep 10;do stuff), cela captera tous les événements, pas seulement le premier.

Je ne l'ai pas utilisé moi-même, mais d'après la documentation, il ne semble pas trop complexe à configurer.

pixelbrei
la source
7

J'ai écrit un programme, GitPrime , pour fournir une sauvegarde automatique pour vos dépôts Git locaux. Maintenant, il est facile de revenir avant de le casser! Dépôt Bitbucket .

Cela devrait fonctionner sur toute plate-forme prenant en charge un shell bash, y compris Windows + Cygwin.

Brendan
la source
+1 J'utilise ceci sur Windows (CygWin) pour enregistrer automatiquement les modifications que je fais dans un référentiel git-tf toutes les 10 minutes en utilisant une tâche planifiée
Darbio
6

Au cas où quelqu'un essaie de le faire à partir de Powershell, j'ai réussi à utiliser ce qui suit:

& "C:\Program Files (x86)\Git\bin\sh.exe" -c "cd D:\PATH\TO\REPO && git add --all  &&  git commit -m 'Automatic Commit Message Goes Here' && git push origin master"
mekuls
la source
5
Et comment cela se déclenche-t-il automatiquement?
jerik
2
tâche planifiée?
ozzy432836
2

Si vous connaissez le nom du fichier et que vous voulez surveiller un seul (ou quelques fichiers), vous pouvez simplement appeler "git commit" toutes les quelques minutes pour y parvenir. Si le fichier n'a pas changé, git se plaindra simplement et vous devrez ignorer cette erreur, mais à part cela, il n'y aura pas de corruption.

En plus de cela, vous voudrez marquer ces fichiers comme "validation automatique" afin de pouvoir également valider manuellement. De cette façon, l'utilisateur peut voir les changements automatiques et aussi les plus gros changements "logiques" qui sont accompagnés de commentaires de commit pour expliquer ce qui a changé depuis le dernier commit manuel.

Par exemple, utilisez "AUTOCOMMIT" comme message de validation. Plus tard, vous pouvez écrire un outil pour purger ces commits en utilisant git log (pour trouver les révisions à tuer) ou vous pouvez essayer de créer une branche AUTOCOMMIT en utilisant une stratégie de résolution de collision par force brute pour marteler les "commits manuels".

Une autre option consiste à utiliser les commandes de bas niveau git pour créer votre propre référentiel spécialisé.

Enfin, vous pouvez copier le fichier sous un nouveau nom ("$ filename.ac") tout en faisant des validations automatiques pour faire la distinction entre les versions manuelle et automatique.

Aaron Digulla
la source
1

Je suis presque sûr que vous aurez besoin de l'intégrer à l'éditeur que vos utilisateurs utilisent. Vous pouvez écrire quelque chose pour interroger les modifications, mais en fonction des modèles d'utilisation, la fréquence d'interrogation peut devoir être incroyablement élevée pour s'assurer qu'elle prend en compte les modifications individuelles au lieu de plusieurs modifications.

Hank Gay
la source
En outre, la recherche de modifications créera des conditions de concurrence.
Bombe
1
Pas avec des éditeurs comme emacs et yi, qui écrivent des fichiers "transactionnellement" pour essayer de s'assurer que les données ne seront pas perdues après un crash.
Robin Green
1

On dirait que vous cherchez quelque chose de similaire à etckeeper , qui est conçu pour vérifier automatiquement tous vos changements de / etc / * dans git (ou quel que soit le VCS que vous voulez), mais je ne vois aucune raison pour laquelle il ne pourrait pas être utilisé avec des fichiers autres que ceux de / etc.

Si vous ne voulez traiter qu'un seul fichier, ce ne serait peut-être pas parfait, mais si vous voulez garder une trace de tout dans un répertoire donné, je pense que cela vaut la peine de vérifier.

iconoclaste
la source
1

Ce script ne s'exécute pas lorsqu'un utilisateur modifie le fichier, mais il pourrait être exécuté en tant que tâche cron (en le déposant dans un répertoire /etc/cron.*), ce qui est également une solution raisonnable.

Ce script itérera dans votre répertoire / srv / www (changez-le à l'endroit où tous vos sites sont stockés), ajoutera, validera et poussera tous les fichiers, et consignera tout dans /var/log/gitlog.txt

now=$(date +"%m.%d.%Y_%T")
logfile='/var/log/gitlog.txt'

for dir in /srv/www/*/
do
echo -e '\n' >> $logfile
echo "autocommit $dir $now" >> $logfile
echo "--------------------------" >> $logfile

cd $dir
git add . >> $logfile
git commit -am "autocommit $now" >> $logfile
git push origin master >> $logfile
done
plantes grimpantes
la source
0

J'ai eu le même problème et sur mac, launchd vous offre une excellente solution. il surveillera un fichier ou un répertoire et s'il y a des changements, vous pouvez exécuter une application ou autre chose ...


la source
Voir «Surveillance d'un répertoire» ici: developer.apple.com/library/mac/#documentation/MacOSX/…
Kris
0

Cela ne satisfait pas la partie «Idéalement» de la question, mais c'était la question la plus proche que j'ai vue de la réponse que je voulais, alors j'ai pensé qu'elle pouvait aller ici. Mon premier post de stackoverflow cependant, alors excuses si je me trompe.

Le script suivant permet commits automatique sur les changements enregistrés, mais ne invite l'utilisateur pour une validation d' entrée. (Je réalise que mon scénario est un peu différent de celui de git-noob).


# While running, monitors the specified directory, and when a file therein 
# is created or edited and saved, this prompts the user for a commit message.
# The --exclude is to avoid extra prompts for the changes made to 
# version control directories.

# requires inotify-tools

inotifywait --exclude '/\..+' -m  path/to/directory -e modify -e create |
        while read path action file; do
                gnome-terminal -e 'bash -c "cd path/to/directory; 
                                            git add *; 
                                            echo What did you just do??; 
                                            read varname; 
                                            git commit -m \"$varname\""'
        done
Fintan
la source
0

Pour les fenêtres

Selon cet article sur l'autocommit , vous devez créer un .batfichier avec du contenu:

git add -u
git commit -m "your commit message"
git push origin master 

et exécutez avec Task Scheduler. Si vous ne savez pas comment procéder étape par étape, reportez-vous à cet article.

T.Todua
la source