↓Перейти к содержанию
  1. Git: руководства и команды/

git commit --allow-empty: создание пустого коммита

·8 минут·

Обычно Git отказывается создавать коммит, если нет никаких изменений в файлах. Это логичная защита — зачем сохранять точку в истории, если ничего не изменилось?

Однако, есть специальные ситуации, когда вам нужен пустой коммит:

  1. Запуск CI/CD — Вы хотите перезапустить сборку/тесты, не меняя код
  2. Маркеры в истории — Вы хотите отметить важное событие (начало спринта, релиз)
  3. Тестирование hooks — Вы хотите проверить pre-commit или pre-push hooks без реальных изменений
  4. Monorepo структуры — Вы хотите создать корневой коммит для отдельной части проекта

Вот здесь вам помогает флаг --allow-empty, который позволяет создать коммит даже без изменений.

В этой статье разберём:

  • Синтаксис git commit --allow-empty
  • Реальные примеры использования
  • Как просмотреть пустые коммиты в истории
  • Лучшие практики при работе с пустыми коммитами
  • Связь с Conventional Commits

Синтаксис #

Базовый пустой коммит #

$ git commit --allow-empty -m "Ваше сообщение"

Пустой коммит с подробным описанием #

$ git commit --allow-empty -m "Краткое описание" -m "Подробное описание"

Или в режиме редактора #

$ git commit --allow-empty
# Откроется редактор для написания сообщения

Коммит, пропуская hooks #

$ git commit --allow-empty --no-verify -m "Сообщение"

Случай 1: Запуск CI/CD вручную #

Это один из самых частых и практичных примеров использования --allow-empty. Представьте, что у вас есть GitHub Actions или другой CI/CD сервис, который автоматически запускается при каждом push’е.

Сценарий: Вы отправили код, и CI/CD обнаружил непостоянное падение теста (flaky test). Тест прошёл со случайной ошибкой, но код правильный. Вам нужно перезапустить тесты без изменения кода.

# Способ 1 (неправильно): создаёте файл, коммитите его, потом удаляете
$ touch dummy.txt
$ git add dummy.txt
$ git commit -m "Trigger CI"
$ rm dummy.txt
# Результат: бесполезный коммит в истории ❌

# Способ 2 (правильно): пустой коммит
$ git commit --allow-empty -m "ci: переза пуск CI/CD для проверки"
$ git push
# Результат: CI/CD перезапустится, история чистая ✓

Пример GitHub Actions workflow #

# .github/workflows/deploy.yml
name: Deploy

on:
  push:
    branches:
      - main
  workflow_dispatch:

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Deploy
        run: ./deploy.sh

Если вам нужно перезапустить деплой:

$ git commit --allow-empty -m "chore: переза пуск деплоя"
$ git push

GitHub Actions увидит push и автоматически запустит workflow.

Alias для быстрого перезапуска CI #

Добавьте в ~/.gitconfig:

[alias]
    ci-retrigger = commit --allow-empty -m "ci: retrigger"
    ci-redeploy = commit --allow-empty -m "ci: redeploy"

Использование:

$ git ci-retrigger && git push

Случай 2: Маркеры в истории #

Пустые коммиты можно использовать для отметки важных событий в истории проекта:

Пример: Начало спринта #

# Сегодня начало спринта #42
$ git commit --allow-empty -m "chore: начало Sprint #42"
$ git push

# История:
# 2a1b3c4 chore: начало Sprint #42
# 9f8e7d6 Исправлена ошибка в парсере
# 5c4b3a2 Добавлена новая функция

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

Пример: Вехи проекта #

# Проект достигнул версии 1.0.0
$ git tag -a v1.0.0 -m "Release version 1.0.0"
$ git commit --allow-empty -m "release: версия 1.0.0 готова к производству"
$ git push origin main --tags

# История:
# a9b8c7d release: версия 1.0.0 готова к производству
# x8y7z6w fix: исправлены критические баги
# m7n6o5p chore: подготовка к релизу

Пример: Передача проекта #

# Проект передаётся другой команде
$ git commit --allow-empty -m "chore: передача проекта команде backend-team"
$ git push

# История:
# t1a2s3k chore: передача проекта команде backend-team
# q1w2e3r Финальные оптимизации производительности
# ...

Пример: Завершение задачи в Jira #

# Завершили большой feature
$ git commit --allow-empty -m "feat: завершен PROJ-1234 - полная переработка API"
$ git push

