Перейти к основному содержимому

Автокоммит CMS — настройка и поведение

Версия: 1.0 Дата: 26.04.2026 Статус: Готов к обсуждению

Документ описывает работу автоматического коммита документов системы при правке через Decap CMS или прямую запись в docs/. Реализован через watcher-скрипт tools/auto-commit-watcher.sh под управлением PM2.

Зачем

Decap CMS в режиме backend: proxy + local_fs (наш режим) не делает git-коммитов при Publish — он только пишет файл на диск через decap-server. Это приводило к ситуации, когда правки лежали на диске untracked часами и днями, а потом случайно затирались git checkout/git reset.

Реальный случай 22-25 апреля 2026: функционал SVG-конвертации в tools.html и cms-tools-api.js жил на диске 3 суток untracked, потом был затёрт и спасён только из ~/archives/. Watcher закрывает этот класс рисков.

Это также закрывает обещание «Связь с Git» в Руководство по установке, где утверждалось, что Publish в CMS делает автоматический коммит.

Что делает watcher

  • Слушает директорию docs/ рекурсивно через inotifywait (пакет inotify-tools).
  • Реагирует на события create, modify, delete, move для файлов .md и .json.
  • Игнорирует временные файлы редакторов (.swp, .tmp, ~), служебные папки (_uploads, .git, node_modules, .docusaurus, build).
  • Применяет debounce 60 секунд — после события ждёт 60 секунд тишины, и только потом делает коммит. Если за время ожидания приходят новые события — таймер сбрасывается. Это даёт один коммит на пакет правок, а не один на каждый штрих.
  • Коммит делается под отдельным author: Decap CMS Auto <noreply@cms.local>. Это видно в git log — отличает автоматические коммиты от ручных.
  • Сообщение коммита:
    • один файл: cms: auto-commit <filename>;
    • несколько файлов: cms: auto-commit N files (YYYY-MM-DD HH:MM).

Как устроено в PM2

В ecosystem.config.js добавлен 4-й процесс:

{
name: 'cms-auto-commit',
script: 'tools/auto-commit-watcher.sh',
cwd: '/home/alex/sites/cms-docs',
watch: false,
autorestart: true,
interpreter: 'bash',
}

autorestart: true — если watcher упадёт (например, из-за ошибки git), PM2 перезапустит автоматически.

Все четыре процесса системы CMS:

IDИмяНазначениеПорт
0cms-docs-devDocusaurus dev-сервер3000
1cms-decap-serverDecap proxy backend (запись в файлы)8083
2cms-tools-apiAPI для tools.html (деплой, конвертация SVG)8084
3cms-auto-commitWatcher автокоммитов

После любого изменения в этом списке — pm2 save, чтобы переживало reboot.

Управление

Временно остановить watcher

Нужно при массовых правках, когда вы сами хотите контролировать когда что коммитится:

pm2 stop cms-auto-commit

После окончания массовых правок — вручную закоммитить накопившееся, потом включить:

git add docs/
git commit -m "manual: <описание>"
pm2 start cms-auto-commit

Посмотреть лог watcher-а

tail -f ~/.pm2/logs/cms-auto-commit-out.log

Видно:

  • Время запуска: auto-commit-watcher запущен. WATCH_DIR=... DEBOUNCE=60s.
  • Каждое событие: событие: CREATE|MODIFY|DELETE /path/to/file.md.
  • Каждый коммит: коммит: N файлов, Author: Decap CMS Auto, M file changed, N insertions(+).

Полный перезапуск (например, после правки самого скрипта)

pm2 restart cms-auto-commit

Посмотреть автокоммиты в истории

git log --author='Decap CMS Auto' --oneline

Откат отдельной правки

Если автокоммит зафиксировал нежелательное изменение (например, вы случайно сохранили в CMS что-то не то):

Вариант 1. Один документ — один коммит

git revert <hash>

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

Вариант 2. Откат нескольких последовательных автокоммитов

git reset --hard <hash-до-нежелательного-коммита>

⚠ Внимание: это переписывает историю и удаляет коммиты безвозвратно. Использовать только если вы уверены и история ещё не запушена.

Вариант 3. Восстановить только один файл из старой версии

git checkout <hash> -- <path/to/file.md>
git commit -m "manual: revert <file> to <hash>"

Тонкости

Конкуренция с decap-server

Decap CMS пишет файл через decap-server → файл на диске → inotify event → watcher через 60 сек делает коммит. Между записью decap-server и коммитом watcher — окно 60 секунд. Если за это время CMS делает несколько Publish одного и того же документа, всё попадёт в один коммит.

Если за 60 секунд несколько РАЗНЫХ документов — тоже один коммит со всеми изменениями (со списком в сообщении: cms: auto-commit N files).

Конкуренция с ручными правками через VS Code/vim

Если вы редактируете файл руками в редакторе:

  • Каждый save → inotify event → перезапуск debounce.
  • Через 60 секунд тишины — автокоммит.
  • Если хотите комитить под своим именем — остановите watcher (pm2 stop cms-auto-commit), сделайте коммит руками, верните watcher.

Что watcher НЕ делает

  • Не делает git push. Коммиты остаются локальными. Деплой на VPS — отдельной командой tools/deploy_site.sh --mode=vps.
  • Не следит за static/, tools/, конфигами. Только docs/. Изменения скриптов и конфигов — коммитятся вручную.
  • Не разрешает merge-конфликты. Если в репо уже есть незакоммиченные конфликтующие правки — git commit упадёт с ошибкой, watcher напишет ошибку в лог и продолжит работать (благодаря PM2 autorestart).

Зависимости

  • inotify-tools — для inotifywait. Установка на Ubuntu:
    sudo apt install inotify-tools
  • git (любая современная версия).
  • bash 4+.

Случаи когда watcher временно отключают

  • Массовая программная генерация документов (например, импорт bundle, перегенерация index.md скриптами). Чтобы не плодить N коммитов под Decap CMS Auto — остановить watcher на время генерации, потом запустить + сделать один человеческий коммит.
  • Конфликт с операциями git rebase/merge. Перед git rebase или git mergepm2 stop cms-auto-commit.
  • Отладка самого watcher-а или экспериментов с docs/. Чтобы не было неожиданных коммитов.

Реализация

Скрипт tools/auto-commit-watcher.sh — bash, ~130 строк. Основные блоки:

  1. Setup — определение REPO, WATCH_DIR, DEBOUNCE_SECONDS=60, author константы.
  2. do_commit — функция: проверяет git status --porcelain docs/, если есть изменения — git add docs/ + git commit с заданным author и сообщением.
  3. debounce_loop — фоновая ветка: каждую секунду проверяет, прошло ли DEBOUNCE_SECONDS с последнего события. Если да и есть pending — вызывает do_commit.
  4. Главный циклinotifywait -m -r + while-чтение событий, обновление файла-флага времени.

Полный исходник — tools/auto-commit-watcher.sh в репозитории.

Связанная документация