Создание git auto-commit

155

Я хотел бы использовать git для записи всех изменений в файл.

Есть ли способ, которым я могу включить git 'commit', чтобы он происходил автоматически при каждом обновлении файла - так что есть новый коммит для каждого изменения файла?

В идеале я бы хотел, чтобы мои пользователи даже не знали, что git работает за кулисами. Затем пользователь может потенциально «отменить» изменения в файле - и этого можно добиться, извлекая предыдущую версию из git.

ГИТ-нуб
источник
9
Было бы проще использовать файловую систему управления версиями: en.wikipedia.org/wiki/Versioning_file_system
Уильям Перселл
1
SparkleShare был довольно впечатляющим на этом.
theode
SparkleShare выглядит отличным вариантом, но он уничтожает любую папку .git внутри основного git
insign
Вы можете использовать github.com/jw0k/gwatch . Работает на Windows и Linux.
rubix_addict
@rubix_addict Почему вы не опубликовали это как ответ?
Тобиас Кинцлер

Ответы:

127

В Linux вы можете использовать inotifywait для автоматического выполнения команды при каждом изменении содержимого файла.

Изменить: следующая команда фиксирует файл file.txt, как только он будет сохранен:

inotifywait -q -m -e CLOSE_WRITE --format="git commit -m 'autocommit on change' %w" file.txt | sh
JesperE
источник
2
Как вы можете сделать это для всей папки (не только для одного файла?)
Андерсон Грин
2
Используйте -rфлаг для inotifywait, но обратите внимание, что ядро ​​имеет ограничение на количество часов inotifywait, которые оно может настроить. man inotifywaitскажу вам больше.
JesperE
14
есть ли вариант в windows ..?
Чандан Пасунори
50

Более ранний ответ inotifywait великолепен, но это не совсем полное решение. Как написано, это одноразовый коммит для одноразового изменения в файле. Это не работает в общем случае, когда при редактировании файла создается новый индекс с исходным именем. inotifywait -m, очевидно, следует за файлами по индексу, а не по имени. Кроме того, после изменения файла он не размещается для git commit без git add или git commit -a . Внесение некоторых изменений, вот что я использую в Debian для отслеживания всех изменений в моем файле календаря:

/etc/rc.local:


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

/ Главная / <имя пользователя> / 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

Это может быть обобщено для ожидания списка файлов и / или каталогов и соответствующих процессов inotifywait и перезапуска каждого inotifywait при изменении файла.

Лестер Бак
источник
8
Лестер, не могли бы вы рассказать о том, как обобщить это в каталог?
Диего
29

Предыдущие ответы с рекомендацией inotifywait для этой работы подсказали мне правильное направление, когда я сам столкнулся с этой проблемой, поэтому я написал небольшой сценарий. Сначала это могло только рекурсивно просматривать целые папки (в противоположность примеру Лестера Бака), но затем я также хотел посмотреть файл где-то еще, поэтому я расширил его.

В результате в настоящее время вызывается скриптgitwatch , который так и делает: он отслеживает изменения в файле или папке (используя inotifywait) и фиксирует их в хранилище git.

Вы можете найти скрипт, дополнительную информацию и инструкции на github: https://github.com/nevik/gitwatch

Невик Рехнел
источник
4
полезный маленький скрипт там. Я запомню это.
iwein
Интересно, может быть полезно для сайтов magento. Я тестирую его, но не могу заставить его
работать
16

git-wip - отличное решение, которое хорошо работает для меня. «WIP» означает «работа в процессе». Каждый раз, когда вы запускаете 'git wip', изменения фиксируются в отдельной ветке. Его можно запустить из командной строки, но есть расширения для vim и emacs для автоматического запуска git-wip при каждой записи файла.

rafak
источник
12

Я хотел сделать это в Windows, и обнаружил, что лучший способ - использовать Directory Monitor для проверки изменений, а затем, когда он обнаружил изменение, запустить его:

Программа: cmd.exe

Параметры: /CC:\pathToBatchFile.bat

Этот пакетный файл содержал:

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

Я также попытался добавить еще одну команду для добавления файлов ( "%PROGRAMFILES(X86)%\git\bin\sh.exe" --login -i -c "git add *.*"), но я не думаю, что у меня это получилось.

Я также сделал хук после фиксации, содержащий:

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

(Если бы были какие-либо конфликты, то это прервало бы тягу и прервало бы толчок, но не было никакого четкого способа сказать, что произошло - в конце концов, мы отказались от всей идеи из-за этого одного недостатка.)

Эта команда curl сообщила моему серверу, что нужно потянуть код. Все, что было необходимо для обработки в php, было:

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

Единственная проблема с этим состояла в том, что он должен был запускаться пользователем root вместо пользователя apache, поэтому я также должен был создать файл, /etc/sudoers.d/содержащий:

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

Для меня, я думаю, это сработало довольно солидно. Монитор каталогов можно настроить для запуска при запуске и запуска в свернутом виде, а также он может просматривать несколько разных папок

Redzarf
источник
Также в Windows я не могу заставить git работать под LocalSystem, поэтому, если вы создадите собственную службу мониторинга, вам придется запускать ее под пользователем, который на самом деле может запускать Git. Возможно, мне просто не хватает некоторых настроек / конфига, но, возможно, все равно лучше настроить новую учетную запись git commit
Whelkaholism
8
#!/bin/bash
git commit -a -m "autoupdate `date +%F-%T`"
git push

