Wykonywanie automatycznego zatwierdzania git

155

Chciałbym użyć git do zapisania wszystkich zmian w pliku.

Czy istnieje sposób, w jaki mogę włączyć „zatwierdzenie” git, aby było wykonywane automatycznie za każdym razem, gdy plik jest aktualizowany - więc dla każdej zmiany w pliku jest nowe zatwierdzenie?

Idealnie chciałbym, aby moi użytkownicy nawet nie wiedzieli, że git działa za kulisami. Użytkownik mógłby wtedy potencjalnie „cofnąć” zmiany w pliku - a można to osiągnąć, wyciągając poprzednią wersję z gita.

git-noob
źródło
9
Byłoby łatwiej używać systemu plików z wersjonowaniem: en.wikipedia.org/wiki/Versioning_file_system
William Pursell
1
SparkleShare był pod tym względem imponujący.
theode
SparkleShare wygląda na świetną opcję, ale niszczy każdy folder .git wewnątrz głównego gita
insign
Możesz użyć github.com/jw0k/gwatch . Działa w systemach Windows i Linux.
rubix_addict,
@rubix_addict Dlaczego nie opublikowałeś tego jako odpowiedzi?
Tobias Kienzler

Odpowiedzi:

127

W Linuksie możesz użyć inotifywait, aby automatycznie wykonać polecenie za każdym razem, gdy zawartość pliku zostanie zmieniona.

Edytuj: poniższe polecenie zatwierdza plik.txt zaraz po jego zapisaniu:

inotifywait -q -m -e CLOSE_WRITE --format="git commit -m 'autocommit on change' %w" file.txt | sh
JesperE
źródło
2
Jak możesz to zrobić dla całego folderu (a nie tylko jednego pliku?)
Anderson Green
2
Użyj -rflagi, aby inotifywait, ale pamiętaj, że jądro ma ograniczenie liczby zegarków inotifywait, które może ustawić. man inotifywaitpowie ci więcej.
JesperE
14
czy jest jakaś opcja w oknach ..?
Chandan Pasunoori
50

Wcześniejsza odpowiedź inotifywait jest świetna, ale nie jest to kompletne rozwiązanie. Jak napisano, jest to jednorazowe zatwierdzenie jednorazowej zmiany w pliku. Nie działa to w typowym przypadku, w którym edycja pliku tworzy nowy i-węzeł z oryginalną nazwą. inotifywait -m najwyraźniej podąża za plikami według i-węzła, a nie według nazwy. Ponadto po zmianie pliku nie jest on przemieszczany do git commit bez git add lub git commit -a . Dokonując pewnych poprawek, oto czego używam w Debianie do śledzenia wszystkich zmian w moim pliku kalendarza:

/etc/rc.local:


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

/ home / <nazwa użytkownika> / 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

Można to uogólnić, aby czekać na liście plików i / lub katalogów oraz odpowiednich procesów inotifywait i ponownie uruchamiać każdy inotifywait, gdy plik zostanie zmieniony.

Lester Buck
źródło
8
Lester, czy mógłbyś rozszerzyć, jak uogólnić to na katalog?
Diego
29

Poprzednie odpowiedzi, które zalecały inotifywait do tej pracy, wskazały mi właściwy kierunek, kiedy sam miałem ten problem, więc napisałem mały skrypt. Na początku można było oglądać rekursywnie tylko całe foldery (przeciwieństwo przykładu Lestera Bucka), ale potem chciałem też obejrzeć plik gdzie indziej, więc go rozszerzyłem.

Rezultatem jest obecnie wywoływany skryptgitwatch , ponieważ to właśnie robi: obserwuje plik lub folder pod kątem zmian (używając inotifywait) i zatwierdza je do repozytorium git.

Możesz znaleźć skrypt, więcej informacji i instrukcji na github: https://github.com/nevik/gitwatch

Nevik Rehnel
źródło
4
przydatny mały skrypt. Zanotuję to.
Iwein
interesujące może być przydatne w przypadku witryn Magento.
Testuję
16

