Fare git auto-commit

Mi piacerebbe usare git per registrare tutte le modifiche a un file.

C’è un modo in cui posso triggersre git ‘commit’ in modo che avvenga automaticamente ogni volta che un file viene aggiornato – quindi c’è un nuovo commit per ogni modifica a un file?

Idealmente, mi piacerebbe che i miei utenti non sapessero nemmeno che git funziona dietro le quinte. Un utente potrebbe quindi “annullare” le modifiche a un file, e ciò potrebbe essere ottenuto estraendo una versione precedente da git.

Su Linux è ansible utilizzare inotifywait per eseguire automaticamente un comando ogni volta che viene modificato il contenuto di un file.

Modifica: il comando seguente esegue il commit di file.txt non appena viene salvato:

inotifywait -q -m -e CLOSE_WRITE --format="git commit -m 'autocommit on change' %w" file.txt | sh 

La prima risposta inotifywait è ottima, ma non è una soluzione completa. Come scritto, è un commit one shot per una modifica una tantum in un file. Non funziona nel caso comune in cui la modifica di un file crea un nuovo inode con il nome originale. inotifywait -m apparentemente segue i file per inode, non per nome. Inoltre, dopo che il file è stato modificato, non viene messo in scena per il commit git senza git add o git commit -a . Apportando alcune modifiche, ecco cosa sto usando su Debian per tenere traccia di tutte le modifiche al mio file di calendario:

/etc/rc.local:

 su -c /home//bin/gitwait -l  

/ Home / / 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 

Questo potrebbe essere generalizzato per attendere un elenco di file e / o directory e i corrispondenti processi inotifywait e riavviare ogni inotifywait mentre un file viene modificato.

Le risposte precedenti che raccomandavano inotifywait per questo lavoro mi hanno dato la giusta direzione quando ho avuto questo problema da solo, quindi ho scritto un piccolo script. Prima, questo poteva solo guardare intere cartelle in modo ricorsivo (il contrario dell’esempio di Lester Buck), ma poi volevo anche guardare un file da qualche altra parte, quindi l’ho espanso.

Il risultato è uno script attualmente chiamato gitwatch , in quanto è ciò che fa: controlla un file o una cartella per le modifiche (usando inotifywait) e li impegna in un repository git.

Puoi trovare lo script, maggiori informazioni e istruzioni su github: https://github.com/nevik/gitwatch

git-wip è un’ottima soluzione che funziona bene per me. “WIP” sta per “work in progress”. Ogni volta che si esegue ‘git wip’, le modifiche vengono eseguite su un ramo separato. Può essere eseguito sulla riga di comando, ma ci sono estensioni per vim ed emacs per eseguire automaticamente git-wip ogni volta che un file viene scritto.

Volevo farlo in Windows, e ho trovato che il modo migliore era usare Directory Monitor per verificare le modifiche e quando ha rilevato che una modifica lo eseguiva:

Programma: cmd.exe

Params: /CC:\pathToBatchFile.bat

Il file batch conteneva:

 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" )) 

Ho anche provato ad avere un altro comando lì per aggiungere file ( "%PROGRAMFILES(X86)%\git\bin\sh.exe" --login -i -c "git add *.*" ), Ma non credo Ho funzionato correttamente.

Ho anche creato un hook post-commit contenente:

 #!/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 

(Se ci fossero stati conflitti allora abortirebbe il tiro e abortirebbe la spinta, ma non c’era un modo chiaro per dire che fosse successo – alla fine abbiamo abbandonato l’idea intera a causa di questo difetto.)

Quel comando di arricciatura diceva al mio server che era necessario eseguire un pull sul codice. Tutto ciò che era necessario per gestirlo in PHP era:

  

L’unico problema era che doveva essere eseguito dall’utente root invece che dall’utente apache, quindi dovevo anche creare un file in /etc/sudoers.d/ contenente:

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

Per quanto mi riguarda, penso che abbia funzionato abbastanza bene. Directory Monitor può essere configurato per essere eseguito all’avvio e avviato a livello ridotto e può controllare diverse cartelle

 #!/bin/bash git commit -a -m "autoupdate `date +%F-%T`" git push 