автопушинг с текущей датой и временем.

веб-наездник
источник
8

Inotify действительно звучит как правильный инструмент для работы.

Существует инструмент под названием incron, который может быть именно тем, что вы ищете. Вы можете указать файлы или папки (и типы событий, такие как «изменить», «создать», «отсоединить») в чем-то вроде crontab, и команду для запуска, когда такое событие происходит.

В отличие от inotifywait (который был бы аналогом cron бедняка sleep 10;do stuff), он будет ловить каждое событие, а не только первое.

Я не использовал его сам, но из документации он не выглядит слишком сложным для настройки.

pixelbrei
источник
7

Я написал программу GitPrime для автоматического сохранения ваших локальных репозиториев Git. Теперь легко откатиться до того, как вы его разорили! Репозиторий Bitbucket .

Это должно работать на любой платформе, которая поддерживает оболочку bash, включая Windows + Cygwin.

Brendan
источник
+1 Я использую это в Windows (CygWin) для автоматического сохранения изменений, которые я делаю в хранилище git-tf каждые 10 минут, используя запланированное задание
Дарбио
6

В случае, если кто-то пытается сделать это из Powershell, я добился успеха, используя следующее:

& "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
источник
5
И как это срабатывает автоматически?
Иерик
2
запланированное задание?
ozzy432836
2

Если вы знаете имя файла и хотите отслеживать только один (или несколько файлов), вы можете просто вызывать «git commit» каждые несколько минут, чтобы добиться этого. Если файл не изменился, git просто будет жаловаться, и вам придется игнорировать эту ошибку, но кроме этого, не будет никакого повреждения.

В дополнение к этому вы захотите пометить эти файлы как «автоматическое принятие», чтобы иметь возможность фиксировать также и вручную. Таким образом, пользователь может видеть автоматические изменения, а также более крупные «логические» изменения, сопровождаемые комментариями к коммиту, чтобы объяснить, что изменилось с момента последнего коммита.

Например, используйте «AUTOCOMMIT» в качестве сообщения фиксации. Позже вы можете написать инструмент для очистки этих коммитов, используя git log (чтобы узнать ревизии, которые нужно убить), или вы можете попытаться создать ветку AUTOCOMMIT, используя стратегию разрешения столкновений методом грубой силы, чтобы забить «ручные коммиты».

Другой вариант - использовать низкоуровневые команды git для создания собственного специализированного репозитория.

Наконец, вы можете скопировать файл под новым именем («$ filename.ac»), выполняя автоматическую фиксацию, чтобы различать ручную и автоматическую версии.

Аарон Дигулла
источник
1

Я уверен, что вам нужно подключить это к любому редактору, который используют ваши пользователи. Вы можете написать что-нибудь, чтобы опросить изменения, но в зависимости от моделей использования частота опросов может быть невероятно высокой, чтобы убедиться, что она собирает отдельные изменения, а не множественные изменения.

Хэнк Гей
источник
Кроме того, опрос об изменениях создаст условия гонки.
Бомба
1
Не с такими редакторами, как emacs и yi, которые пишут файлы «транзакционно», чтобы гарантировать, что данные не будут потеряны после сбоя.
Робин Грин
1

Похоже, вы ищете что-то похожее на etckeeper , который предназначен для автоматической проверки всех ваших изменений в / etc / * в git (или в любом другом VCS, который вы хотите), но я не вижу причин, по которым его нельзя использовать с файлами кроме тех, что в / etc.

Если вы хотите иметь дело только с одним файлом, возможно, это не было бы идеально, но если вы хотите отслеживать все в данном каталоге, я думаю, стоит проверить.

иконоборец
источник
1

Этот сценарий не запускается, когда пользователь изменяет файл, но его можно запустить как задание cron (поместив его в каталог /etc/cron.*), что также является разумным решением.

Этот скрипт будет перебирать вашу директорию / srv / www (изменить ее на место, где хранятся все ваши сайты), добавлять, фиксировать и отправлять все файлы, а также записывать все в /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
источник
0

У меня была та же проблема, и на Mac launchd предоставляет вам отличное решение. он будет смотреть файл или каталог, и если есть изменения, вы можете запустить приложение или что-нибудь еще ...


источник
См. «Мониторинг каталога» здесь: developer.apple.com/library/mac/#documentation/MacOSX/…
Крис
0

Это не удовлетворяет «в идеале» части вопроса, но это был самый близкий вопрос, который я видел к ответу, который хотел, поэтому я решил, что он может пойти сюда. Мой первый пост, посвященный stackoverflow, поэтому извиняюсь, если я ошибаюсь

Следующий сценарий обеспечивает автоматические фиксации на сохраненных изменениях, но делает подсказки пользователя для фиксации ввода. (Я понимаю, что мой сценарий немного отличается от сценария 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
источник
0

Для Windows

Согласно этой статье об autocommit , вы должны создать .batфайл с контентом:

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

и выполнить с Task Scheduler. Если вы не знаете, как сделать это шаг за шагом, обратитесь к этой статье.

T.Todua
источник