git-wip to świetne rozwiązanie, które dobrze mi się sprawdza. „WIP” oznacza „prace w toku”. Za każdym razem, gdy uruchamiasz 'git wip', zmiany są zatwierdzane w oddzielnej gałęzi. Można go uruchomić z wiersza poleceń, ale istnieją rozszerzenia dla vim i emacs, które automatycznie uruchamiają git-wip za każdym razem, gdy plik jest zapisywany.

rafak
źródło
12

Chciałem to zrobić w systemie Windows i stwierdziłem, że najlepszym sposobem jest użycie Monitora katalogów do sprawdzenia zmian, a następnie po wykryciu zmiany uruchom:

Program: cmd.exe

Parametry: /CC:\pathToBatchFile.bat

Ten plik wsadowy zawierał:

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

Próbowałem też mieć tam inne polecenie dodawania plików ( "%PROGRAMFILES(X86)%\git\bin\sh.exe" --login -i -c "git add *.*"), ale nie sądzę, że działało poprawnie.

Zrobiłem również hak po zatwierdzeniu zawierający:

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

(Gdyby były jakieś konflikty, przerwałoby to wyciąganie i przerwanie pchania, ale nie było żadnego jasnego sposobu, aby to stwierdzić - w końcu porzuciliśmy cały pomysł z powodu tej jednej wady).

To polecenie curl powiedziało mojemu serwerowi, że musi wyciągnąć kod. Wszystko, co było potrzebne do obsługi tego w php, to:

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

Jedynym problemem było to, że musiał być uruchamiany przez użytkownika root zamiast użytkownika apache, więc musiałem również zrobić plik /etc/sudoers.d/zawierający:

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

Myślę, że to działało całkiem solidnie. Directory Monitor można skonfigurować tak, aby działał przy starcie i uruchomieniu zminimalizowanym i może obserwować kilka różnych folderów

Redzarf
źródło
Również w systemie Windows nie mogę uruchomić gita w LocalSystem, więc jeśli utworzysz własną usługę monitorowania, będziesz musiał uruchomić ją na koncie użytkownika, który faktycznie może uruchomić Git. Możliwe, że brakuje mi tylko niektórych ustawień / konfiguracji, ale prawdopodobnie i tak ładniej jest założyć nowe konto git commit
Whelkaholism
8
#!/bin/bash
git commit -a -m "autoupdate `date +%F-%T`"
git push

autopushing z aktualną datą i godziną.

web-rider
źródło
8

Inotify naprawdę brzmi jak odpowiednie narzędzie do pracy.

Istnieje narzędzie o nazwie incron, które może być dokładnie tym, czego szukasz. Możesz określić pliki lub foldery (i typy zdarzeń, takie jak „zmień”, „utwórz”, „odłącz”) w czymś takim jak tabela crontab oraz polecenie, które ma być uruchamiane, gdy takie zdarzenie wystąpi.

W przeciwieństwie do inotifywait (który byłby odpowiednikiem crona biednego człowieka sleep 10;do stuff), to złapie każde zdarzenie, nie tylko pierwsze.

Sam tego nie używałem, ale z dokumentacji wynika, że ​​konfiguracja nie jest zbyt skomplikowana.

pixelbrei
źródło
7

Napisałem program GitPrime , aby zapewnić automatyczne zapisywanie dla lokalnych repozytoriów Git. Teraz łatwo cofnąć się, zanim go zepsułeś! Repozytorium Bitbucket .

Powinno to działać na każdej platformie obsługującej powłokę bash, w tym Windows + Cygwin.

Brendan
źródło
+1 Używam tego w systemie Windows (CygWin) do automatycznego zapisywania zmian, które wprowadzam w repozytorium git-tf co 10 minut przy użyciu zaplanowanego zadania
Darbio
6

Na wypadek, gdyby ktoś próbował to zrobić z Powershell, odniosłem sukces, używając następującego:

& "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
źródło
5
Jak to się uruchamia automatycznie?
jerik
2
zaplanowane zadanie?
ozzy432836
2

