graphite stacked PR поверх git

gt — Graphite CLI

Инструмент для работы со стеками небольших веток и pull request'ов поверх Git

⚠️ Проверить по документации. Graphite (gt) — внешний инструмент, которого нет в лекциях курса. Это материал-дополнение. Синтаксис и флаги быстро развиваются — сверяйтесь с официальной документацией: graphite.com/docs и gt --help.

Описание

gt (Graphite CLI) — это надстройка над Git, которая делает удобной работу со стеками веток (stacked branches / stacked PRs). Идея: вместо одной большой ветки с десятком коммитов вы создаёте цепочку маленьких веток, где каждая следующая ответвляется от предыдущей, и для каждой открывается отдельный небольшой pull request. Так ревью идёт по одной логической части за раз, а не одним гигантским диффом.

Главная боль, которую решает gt, — это ручной rebase цепочки веток. Когда вы меняете нижнюю ветку стека, все ветки выше нужно перебазировать. В чистом Git это серия git rebase вручную; в Graphite — одна команда gt restack (или автоматически при gt modify). Graphite хранит метаданные о том, какая ветка чьим «родителем» является.

┌─ feat/api-endpoint PR #3 (вершина стека, gt top) │ ├─ feat/service-layer PR #2 │ ├─ feat/db-model PR #1 (низ стека, gt bottom) │ main ──────────────────────────── (trunk)

gt не заменяет Git — под капотом это всё те же ветки и коммиты. Любой репозиторий с Graphite остаётся обычным Git-репозиторием, и команды git продолжают работать.

Установка и инициализация

# Установка (npm) — нужен Node.js npm install -g @withgraphite/graphite-cli # Через Homebrew (macOS / Linux) brew install withgraphite/tap/graphite # Проверить версию gt --version # Инициализировать Graphite в репозитории (выбрать trunk-ветку, напр. main) gt init # Авторизоваться для создания/обновления PR на GitHub gt auth --token <ВАШ_ТОКЕН>
trunk — это ваша основная ветка (main или master), от которой растут стеки. gt init спрашивает её один раз и запоминает.

Базовый цикл работы

# 1. Создать первую ветку стека с закоммиченными изменениями git add . gt create feat/db-model -m "feat: add Task model" # ... или коротко: застейджить всё и закоммитить одной командой gt create feat/db-model -a -m "feat: add Task model" # 2. Сверху создать вторую ветку — она стекается на первую gt create feat/service-layer -a -m "feat: add task service" # 3. Посмотреть стек gt log short # алиас: gt ls # 4. Перейти вниз, поправить нижнюю ветку gt down # на feat/db-model # ...правим код... gt modify -a # amend + автоматический restack веток выше # 5. Отправить весь стек на GitHub (создать/обновить PR для каждой ветки) gt submit --stack # алиас: gt ss # 6. После merge нижнего PR — синхронизироваться и удалить влитые ветки gt sync

Все команды gt

Инициализация и настройка

КомандаНазначение
gt initВключить Graphite в репозитории, выбрать trunk-ветку. Флаги: --trunk, --reset
gt auth -t <token>Добавить токен GitHub для создания/обновления PR
gt configНастройки Graphite CLI
gt aliasesПросмотр/редактирование коротких алиасов команд

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

КомандаНазначение
gt create [name]Создать новую ветку поверх текущей и закоммитить застейдженные изменения. Флаги: -a/--all, -m/--message, -i/--insert (вставить в середину стека), -p/--patch
gt modifyИзменить коммит текущей ветки (amend) или добавить новый коммит, после чего автоматически перестроить (restack) ветки выше. Флаги: -a/--all, -c/--commit (новый коммит вместо amend), -m, -e/--edit
gt absorb«Впитать» застейдженные изменения в соответствующие коммиты стека автоматически. Флаги: -a, -d/--dry-run, -p/--patch
gt squashСхлопнуть все коммиты текущей ветки в один. Флаги: -m, -n/--no-edit
gt splitРазбить ветку на несколько. Режимы: --by-commit, --by-hunk, --by-file. Алиас: sp
gt foldВлить изменения ветки в её родителя и перестроить потомков. Флаги: -k/--keep

Навигация по стеку

КомандаНазначение
gt up [n]Перейти на дочернюю ветку (вверх по стеку). При нескольких детях — спросит
gt down [n]Перейти на родительскую ветку (вниз по стеку)
gt topНа вершину стека
gt bottomНа ближайшую к trunk ветку
gt checkout [branch]Переключиться на ветку; без аргумента — интерактивный выбор. Алиас: co. Флаг -s/--stack
gt parent / gt childrenПоказать родителя / детей текущей ветки
gt log · gt log short · gt log longПоказать дерево стеков. Алиасы: ls (short), ll (long)
gt info [branch]Информация о ветке (тело PR, дифф, статистика)