# История содержит чистый маркер:
# h1e2l3l chore: завершен PROJ-1234

Случай 3: Тест hooks без изменений #

Если вы разрабатываете или тестируете Git hooks (pre-commit, pre-push, commit-msg), вам может понадобиться создать коммит без реальных изменений.

Пример: Тестирование commit-msg hook #

# Вы только что создали hook, который проверяет формат сообщения
$ cat .git/hooks/commit-msg
#!/bin/bash
# Сообщение должно начинаться с "feat:", "fix:", "chore:" и т.д.
if ! echo "$1" | grep -qE "^(feat|fix|chore|docs):"; then
    echo "Ошибка: сообщение должно начинаться с feat:, fix:, chore: или docs:"
    exit 1
fi

# Тест 1: Правильный формат
$ git commit --allow-empty -m "feat: новая фишка"
# Успех! Коммит создан ✓

# Тест 2: Неправильный формат
$ git commit --allow-empty -m "добавлена новая фишка"
# Ошибка: сообщение должно начинаться с feat:, fix:, chore: или docs:
# Хук отработал правильно! ✓

# Тест 3: Пропуск хука (если нужно)
$ git commit --allow-empty --no-verify -m "добавлена новая фишка"
# Коммит создан без проверки хука

Пример: Тестирование pre-commit hook #

$ cat .git/hooks/pre-commit
#!/bin/bash
# Проверка синтаксиса Python
python -m py_compile src/**/*.py || exit 1

# Но нам нужно только тестировать hook, без реальных изменений
$ git commit --allow-empty -m "test: проверка pre-commit hook"
# Hook сработает, даже хотя нет файлов для проверки

Случай 4: Корневой коммит для monorepo #

В монорепозиториях (когда один репозиторий содержит несколько независимых проектов) иногда нужно создать отдельную историю для каждого проекта.

# Структура monorepo:
# /
#   backend/
#   frontend/
#   shared/

# Создаём пустой корневой коммит для backend
$ git commit --allow-empty -m "init: инициализация backend проекта"
$ git push

# Позже, когда захотите работать только с backend:
$ git log --all -- backend/  # покажет коммиты для backend

Просмотр пустых коммитов в истории #

Стандартное просмотра истории #

Пустые коммиты видны в истории как обычные:

$ git log --oneline
a9b8c7d ci: retrigger CI/CD
x8y7z6w feat: добавлена новая функция
m7n6o5p fix: исправлена ошибка

Проверка, что коммит действительно пустой #

# Показать коммит и его изменения
$ git show a9b8c7d --stat

# Вывод:
# commit a9b8c7da1b2c3d4e5f6g7h8
# Author: Ivan Petrov <[email protected]>
# Date:   Fri Feb 27 10:30:00 2026 +0300
#
#     ci: retrigger CI/CD
#
# (нет файлов, so no changes to display)

Поиск всех пустых коммитов #

# Найти все коммиты без изменений файлов
$ git log --all --diff-filter=M --oneline

# Или более сложный поиск через git rev-list
$ git rev-list --all | while read commit; do
    if [ $(git diff --name-only $commit^..$commit | wc -l) -eq 0 ]; then
        echo "Пустой коммит: $commit"
        git show --oneline -s $commit
    fi
done

Фильтрация пустых коммитов из логов #

Если вы хотите показать историю без пустых коммитов:

# Использовать самодельный скрипт или инструмент
# К сожалению, встроенного флага нет, но можно использовать:
$ git log --all --pretty=format:"%h %s" | grep -v "^[a-f0-9]* $"

Лучшие практики #

1. Используйте значимые сообщения #

# ❌ Плохо: неинформативное сообщение
$ git commit --allow-empty -m "Empty commit"

# ✓ Хорошо: ясно объясняет причину
$ git commit --allow-empty -m "ci: перезапуск CI для проверки непостоянного теста"

2. Используйте Conventional Commits префиксы #

# Для пустых коммитов используйте префиксы, чтобы объяснить причину:

# ci: для запуска CI/CD
$ git commit --allow-empty -m "ci: переза пуск сборки"

# chore: для административных операций
$ git commit --allow-empty -m "chore: начало Sprint #42"

# docs: для обновления документации без кода
$ git commit --allow-empty -m "docs: завершена документация API"

# test: для тестирования hooks или процессов
$ git commit --allow-empty -m "test: проверка commit-msg hook"

