Git automatisch festschreiben

154

Ich möchte git verwenden, um alle Änderungen an einer Datei aufzuzeichnen.

Gibt es eine Möglichkeit, git 'commit' zu aktivieren, die bei jeder Aktualisierung einer Datei automatisch ausgeführt wird? Es gibt also für jede Änderung an einer Datei ein neues Commit?

Idealerweise möchte ich, dass meine Benutzer nicht einmal wissen, dass Git hinter den Kulissen läuft. Ein Benutzer könnte dann möglicherweise Änderungen an einer Datei "rückgängig machen" - und dies könnte erreicht werden, indem eine frühere Version aus git gezogen wird.

git-noob
quelle
9
Es wäre einfacher, ein Versionsdateisystem zu verwenden: en.wikipedia.org/wiki/Versioning_file_system
William Pursell
1
SparkleShare war ziemlich beeindruckend.
Theode
SparkleShare sieht gut aus, zerstört aber jeden .git-Ordner im Haupt-Git
Insign
Sie können github.com/jw0k/gwatch verwenden . Es funktioniert unter Windows und Linux.
rubix_addict
@rubix_addict Warum hast du das nicht als Antwort gepostet?
Tobias Kienzler

Antworten:

127

Unter Linux können Sie inotifywait verwenden , um bei jeder Änderung des Inhalts einer Datei automatisch einen Befehl auszuführen.

Bearbeiten: Der folgende Befehl schreibt file.txt fest, sobald es gespeichert wird:

inotifywait -q -m -e CLOSE_WRITE --format="git commit -m 'autocommit on change' %w" file.txt | sh
JesperE
quelle
2
Wie kann man das für einen ganzen Ordner machen (nicht nur für eine einzelne Datei?)
Anderson Green
2
Verwenden Sie das -rFlag inotifywait, aber beachten Sie, dass der Kernel die Anzahl der inotifywait-Uhren, die er einrichten kann, begrenzt. man inotifywaitwerde dir mehr erzählen.
JesperE
14
Gibt es eine Option in Windows ..?
Chandan Pasunoori
50

Die frühere Antwort von inotifywait ist großartig, aber keine vollständige Lösung. Wie geschrieben, handelt es sich um ein One-Shot-Commit für eine einmalige Änderung in einer Datei. Dies funktioniert nicht für den allgemeinen Fall, dass beim Bearbeiten einer Datei ein neuer Inode mit dem ursprünglichen Namen erstellt wird. inotifywait -m folgt Dateien anscheinend nach Inode, nicht nach Namen. Nachdem die Datei geändert wurde, wird sie nicht für git commit ohne git add oder git commit -a bereitgestellt . Ich nehme einige Anpassungen vor und verwende Folgendes in Debian, um alle Änderungen an meiner Kalenderdatei zu verfolgen:

/etc/rc.local:


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

/ home / <Benutzername> / 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

Dies kann verallgemeinert werden, um auf eine Liste von Dateien und / oder Verzeichnissen und die entsprechenden inotifywait- Prozesse zu warten und jedes inotifywait neu zu starten, wenn eine Datei geändert wird.

Lester Buck
quelle
8
Lester, können Sie bitte erläutern, wie dies auf ein Verzeichnis verallgemeinert werden kann?
Diego
29