Синхронизация и отправка

КомандаНазначение
gt submitИдемпотентно отправить (force-push) ветки текущего стека и создать/обновить PR. Алиас gt ss = gt submit --stack. Флаги: --stack, -d/--draft, -r/--reviewers, --dry-run, -m/--merge-when-ready
gt syncСинхронизировать ветки с remote, предложить удалить ветки влитых/закрытых PR. Флаги: -f/--force, --restack
gt restackПерестроить (rebase) стек так, чтобы у каждой ветки родитель был в её истории. Флаги: -u/--upstack, -d/--downstack, -o/--only
gt get [branch]Скачать ветки стека из remote (для ревью чужого стека). Флаг --checkout
gt moveПеребазировать текущую ветку на другую цель и перестроить потомков. Флаг -o/--onto
gt reorderПоменять порядок веток в стеке через редактор
gt pr [branch]Открыть страницу pull request ветки

Трекинг веток

КомандаНазначение
gt track [branch]Начать отслеживать существующую Git-ветку в Graphite (выбрать родителя). Флаг -p/--parent
gt untrack [branch]Перестать отслеживать ветку (ветка в Git остаётся)
gt rename [name]Переименовать ветку и обновить метаданные
gt delete [name]Удалить ветку и метаданные Graphite, перестроить детей. Флаги: --upstack, --downstack
gt trunkПоказать trunk текущей ветки

Состояние и отмена

КомандаНазначение
gt continueПродолжить команду Graphite, остановленную конфликтом rebase (после git add)
gt abortПрервать остановленную конфликтом команду
gt undoОткатить последние изменения, сделанные Graphite
gt freeze / gt unfreezeЗапретить / разрешить локальные изменения ветки
gt dashОткрыть веб-дашборд Graphite

Паттерны использования

Создать стек из трёх веток

git add .
gt create feat/db-model     -a -m "feat: model"
gt create feat/service      -a -m "feat: service"
gt create feat/api          -a -m "feat: API"
gt log short   # увидеть всю цепочку

Поправить нижнюю ветку и обновить весь стек

gt bottom            # вниз стека
# ...правки по ревью...
gt modify -a         # amend + авто-restack
                     # веток выше — одной командой
gt ss                # переотправить PR стека

Подтянуть свежий main под весь стек

gt sync              # обновит trunk и
                     # перебазирует стек,
                     # предложит снести влитые ветки

Разрешить конфликт во время restack

# restack остановился на конфликте
# ...правим файлы...
git add <файлы>
gt continue          # продолжить
# или: gt abort — откатить

Вставить ветку в середину стека

gt checkout feat/service
gt create feat/validation -i -a \
  -m "feat: input validation"
# -i вставит ветку между service и api

Перевести существующие git-ветки в стек

git switch feature-big
gt track              # выбрать родителя
gt split --by-commit  # разбить на мелкие ветки

Шпаргалка: gt ↔ чистый Git

GraphiteПримерный эквивалент в Git
gt create -a -m "msg"git switch -c new && git add -A && git commit -m "msg" (+ запись родителя)
gt modify -agit commit -a --amend + ручной git rebase всех веток выше
gt restackсерия git rebase по цепочке родителей
gt up / gt downgit switch <child> / git switch <parent>
gt submit --stackgit push --force-with-lease каждой ветки + открыть PR вручную
gt syncgit fetch + git rebase origin/main + удаление влитых веток

Советы и подводные камни

Маленькие ветки = быстрое ревью. Главная ценность стеков — не сам инструмент, а привычка дробить большую задачу на маленькие логические PR. Ревьюеру проще принять 5 диффов по 50 строк, чем один на 250.
gt submit делает force-push. Это нормально для ваших feature-веток стека, но никогда не направляйте стек так, чтобы перезаписать общий main. Graphite пушит каждую ветку стека отдельно — следите, что trunk не входит в отправляемый набор.
Конфликты всё равно бывают. gt автоматизирует rebase, но не отменяет конфликты слияния. При остановке решайте их как обычно (git add), затем gt continue.
⚠️ Проверить по документации. Набор команд и флагов Graphite меняется между версиями. Перед использованием в реальном проекте сверьтесь с gt <команда> --help и официальным справочником команд.