Рабочие инструменты

Правила репозитория (.gitcito.json)

В каждом проекте есть правила, которые из кода не выводятся. Никогда не пушить напрямую в release/*. Области коммитов — api, web и infra, и больше никаких. Нужен Node 20, выгруженные подмодули и .env, скопированный из .env.example, иначе ничего не запустится. Такие правила живут в README, который никто не перечитывает, в упавшей сборке CI или в голове того, кто здесь дольше всех.

.gitcito.json — место, где репозиторий их записывает, чтобы инструмент мог на них опираться. Файл лежит в корне репозитория, версионируется как любой другой и потому путешествует вместе с клоном: все, кто открывает проект, получают одни и те же правила, а новый человек получает их в первый день, а не при первом отклонённом push.

Файл полностью необязателен. Репозиторий без него ведёт себя ровно так же, как раньше.

Писать его вручную не обязательно: чату репозитория передают схему этого файла, поэтому добавь ссылки на задачи вида JIRA-1234 или защити release-ветки возвращается как файловое действие, которое можно просмотреть.

Вкладка Config репозитория со строками доктора и секциями правил

Где его править

Шестерёнка рядом с инструментами панели → Config. Этот редактор пишет файл в рабочее дерево; больше он нигде не хранится, поэтому сделайте коммит, чтобы поделиться правилами с командой.

Если файла ещё нет, Прочитать репозиторий предложит его на основе того, что уже есть: .nvmrc или engines.node, .gitmodules, filter=lfs в .gitattributes, .env.example без соседнего .env, ветки, которые вы уже защищаете локально, и области из последних 500 заголовков коммитов. Ничего не пишется, пока вы не сохраните. В терминале то же самое делает gitcito config init (см. командную строку).

Что может быть в файле

{
  "version": 1,
  "protect": ["main", "release/*"],
  "links": {
    "tickets": [
      { "match": "\\b[A-Z][A-Z0-9]+-\\d+\\b", "url": "https://tracker.example.com/browse/$0", "label": "Jira" }
    ]
  },
  "commit": {
    "scopes": ["api", "web", "infra"],
    "ticketFromBranch": true,
    "trailers": ["Refs: {ticket}"]
  },
  "requires": {
    "node": ">=20",
    "hooksPath": ".husky",
    "submodules": true,
    "lfs": true,
    "files": [{ "path": ".env", "from": ".env.example", "why": "Базовый адрес API и токен для разработки" }]
  },
  "checklist": {
    "push": ["Прогнать интеграционные тесты на staging"]
  }
}
Поле Что делает
version Должно быть 1. Файл более новой схемы игнорируется целиком, а не угадывается.
protect Имена веток, * совпадает с любой последовательностью символов. Добавляются к веткам, которые вы защищаете локально — см. защищённые ветки.
links.tickets Регулярное выражение и шаблон адреса. $0 — всё совпадение, $1…$9 — его группы. Совпадения в заголовках и телах коммитов становятся ссылками.
commit.scopes Области, которые предлагает композитор вместо свободного поля. Их объявление также превращает неизвестную область в gitcito commit-check из стилевого совета в ошибку.
commit.ticketFromBranch Подставляет ключ тикета из имени ветки (feature/ABC-123-thing → ABC-123) — но только в пустой композитор, никогда поверх того, что вы печатаете.
commit.trailers Строки, дописываемые в тело коммита. {ticket} и {branch} подставляются; строка, чей плейсхолдер нечем заполнить, отбрасывается, а не пишется наполовину.
requires.* Что нужно работающему клону. Каждая запись становится строкой доктора, ниже.
checklist.push Свободный текст, показываемый один раз за сессию перед первым push.

Доктор

requires — та часть, которая отвечает на «я склонировал, и оно не запускается». Gitcito проверяет её при открытии репозитория и показывает чип со стетоскопом в строке состояния, когда что-то не так. Клик открывает вкладку Config на строках доктора; Проверить снова запускает их заново.

Проверка Проходит, когда Чинится
node node в вашем PATH удовлетворяет спецификации —
submodules Ни один подмодуль не остался без checkout git submodule update --init --recursive
lfs git-lfs установлен, а отслеживаемые файлы — настоящее содержимое, а не текст указателя git lfs pull
hooksPath core.hooksPath совпадает с объявленным путём установкой core.hooksPath
files Файл существует копированием из from, если он есть

Два намеренных ограничения. Предупреждение никогда не значит «сломано» — оно значит, что доктор не смог что-то определить (нечитаемая спецификация Node проходит, вместо того чтобы выдумывать ошибку, с которой вы ничего не сделаете), и предупреждения не роняют gitcito doctor в CI. И починка никогда не приходит из файла: набор выше — это весь набор, закрытый на этапе компиляции. Конфигурация передаёт ему значение — путь для копирования, значение для core.hooksPath — и никогда команду.

Копирование никогда не перезаписывает: отсутствие файла — ровно та причина, по которой эта строка здесь.

Коммиты

Когда объявлены commit.scopes, кнопка области в композиторе предлагает этот список вместо свободного поля — разница между feat(renderer) и feat(rendererr). ticketFromBranch и trailers заполняют механические части сообщения, а links.tickets возвращает ключам вид ссылок везде, где показан коммит.

Те же правила действуют и вне окна: gitcito commit-check читает этот файл, поэтому хук commit-msg и CI требуют ровно то, что предлагает композитор. См. командную строку и коммиты.

Список перед push

checklist.push показывается как подтверждение перед первым push в сессии, по строке на пункт. Это место для того, что действительно требует суждения — кто- нибудь предупредил поддержку? — потому что Gitcito никогда не проверяет это за вас. Это напоминания, а не запреты: прочитали и запушили либо отменили. Показывается один раз на репозиторий за сессию, потому что диалог при каждом push — это диалог, который никто не читает.

Почему он не может вам навредить

Файл приходит вместе с репозиторием, то есть от того, кто репозиторий написал. Он считается недоверенным содержимым, как и сообщение коммита:

  • Ничего в нём не выполняется. Нет поля, хранящего команду, а починки доктора — фиксированный список.
  • Он может только добавлять ограничения. protect объединяется с вашим локальным списком: репозиторий может защитить больше, чем выбрали вы, но никогда не отговорит вас что-то защищать. Ни одно поле не выключает защиту.
  • Пути не могут выйти за репозиторий. Абсолютные пути, .., ~, буквы дисков и всё, что касается .git, отклоняются — и проверяются ещё раз там, где строка становится настоящим путём.
  • Ссылки должны быть http(s). Ничего другого системному открывателю адресов не передаётся.
  • У всего есть предел — длина списков, строк, шаблонов, — чтобы враждебный репозиторий не вставил стену текста в диалог и тысячу чипов в панель.

Плохое поле отбрасывается, а не рушит всё. Остальная часть файла продолжает действовать, а отброшенное перечислено под заголовком Проигнорировано Gitcito во вкладке Config вместе с причиной. Единственное исключение — невалидный JSON или неизвестная version: там спасать нечего.

Чего он намеренно не делает

  • Ни команд, ни скриптов, ни хуков. Для этого есть хуки, и это решение, которое вы принимаете для каждого клона.
  • Ни правил на ветку, ни на человека. Один файл, один набор правил.
  • Он не заменяет CI. Список — это текст; доктор проверяет окружение, а не вашу работу.
  • Он ничего не может ослабить. Все защиты Gitcito остаются вашими.

См. также: Настройки репозитория · Командная строка · Коммиты · Хуки и .gitignore

Улучшить этот перевод на GitHub