Hacer git auto-commit

155

Me gustaría usar git para registrar todos los cambios en un archivo.

¿Hay alguna manera de activar git 'commit' para que ocurra automáticamente cada vez que se actualiza un archivo, por lo que hay una nueva confirmación para cada cambio en un archivo?

Idealmente, me gustaría que mis usuarios ni siquiera supieran que git se está ejecutando detrás de escena. Un usuario podría potencialmente "deshacer" los cambios en un archivo, y esto podría lograrse sacando una versión anterior de git.

git-noob
fuente
9
Sería más fácil usar un sistema de archivos de versiones: en.wikipedia.org/wiki/Versioning_file_system
William Pursell
1
SparkleShare fue bastante impresionante en eso.
theode
SparkleShare parece una gran opción, pero destruye cualquier carpeta .git dentro del git principal
insign
Puede usar github.com/jw0k/gwatch . Funciona en Windows y Linux.
rubix_addict
@rubix_addict ¿Por qué no publicaste eso como respuesta?
Tobias Kienzler

Respuestas:

127

En Linux, puede usar inotifywait para ejecutar automáticamente un comando cada vez que se cambia el contenido de un archivo.

Editar: el siguiente comando confirma file.txt tan pronto como se guarda:

inotifywait -q -m -e CLOSE_WRITE --format="git commit -m 'autocommit on change' %w" file.txt | sh
JesperE
fuente
2
¿Cómo puede hacer que haga esto para una carpeta completa (no solo un archivo?)
Anderson Green
2
Use la -rbandera para inotifywait, pero tenga en cuenta que el núcleo tiene un límite en la cantidad de relojes inotifywait que puede configurar. man inotifywaitTe diré más.
JesperE
14
¿hay alguna opción en windows ..?
Chandan Pasunoori
50

La respuesta anterior de inotifywait es excelente, pero no es una solución completa. Como está escrito, es una confirmación de una sola vez para un cambio único en un archivo. No funciona para el caso común en el que editar un archivo crea un nuevo inodo con el nombre original. Inotifywait -m aparentemente sigue los archivos por inodo, no por nombre. Además, después de que el archivo ha cambiado, no está preparado para git commit sin git add o git commit -a . Haciendo algunos ajustes, esto es lo que estoy usando en Debian para seguir todos los cambios en mi archivo de calendario:

/etc/rc.local:


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

/ home / <nombre de usuario> / 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

Esto podría generalizarse para esperar en una lista de archivos y / o directorios, y los procesos de inotifywait correspondientes , y reiniciar cada inotifywait a medida que se cambia un archivo.

Lester Buck
fuente
8
Lester, ¿podría ampliar cómo generalizar esto a un directorio?
Diego
29

Las respuestas anteriores que recomendaban inotifywait para este trabajo me indicaron la dirección correcta cuando tuve este problema yo mismo, así que escribí un pequeño guión. Primero, esto solo podía ver carpetas enteras de forma recursiva (lo contrario del ejemplo de Lester Buck), pero luego también quería ver un archivo en otro lugar, así que lo expandí.

El resultado es un script llamado actualmente gitwatch, ya que eso es lo que hace: observa los cambios en un archivo o carpeta (usando inotifywait) y los confirma en un repositorio git.

Puede encontrar el script, más información e instrucciones en github: https://github.com/nevik/gitwatch

Nevik Rehnel
fuente
44
pequeño guión útil allí. Tomaré nota de ello.
iwein
interesante puede ser útil para sitios magento. Estoy probando, pero parece que no puede conseguirlo para empujar de forma automática, así
NoSixties
16

git-wip es una gran solución que me funciona bien. "WIP" significa "trabajo en progreso". Cada vez que ejecuta 'git wip', los cambios se confirman en una rama separada. Se puede ejecutar en la línea de comando, pero hay extensiones para que vim y emacs ejecuten automáticamente git-wip cada vez que se escribe un archivo.

rafak
fuente
12

Quería hacer esto en Windows, y encontré que la mejor manera era usar Directory Monitor para verificar los cambios y luego, cuando detectó un cambio, lo ejecuté:

Programa: cmd.exe

Parámetros: /CC:\pathToBatchFile.bat

Ese archivo por lotes contenía:

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

También intenté tener otro comando allí para agregar archivos ( "%PROGRAMFILES(X86)%\git\bin\sh.exe" --login -i -c "git add *.*"), pero no creo que haya funcionado correctamente.

También hice un gancho posterior a la confirmación que contiene:

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

(Si hubiera algún conflicto, entonces abortaría el tirón y el empuje, pero no había ninguna forma clara de saber que había sucedido; al final, abandonamos toda la idea debido a este defecto).

Ese comando curl le dijo a mi servidor que necesitaba hacer una extracción del código. Todo lo que se necesitaba para manejarlo en php era:

<?
$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";
}
?>

El único problema con eso era que tenía que ser ejecutado por el usuario root en lugar del usuario apache, por lo que también tuve que hacer un archivo que /etc/sudoers.d/contenga:

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

Para mí, creo que funcionó bastante bien. Directory Monitor se puede configurar para ejecutarse al inicio y comenzar minimizado, y puede ver varias carpetas diferentes