Jeśli znasz nazwę pliku i chcesz monitorować tylko jeden (lub kilka plików), możesz po prostu wywoływać „git commit” co kilka minut, aby to osiągnąć. Jeśli plik się nie zmienił, git po prostu narzeknie i będziesz musiał zignorować ten błąd, ale poza tym nie będzie korupcji.

Oprócz tego będziesz chciał oznaczyć te pliki jako „automatyczne zatwierdzanie”, aby móc również zatwierdzać ręcznie. W ten sposób użytkownik może zobaczyć automatyczne zmiany, a także większe „logiczne” zmiany, którym towarzyszą komentarze dotyczące zatwierdzania, wyjaśniające, co zmieniło się od ostatniego ręcznego zatwierdzenia.

Na przykład użyj „AUTOCOMMIT” jako komunikatu o zatwierdzeniu. Później możesz napisać narzędzie do usuwania tych zatwierdzeń za pomocą dziennika git (aby znaleźć wersje do zabicia) lub możesz spróbować utworzyć gałąź AUTOCOMMIT, używając strategii rozwiązywania kolizji brutalnej siły, aby wbić w "ręczne zatwierdzenie".

Inną opcją jest użycie niskopoziomowych poleceń git do zbudowania własnego wyspecjalizowanego repozytorium.

Wreszcie, możesz skopiować plik do nowej nazwy („$ filename.ac”) podczas wykonywania automatycznych zatwierdzeń, aby odróżnić wersję ręczną od automatycznej.

Aaron Digulla
źródło
1

Jestem prawie pewien, że musiałbyś podłączyć to do dowolnego edytora, którego używają Twoi użytkownicy. Możesz napisać coś do sondowania pod kątem zmian, ale w zależności od wzorców użytkowania częstotliwość odpytywania może być niewiarygodnie wysoka, aby upewnić się, że zbiera poszczególne zmiany zamiast wielu zmian.

Hank Gay
źródło
Ponadto sondowanie zmian stworzy warunki wyścigu.
Bombe
1
Nie w przypadku edytorów takich jak emacs i yi, które zapisują pliki „transakcyjnie”, aby upewnić się, że dane nie zostaną utracone po awarii.
Robin Green,
1

Wygląda na to, że szukasz czegoś podobnego do etckeeper , który jest zaprojektowany do automatycznego sprawdzania wszystkich twoich zmian w / etc / * w git (lub jakimkolwiek VCS, który chcesz), ale nie widzę powodu, dla którego nie można go używać z plikami inne niż te w / etc.

Jeśli chcesz zajmować się tylko jednym plikiem, może nie byłoby to idealne, ale jeśli chcesz śledzić wszystko w danym katalogu, myślę, że warto to sprawdzić.

ikonoklasta
źródło
1

Ten skrypt nie działa, gdy użytkownik zmienia plik, ale można go uruchomić jako zadanie cron (upuszczając go do katalogu /etc/cron.*), co również jest rozsądnym rozwiązaniem.

Ten skrypt przejdzie przez twój katalog / srv / www (zmień go na miejsce, w którym są przechowywane wszystkie twoje witryny), doda, zatwierdza i wypycha wszystkie pliki oraz loguje wszystko do /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
Runningonplants
źródło
0

To nie odpowiada części „Idealnie” pytania, ale było to najbliższe pytanie, które widziałem, odpowiadające odpowiedzi, której szukałem, więc pomyślałem, że może tu trafić. Mój pierwszy post dotyczący stackoverflow, więc przepraszam, jeśli się mylę.

Poniższy skrypt zapewnia automatyczne zobowiązuje zapisanych na zmiany, ale nie pyta użytkownika o popełnić wejście. (Zdaję sobie sprawę, że mój scenariusz różni się nieco od scenariusza 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
źródło
0

Dla Windowsa

Zgodnie z tym artykułem o autocommit , powinieneś utworzyć .batplik z zawartością:

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

i wykonaj za pomocą Task Scheduler. Jeśli nie wiesz, jak to zrobić krok po kroku, zapoznaj się z tym artykułem.

T.Todua
źródło