3. Ограничивайте использование пустых коммитов #

Пустые коммиты — это инструмент для исключительных ситуаций. Используйте их рассудительно:

# ✓ Правильное использование: редкое и с причиной
$ git commit --allow-empty -m "ci: retrigger flaky test"

# ❌ Неправильное использование: частые и без смысла
$ git commit --allow-empty -m "update"
$ git commit --allow-empty -m "changes"

4. Избегайте пустых коммитов в shared branches #

Не создавайте пустые коммиты в общих ветках (main, develop), если это может запутать коллег. Используйте их только в:

  • Личных feature branches
  • CI/CD automation
  • Документированных маркерах версий

5. Документируйте причину #

Если вы используете пустой коммит, убедитесь, что сообщение ясно объясняет почему:

# ✓ Хорошо: понятна причина
$ git commit --allow-empty -m "ci: перезапуск CI после обновления GitHub Actions"

# ❌ Плохо: непонятна причина
$ git commit --allow-empty -m "trigger"

Связь с Conventional Commits #

Conventional Commits — это стандарт для форматирования сообщений коммитов. Для пустых коммитов рекомендуется использовать соответствующие префиксы:

<type>[optional scope]: <description>

Типы для пустых коммитов:

ТипИспользованиеПример
ciCI/CD операции, перезапускci: retrigger GitHub Actions
choreАдминистративные операции, маркерыchore: start Sprint #42
docsДокументация без кодаdocs: update API documentation
testТестирование процессовtest: verify pre-commit hook
# Примеры с Conventional Commits:
$ git commit --allow-empty -m "ci: retrigger tests after GitHub Actions update"
$ git commit --allow-empty -m "chore: mark release v2.0.0"
$ git commit --allow-empty -m "docs: document monorepo structure"

FAQ #

Вопрос 1: Почему я не могу просто отправить пустой push вместо коммита?

Git не позволяет push’ить без новых коммитов. Если нужно переза пустить CI/CD, нужно создать коммит (пустой или нет). Пустой коммит — это чистый способ сделать это, он не загрязняет историю.

Вопрос 2: Есть ли флаг –allow-empty-message, который позволит пустое сообщение?

Да, git commit --allow-empty --allow-empty-message создаст коммит без сообщения. Но это очень не рекомендуется, потому что история станет невоспроизводимой. Всегда используйте -m с описанием.

# Не делайте так:
$ git commit --allow-empty --allow-empty-message

# Делайте так:
$ git commit --allow-empty -m "Описание"

Вопрос 3: Как пустой коммит влияет на git bisect?

При использовании git bisect для поиска регрессии, пустые коммиты будут включены в процесс поиска. Это может немного замедлить bisect, но не нарушает его функциональность. Если вам часто нужен bisect, минимизируйте количество пустых коммитов.

Вопрос 4: Как удалить пустой коммит из истории?

# Если это последний коммит:
$ git reset --soft HEAD~1
$ git reset HEAD

# Или:
$ git rebase -i HEAD~2  # интерактивный rebase, удалите строку с пустым коммитом

# На общей ветке (после push):
$ git revert <commit-hash>
$ git push

Вопрос 5: Можно ли использовать пустой коммит вместо git tag?

Нет, это не рекомендуется. Git tags специально предназначены для маркирования версий и выпусков. Для версионирования используйте git tag, а не пустые коммиты:

# ✓ Правильно для версий:
$ git tag -a v1.0.0 -m "Release version 1.0.0"

# Если нужен маркер в истории, то:
$ git commit --allow-empty -m "release: v1.0.0"
$ git tag v1.0.0  # обе операции вместе

Заключение #

git commit --allow-empty — это специализированный инструмент для:

  • Запуска CI/CD без изменения кода
  • Создания маркеров в истории проекта
  • Тестирования hooks и процессов
  • Специальных сценариев в monorepo

Ключевые принципы:

  • Используйте только когда нужно (редко)
  • Всегда пишите понятное сообщение с префиксом (ci:, chore:, docs:)
  • Избегайте на общих ветках
  • Документируйте причину в сообщении коммита

Не используйте для:

  • Загрязнения истории без причины
  • Замены нормальных коммитов
  • Сообщений без содержания

Пустые коммиты — это мощный инструмент в правильных руках, но его нужно использовать осознанно и редко.

Дополнительная информация доступна в статьях /ru/git/git-commit/, /ru/git/git-hooks/ и /ru/git/conventional-commits/.