Агент-инженер по репозиторию · Модуль 4 · Урок 4.4
Чекпойнт-коммиты и откат: обратимость
Зачем (какую проблему чиним)
Агент сделал серию правок, прогнал тесты — часть стало хуже. Если всё лежит одной кучей незакоммиченных изменений, откатить только неудачный шаг нельзя: либо теряем всё, либо тащим поломку дальше. Нужны чекпойнт-коммиты после каждого успешного шага и умение откатываться к последнему хорошему.
Решение и альтернативы
Решение: после каждого шага плана, прошедшего проверки, агент делает чекпойнт-коммит в своей ветке (git commit в worktree) с осмысленным сообщением. Если следующий шаг сломал сборку и почини́ть не удаётся — откат к последнему чекпойнту (git reset --hard <checkpoint> в worktree, не трогая основной репозиторий). История ветки агента — это лента обратимых точек.
Альтернативы: один коммит в конце — нечего откатывать пошагово; git revert — корректно для публичной истории, но внутри одноразовой ветки агента reset к чекпойнту проще и чище (ветку всё равно причёсываем перед MR).
DIFF
Добавляем чекпойнт-коммит и откат к последнему чекпойнту — строго в worktree, через assertWritable.
⚠ Безопасность
Обратимость — это безопасность: каждый чекпойнт даёт точку, к которой гарантированно можно вернуться, и фиксируется в аудит-логе (версия v5). reset --hard выполняется только в worktree агента — основной репозиторий и main недостижимы. Чекпойнты не пушатся автоматически: публикация — отдельное решение (версия v4, MR).
Проверка
Сценарий: шаг 1 ок (чекпойнт), шаг 2 ломает сборку → агент откатывается к чекпойнту шага 1 и пробует иначе. git -C <wt> log --oneline показывает ленту чекпойнтов; основной репозиторий не затронут.
Глубже
Durable-исполнение, идемпотентность, восстановление после сбоя — курс «Продакшн-разработка», Модуль 1 (гл. 1). Полный аудит обратимых действий — версия v5 (урок 6.4).
+// checkpoint фиксирует успешный шаг отдельным коммитом в ветке агента.
+func (w *Workspace) checkpoint(ctx context.Context, msg string) (string, error) {
+ if err := w.assertWritable(ctx); err != nil {
+ return "", err
+ }
+ if _, err := runGitWrite(ctx, w.Dir, "add", "-A"); err != nil {
+ return "", err
+ }
+ if _, err := runGitWrite(ctx, w.Dir, "commit", "-m", msg); err != nil {
+ return "", err
+ }
+ return runGitWrite(ctx, w.Dir, "rev-parse", "HEAD") // sha чекпойнта в аудит
+}
+
+// rollbackTo откатывает worktree к чекпойнту. Только в worktree агента —
+// основной репозиторий и main недостижимы.
+func (w *Workspace) rollbackTo(ctx context.Context, sha string) error {
+ if err := w.assertWritable(ctx); err != nil {
+ return err
+ }
+ _, err := runGitWrite(ctx, w.Dir, "reset", "--hard", sha)
+ return err
+}Anti-patterns
| Грабля | Почему плохо | Как правильно |
|---|---|---|
| Копить все правки одной кучей и коммитить в конце | Нельзя откатить только неудачный шаг — теряешь всё или тащишь поломку | Чекпойнт-коммит после каждого успешного шага; откат к последнему хорошему |
reset --hard в основном репозитории | Можно уничтожить чужую работу/состояние вне изоляции | Откат строго в worktree агента; основной репозиторий не трогаем |
| Автопуш чекпойнтов | Сырые промежуточные коммиты утекают наружу до ревью | Чекпойнты локальны; публикация — отдельное решение на версии MR |
Практическое задание (RA-v3)
- Добавить
checkpoint(коммит шага) иrollbackTo(reset к sha) строго в worktree. - Записывать sha чекпойнтов для будущего аудита; не пушить автоматически.
- Закоммитить:
git commit -m "v3: checkpoint commits and rollback".
Проверка знаний
Агент сделал 4 правки без промежуточных коммитов; последняя сломала сборку.
Почему чекпойнт-коммиты после каждого успешного шага лучше?
Верный ответ: B
B. Без промежуточных чекпойнтов поломка на последнем шаге заставляет либо откатить всё, либо чинить поверх. Чекпойнт после каждого успешного шага даёт гранулярную обратимость — вернуться к последнему зелёному состоянию и переделать только сломанное.