open atlas
↑ К треку
Git: от нуля до сеньора GIT · 10 · 01

День в настоящей команде

Полный дневной цикл в trunk-based команде, от и до: ветка от main, атомарные коммиты, rebase на origin/main для актуальности, push и открытие PR, правки ревью через fixup и force-with-lease, затем squash-merge и синхронизация. Все прошлые юниты складываются в один процесс.

GIT Senior ◷ 18 min
Уровень
ОсновыJuniorMiddleSenior

Ты изучил ветки, удалённые репозитории, rebase, reflog и подпись коммитов как отдельные навыки. В настоящей команде они не отдельные — это один непрерывный цикл, который ты прогоняешь несколько раз в день, почти не задумываясь. Цикл такой: короткоживущая ветка, оставайся актуальным, отгружай, повторяй. Сеньор прогоняет его так гладко, что git-команды исчезают и остаётся только работа.

К концу этого урока ты сможешь пройти весь дневной цикл trunk-based / GitHub-flow команды — от git switch -c до squash-merge и обратно к чистому main — и объяснить, почему каждый шаг держит ветку короткоживущей и без конфликтов.

Цель

После этого урока ты сможешь по памяти прогнать весь цикл GitHub-flow: ветка от main, атомарные коммиты, rebase на origin/main для актуальности, push и открытие PR, правки по ревью через --fixup и --force-with-lease, затем squash-merge и синхронизация — объясняя назначение каждого шага.

1

Начинай каждую единицу работы со свежей, актуальной ветки от main. Никогда не строй на устаревшей базе. Сначала fetch, затем режь ветку прямо от main удалённого репозитория, чтобы стартовать ровно оттуда, где прод:

git switch main
git pull --ff-only            # перемотать main к origin/main, отказать если разошлись
git switch -c feat/checkout-coupons origin/main

--ff-only — это страховочный ремень: если твой локальный main каким-то образом содержит коммиты, которых нет в origin/main, pull откажет вместо тихого создания merge-коммита. Ветка, названная по своей цели (feat/checkout-coupons), — это то, что унаследуют PR и итоговый squash-коммит.

2

Делай работу маленькими, атомарными коммитами — каждый цельный, обратимый шаг. Коммит должен собираться и рассказывать одну историю. Стейдж осознанно и пиши настоящее сообщение:

git add -p                    # стейдж по кускам, а не всё дерево вслепую
git commit -m "Validate coupon code before applying discount"
# ... ещё работа ...
git commit -m "Add expired-coupon error path + test"

Атомарные коммиты — не бюрократия: они делают возможными git revert, git bisect и код-ревью. Ревьюер читает последовательность ясных шагов; единый коммит «wip» на 600 строк не ревьюется.

3

Оставайся актуальным через rebase на origin/main — не давай ветке дрейфовать. Пока ты работаешь, коллеги мёржат в main. Ветка, разошедшаяся на дни, превращается в кошмар при слиянии. Подтягивай их работу под свою, чтобы твои коммиты всегда лежали поверх свежего ствола:

git fetch origin
git rebase origin/main        # переиграть твои коммиты поверх свежего main
# разреши конфликты сейчас, пока они маленькие, затем:
git rebase --continue

Rebase держит историю линейной и поднимает конфликты рано и маленькими порциями, вместо одного гигантского столкновения в момент слияния. Делай это хотя бы раз в день на живой ветке.

Почему это работает

Почему rebase’ить фичеветку, а не мёржить main в неё? Оба способа подтягивают свежий ствол, но merge, засорённый коммитами «Merge branch ‘main’ into feat/x», делает историю ветки шумной, а итоговый diff — трудночитаемым. Rebase даёт чистую стопку только твоих коммитов поверх текущего main — ровно то, что хочет видеть ревьюер, и ровно то, что squash-merge схлопывает чисто.

4

Push, открой PR и правь ревью через fixup + force-with-lease. Опубликуй ветку, открой pull request и дай CI отработать. Когда придёт ревью, не громозди сверху коммиты «учёл замечания» — вкладывай правки в тот коммит, которому они принадлежат:

git push -u origin feat/checkout-coupons      # первая публикация, ставит upstream
# ревью просит изменить коммит с валидацией:
git add -p
git commit --fixup=<sha-коммита-валидации>
git rebase -i --autosquash origin/main        # autosquash вставит fixup на место
git push --force-with-lease                    # безопасный force: откажет, если remote сдвинулся

--force-with-lease — это деталь, по которой нельзя торговаться: обычный --force затёр бы любой коммит, который коллега запушил в твою ветку с момента твоего последнего fetch. --force-with-lease проверяет, что remote всё ещё там, где ты думаешь, и иначе прерывается.

5

Когда CI зелёный и ревью одобрено — squash-merge и возврат к чистому main. Большинство trunk-based команд схлопывают ветку в один коммит на main — грязные промежуточные шаги ветки сворачиваются в одну чистую запись с заголовком по PR. Затем синхронизация и зачистка:

# слияние через кнопку PR «Squash and merge» (или gh pr merge --squash)
git switch main
git pull --ff-only            # принести новый squash-коммит в локальный main
git branch -d feat/checkout-coupons       # удалить локальную ветку (смёржена)
git push origin --delete feat/checkout-coupons   # удалить удалённую ветку

Цикл замкнут: main держит один аккуратный коммит, ни одна ветка не висит, и ты готов резать следующую фичу со свежей базы.

Разбор примера

Утро среды, одна фича, от начала до конца.

Ты берёшь «купоны на чекауте». Синхронизируешься и ветвишься: git switch main && git pull --ff-only && git switch -c feat/checkout-coupons origin/main. За утро ты кладёшь два атомарных коммита — валидация, затем путь просроченного купона с тестом. Перед обедом коллега мёржит рефакторинг модуля корзины в main. Ты запускаешь git fetch origin && git rebase origin/main; один маленький конфликт в cart.ts, разрешён за две минуты, потому что он свежий.

Ты пушишь с -u и открываешь PR. CI проходит; ревьюер просит ужать regex валидации. Вместо нового коммита ты делаешь git commit --fixup=<sha валидации>, git rebase -i --autosquash origin/main и git push --force-with-lease. Теперь PR показывает два чистых коммита, правка вложена в нужный. Приходит одобрение; ты жмёшь «Squash and merge». Назад на машине: git switch main && git pull --ff-only && git branch -d feat/checkout-coupons. В main один новый коммит, «Coupons at checkout (#812)», и твоё дерево чисто для следующей задачи. Полное время жизни ветки: меньше дня.

Частая ошибка

Классический провал — долгоживущая ветка. Фича, которая живёт две недели без rebase, уезжает от main так далеко, что итоговое слияние превращается в многочасовой марафон конфликтов, а diff слишком большой, чтобы честно его отревьюить. Лечение — дисциплина, а не инструменты: держи ветки маленькими, rebase’ь на origin/main ежедневно и мёржи в течение дня-двух. Короткоживущие ветки — это и есть весь смысл trunk-based разработки.

Проверь себя
Викторина

Во время ревью тебе нужно поправить более ранний коммит на запушенной фичеветке и обновить remote. Какой финальный push корректен и безопасен?

Итог

Дневной цикл trunk-based команды — это один непрерывный круг: ветка от свежего origin/main, атомарные коммиты, rebase на origin/main для актуальности, push и открытие PR, правки по ревью через --fixup плюс --force-with-lease и, наконец, squash-merge с синхронизацией обратно к чистому main. Каждый прошлый юнит — ветки, удалённые репозитории, rebase, безопасность force — складывается в этот один рабочий процесс, а дисциплина, что держит его вместе, — это короткоживущая и постоянно rebase’нутая ветка. Дальше ты прогонишь ту же машинерию под давлением, когда плохой merge покрасил main в красный.

Практика

Начни сверху. Задачи идут от простого к сложному: вспомнить факт, применить к случаю, затем senior-уровень. Открой, попробуй, потом открой ответ.

вспомнитьприменитьуглубить0 из 4 завершено

Что-то непонятно?

Задай вопрос по этому уроку. Вопросы анонимны и попадают напрямую автору — урок станет лучше.

хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources2
expand
  1. 01
  2. 02

Trademarks belong to their respective owners. Editorial reference only.