Redzarf
fuente
También en Windows, no puedo hacer que git se ejecute bajo LocalSystem, por lo que si crea su propio servicio de monitoreo, tendrá que ejecutarlo bajo un usuario que realmente pueda ejecutar Git. Posible, solo me faltan algunas configuraciones / configuración, pero probablemente sea mejor configurar una nueva cuenta git commit de todos modos
Whelkaholism,
8
#!/bin/bash
git commit -a -m "autoupdate `date +%F-%T`"
git push

autocompletado con fecha y hora actuales.

jinete web
fuente
8

Inotify realmente suena como la herramienta adecuada para el trabajo.

Hay una herramienta llamada incron que podría ser exactamente lo que estás buscando. Puede especificar archivos o carpetas (y tipos de eventos, como "cambiar", "crear", "desvincular") en algo así como un crontab y un comando que se ejecutará cuando ocurra tal evento.

A diferencia de inotifywait (que sería el análogo del cron del pobre sleep 10;do stuff), esto captará todos los eventos, no solo el primero.

No lo he usado yo mismo, pero desde la documentación no parece demasiado complejo de configurar.

pixelbrei
fuente
7

Escribí un programa, GitPrime , para proporcionar autoguardado para sus repositorios locales de Git. ¡Ahora es fácil retroceder antes de que lo revientes! Repositorio Bitbucket .

Esto debería funcionar en cualquier plataforma que admita un shell bash, incluido Windows + Cygwin.

Brendan
fuente
+1 Estoy usando esto en Windows (CygWin) para guardar automáticamente los cambios que hago en un repositorio git-tf cada 10 minutos usando una tarea programada
Darbio
6

En caso de que alguien intente hacer esto desde Powershell, tuve éxito usando lo siguiente:

& "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
fuente
55
¿Y cómo se desencadena esto automáticamente?
Jerik
2
¿tarea programada?
ozzy432836
2

Si conoce el nombre del archivo y desea monitorear solo uno (o algunos archivos), simplemente puede llamar "git commit" cada pocos minutos para lograr esto. Si el archivo no ha cambiado, git solo se quejará y tendrá que ignorar este error, pero aparte de eso, no habrá corrupción.

Además de eso, querrá marcar estos archivos como "confirmación automática" para poder confirmar también manualmente. De esta manera, el usuario puede ver los cambios automáticos y también los cambios "lógicos" más grandes que van acompañados de comentarios de confirmación para explicar que ha cambiado desde la última confirmación manual.

Por ejemplo, use "AUTOCOMMIT" como mensaje de confirmación. Más tarde, puede escribir una herramienta para purgar estas confirmaciones utilizando git log (para averiguar las revisiones a matar) o puede intentar crear una rama AUTOCOMMIT utilizando una estrategia de resolución de colisión de fuerza bruta para martillar en las "confirmaciones manuales".

Otra opción es usar los comandos de bajo nivel git para construir su propio repositorio especializado.

Por último, puede copiar el archivo a un nuevo nombre ("$ filename.ac") mientras realiza confirmaciones automáticas para distinguir entre las versiones manual y automática.

Aaron Digulla
fuente
1

Estoy bastante seguro de que necesitarás conectarlo al editor que estén usando tus usuarios. Podría escribir algo para sondear los cambios, pero dependiendo de los patrones de uso, la frecuencia de sondeo podría necesitar ser increíblemente alta para asegurarse de que estaba recogiendo cambios individuales en lugar de múltiples cambios.

Hank Gay
fuente
Además, la votación de los cambios creará condiciones de carrera.
Bombe
1
No con editores como emacs y yi, que escriben archivos "transaccionalmente" para tratar de garantizar que los datos no se pierdan después de un bloqueo.
Robin Green
1

Parece que está buscando algo similar a etckeeper , que está diseñado para verificar automáticamente todos sus cambios a / etc / * en git (o cualquier VCS que desee), pero no veo ninguna razón para que no pueda usarse con archivos que no sean los de / etc.

Si solo desea lidiar con un solo archivo, tal vez eso no sería perfecto, pero si desea realizar un seguimiento de todo en un directorio determinado, creo que vale la pena consultarlo.

iconoclasta
fuente
1

Este script no se ejecuta cuando un usuario cambia el archivo, pero podría ejecutarse como un trabajo cron (colocándolo en un directorio /etc/cron.*), que también es una solución razonable.

Este script iterará a través de su directorio / srv / www (cámbielo a donde estén almacenados todos sus sitios), agregue, confirme e inserte todos los archivos, y registre todo en /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
plantaciones
fuente
0

Esto no satisface la parte "Idealmente" de la pregunta, pero esta fue la pregunta más cercana que vi a la respuesta que quería, así que pensé que podría ir aquí. Sin embargo, mi primera publicación de stackoverflow, así que disculpa si me equivoco.

La siguiente secuencia de comandos asegura confirmaciones automáticas en los cambios guardados, pero solicitar al usuario cometer entrada. (Me doy cuenta de que mi escenario es un poco diferente al 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
fuente
0

Para ventanas

De acuerdo con este artículo sobre confirmación automática , debe crear un .batarchivo con contenido:

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

y ejecutar con Task Scheduler. Si no sabe cómo hacerlo paso a paso, consulte ese artículo.

T.Todua
fuente