autopushing con data e ora correnti.

Inotify suona davvero come lo strumento giusto per il lavoro.

C’è uno strumento chiamato incron che potrebbe essere esattamente quello che stai cercando. È ansible specificare file o cartelle (e tipi di eventi, come “change”, “create”, “unlink”) in qualcosa come un crontab e un comando da eseguire quando si verifica tale evento.

In contrasto con inotifywait (che sarebbe l’analogo del cron sleep 10;do stuff del povero uomo sleep 10;do stuff ), questo catturerà ogni evento, non solo il primo.

Non l’ho usato da solo, ma dalla documentazione non sembra troppo complesso da configurare.

Ho scritto un programma, GitPrime , per fornire il salvataggio automatico per i repository Git locali. Ora è facile tornare indietro prima di averlo sballato! Repository Bitbucket .

Questo dovrebbe funzionare su qualsiasi piattaforma che supporti una shell bash che includa Windows + Cygwin.

Nel caso qualcuno provi a fare questo da Powershell ho avuto successo usando quanto segue:

 & "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" 

Se si conosce il nome del file e si desidera monitorare solo uno (o alcuni file), è sufficiente chiamare “git commit” ogni pochi minuti per ottenere ciò. Se il file non è cambiato, git si lamenterà e dovrai ignorare questo errore, ma a parte questo, non ci sarà corruzione.

Oltre a questo, ti consigliamo di contrassegnare questi file come “auto commit” per poter eseguire il commit manualmente. In questo modo, l’utente può vedere le modifiche automatiche e anche le più grandi modifiche “logiche” che sono accompagnate da commenti di commit per spiegare che è cambiato dall’ultimo commit manuale.

Ad esempio, utilizzare “AUTOCOMMIT” come messaggio di commit. In seguito, puoi scrivere uno strumento per eliminare questi commit usando git log (per scoprire le revisioni da uccidere) oppure puoi provare a creare un ramo AUTOCOMMIT usando una strategia di risoluzione delle collisioni forza bruta per eseguire il martellamento nei “commit manuali”.

Un’altra opzione è usare i comandi di basso livello git per creare il tuo repository specializzato.

Infine, è ansible copiare il file in un nuovo nome (“$ filename.ac”) mentre si esegue il commit automatico per distinguere tra le versioni manuale e automatica.

Sono abbastanza sicuro che avresti bisogno di collegarlo a qualsiasi editor utilizzi gli utenti. Potresti scrivere qualcosa per sondare le modifiche, ma a seconda dei modelli di utilizzo, la frequenza di polling potrebbe essere incredibilmente alta per essere sicura di raccogliere singole modifiche anziché più modifiche.

Ho avuto lo stesso problema e su Mac Launchd ti offre un’ottima soluzione. guarderà un file o una directory e se ci sono cambiamenti puoi eseguire un’app o qualsiasi altra cosa …

Sembra che tu stia cercando qualcosa di simile a etckeeper , che è progettato per controllare automaticamente tutti i tuoi changest in / etc / * in git (o qualsiasi altro VCS tu voglia), ma non vedo alcun motivo per cui non possa essere usato con i file diversi da quelli in / etc.

Se vuoi solo gestire un singolo file, forse non sarebbe perfetto, ma se vuoi tenere traccia di tutto in una determinata directory, penso che valga la pena di controllarlo.

Questo script non viene eseguito quando un utente modifica il file, ma può essere eseguito come cron job (rilasciandolo in una directory /etc/cron.*), che è anche una soluzione ragionevole.

Questo script eseguirà una iterazione nella directory / srv / www (cambiarlo in tutti i siti in cui sono memorizzati), aggiungere, eseguire il commit e spingere tutti i file e registrare tutto in /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 

Due soluzioni che mi piacciono sono etckeeper , che può essere adattato a una directory personalizzata diversa da /etc :

 mkdir /foo etckeeper -d /foo init` etckeeper -d /foo commit 'message' 

E gitwatch – specialmente le istruzioni su come usarlo con supervisord .