Die vorherigen Antworten, in denen inotifywait für diesen Job empfohlen wurde, haben mich in die richtige Richtung gelenkt, als ich dieses Problem selbst hatte, also habe ich ein kleines Skript geschrieben. Zuerst konnte dies nur ganze Ordner rekursiv anzeigen (das Gegenteil von Lester Buck 'Beispiel), aber dann wollte ich auch eine Datei woanders ansehen, also habe ich sie erweitert.

Das Ergebnis ist ein Skript, das derzeit aufgerufen wird gitwatch, da es eine Datei oder einen Ordner auf Änderungen überwacht (mithilfe von inotifywait) und diese in ein Git-Repository festschreibt.

Das Skript, weitere Informationen und Anweisungen finden Sie auf github: https://github.com/nevik/gitwatch

Nevik Rehnel
quelle
4
nützliches kleines Skript dort. Ich werde es notieren.
iwein
Interessant könnte für Magento-Sites nützlich sein. Ich
teste
16

Git-Wip ist eine großartige Lösung, die für mich gut funktioniert. "WIP" steht für "work in progress". Jedes Mal, wenn Sie 'git wip' ausführen, werden die Änderungen in einen separaten Zweig übernommen. Es kann in der Befehlszeile ausgeführt werden, es gibt jedoch Erweiterungen für vim und emacs, mit denen git-wip bei jedem Schreiben einer Datei automatisch ausgeführt wird.

Rafak
quelle
12

Ich wollte dies in Windows tun und fand heraus, dass der beste Weg darin bestand, Directory Monitor zu verwenden, um nach Änderungen zu suchen , und diese dann auszuführen, wenn eine Änderung festgestellt wurde:

Programm: cmd.exe

Parameter: /CC:\pathToBatchFile.bat

Diese Batch-Datei enthielt:

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

Ich habe auch versucht, einen anderen Befehl zum Hinzufügen von files ( "%PROGRAMFILES(X86)%\git\bin\sh.exe" --login -i -c "git add *.*") zu verwenden, aber ich glaube nicht, dass das richtig funktioniert.

Ich habe auch einen Post-Commit-Hook erstellt, der Folgendes enthält:

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

(Wenn es Konflikte gäbe, würde dies das Ziehen und das Drücken abbrechen, aber es gab keinen klaren Weg, um festzustellen, dass dies geschehen war - am Ende haben wir die gesamte Idee wegen dieses einen Fehlers aufgegeben.)

Dieser Curl-Befehl teilte meinem Server mit, dass der Code abgerufen werden muss. Alles, was benötigt wurde, um es in PHP zu handhaben, war:

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

Das einzige Problem dabei war, dass es vom Root-Benutzer anstelle des Apache-Benutzers ausgeführt werden musste, sodass ich auch eine Datei erstellen musste, die Folgendes /etc/sudoers.d/enthielt:

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

Für mich hat das ziemlich solide funktioniert. Directory Monitor kann so konfiguriert werden, dass es beim Start ausgeführt und minimiert gestartet wird, und es kann mehrere verschiedene Ordner überwachen

Redzarf
quelle
Auch unter Windows kann ich git nicht unter LocalSystem ausführen. Wenn Sie also Ihren eigenen Überwachungsdienst erstellen, müssen Sie ihn unter einem Benutzer ausführen, der Git tatsächlich ausführen kann. Möglicherweise fehlen mir nur einige Einstellungen / Konfigurationen, aber es ist wahrscheinlich
besser
8
#!/bin/bash
git commit -a -m "autoupdate `date +%F-%T`"
git push

Autopushing mit aktuellem Datum und Uhrzeit.

Web-Fahrer
quelle
8

Inotify klingt wirklich nach dem richtigen Werkzeug für den Job.

Es gibt ein Tool namens incron, das genau das sein könnte, wonach Sie suchen. Sie können Dateien oder Ordner (und Ereignistypen wie "Ändern", "Erstellen", "Verknüpfung aufheben") in einer Crontab und einen Befehl angeben, der ausgeführt werden soll, wenn ein solches Ereignis auftritt.

Im Gegensatz zu inotifywait (das Analogon zum Cron des armen Mannes sleep 10;do stuff) wird dies jedes Ereignis erfassen , nicht nur das erste.

Ich habe es selbst nicht verwendet, aber aus der Dokumentation geht hervor, dass die Einrichtung nicht zu komplex ist.

pixelbrei
quelle
7

Ich habe ein Programm geschrieben, GitPrime , um die automatische Speicherung für Ihre lokalen Git-Repositorys bereitzustellen. Jetzt einfach zurück zu rollen, bevor Sie es kaputt gemacht haben! Bitbucket-Repository .

Dies sollte auf jeder Plattform funktionieren, die eine Bash-Shell unterstützt, einschließlich Windows + Cygwin.

Brendan
quelle
+1 Ich verwende dies unter Windows (CygWin), um Änderungen, die ich an einem Git-TF-Repository vornehme, alle 10 Minuten mithilfe einer geplanten Aufgabe
automatisch zu speichern
6

Falls jemand versucht, dies von Powershell aus zu tun, hatte ich folgenden Erfolg:

& "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
quelle
5
Und wie wird das automatisch ausgelöst?
Jerik
2
geplante Aufgabe?
ozzy432836
2

Wenn Sie den Namen der Datei kennen und nur eine (oder einige) Dateien überwachen möchten, können Sie einfach alle paar Minuten "git commit" aufrufen, um dies zu erreichen. Wenn sich die Datei nicht geändert hat, beschwert sich git nur und Sie müssen diesen Fehler ignorieren, aber ansonsten gibt es keine Beschädigung.

Darüber hinaus möchten Sie diese Dateien als "Auto Commit" markieren, um sie auch manuell festschreiben zu können. Auf diese Weise kann der Benutzer die automatischen Änderungen sowie die größeren "logischen" Änderungen sehen, die von Festschreibungskommentaren begleitet werden, um zu erklären, dass sich diese seit dem letzten manuellen Festschreiben geändert haben.

Verwenden Sie beispielsweise "AUTOCOMMIT" als Festschreibungsnachricht. Später können Sie ein Tool schreiben, um diese Commits mithilfe des Git-Protokolls zu löschen (um die zu tötenden Revisionen herauszufinden), oder Sie können versuchen, einen Zweig AUTOCOMMIT mithilfe einer Brute-Force-Kollisionslösungsstrategie zu erstellen, um die "manuellen Commits" einzuschlagen.

Eine andere Möglichkeit besteht darin, die git-Befehle auf niedriger Ebene zu verwenden, um ein eigenes spezialisiertes Repository zu erstellen.

Zuletzt können Sie die Datei unter automatischen Festschreibungen in einen neuen Namen ("$ filename.ac") kopieren, um zwischen der manuellen und der automatischen Version zu unterscheiden.

Aaron Digulla
quelle
1

Ich bin mir ziemlich sicher, dass Sie das in den Editor einbinden müssen, den Ihre Benutzer verwenden. Sie könnten etwas schreiben, um Änderungen abzufragen, aber abhängig von den Verwendungsmustern muss die Abrufhäufigkeit möglicherweise unglaublich hoch sein, um sicherzustellen, dass einzelne Änderungen anstelle mehrerer Änderungen erfasst werden.

Hank Gay
quelle
Durch das Abrufen von Änderungen werden außerdem Rennbedingungen geschaffen.
Bombe
1
Nicht bei Editoren wie Emacs und Yi, die Dateien "transaktional" schreiben, um sicherzustellen, dass Daten nach einem Absturz nicht verloren gehen.
Robin Green
1

Es hört sich so an, als ob Sie nach etwas ähnlichem wie etckeeper suchen , das automatisch alle Änderungen an / etc / * in git (oder einem beliebigen VCS, das Sie möchten) überprüft, aber ich sehe keinen Grund, warum es nicht mit Dateien verwendet werden kann andere als die in / etc.

Wenn Sie sich nur mit einer einzigen Datei befassen möchten, wäre das vielleicht nicht perfekt, aber wenn Sie alles in einem bestimmten Verzeichnis im Auge behalten möchten, lohnt es sich, einen Blick darauf zu werfen.

Bilderstürmer
quelle
1

Dieses Skript wird nicht ausgeführt, wenn ein Benutzer die Datei ändert, es kann jedoch als Cron-Job ausgeführt werden (indem es in ein Verzeichnis /etc/cron.* abgelegt wird). Dies ist auch eine sinnvolle Lösung.

Dieses Skript durchläuft Ihr Verzeichnis / srv / www (ändern Sie es in den Speicherort aller Ihrer Websites), fügt alle Dateien hinzu, schreibt sie fest und überträgt sie und protokolliert alles 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
laufende Pflanzen
quelle
0

Ich hatte das gleiche Problem und auf Mac Launchd bietet Ihnen eine großartige Lösung. Es wird eine Datei oder ein Verzeichnis anzeigen und wenn es Änderungen gibt, können Sie eine App oder etwas anderes ausführen ...


quelle
Siehe "Überwachen eines Verzeichnisses" hier: developer.apple.com/library/mac/#documentation/MacOSX/…
Kris
0

Dies erfüllt nicht den "Ideal" -Teil der Frage, aber dies war die Frage, die der Antwort, die ich wollte, am nächsten kam, also dachte ich, dass sie hier hingehen könnte. Mein erster Stackoverflow-Beitrag, also entschuldige mich, wenn ich mich irre.

Das folgende Skript stellt automatische Festschreibungen für gespeicherte Änderungen sicher, fordert den Benutzer jedoch zur Eingabe von Festschreibungen auf. (Mir ist klar, dass mein Szenario etwas anders ist als das von 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
quelle
0

Für Windows

Gemäß diesem Artikel über Autocommit erstellen Sie eine .batDatei mit Inhalten:

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

und ausführen mit Task Scheduler. Wenn Sie nicht wissen, wie Sie Schritt für Schritt vorgehen, lesen Sie diesen Artikel.

T.Todua
quelle