Git-воркфлоу и CI/CD
Переписывание истории (rebase, amend), продвинутые инструменты (reflog, bisect, cherry-pick, hooks), командная работа, сабмодули и CI/CD-пайплайны.
15 вопросов
JuniorДизайнОчень частоОпишите типичный жизненный цикл pull request — от ветки до merge — в команде, использующей код-ревью и CI. Затем объясните, какие свойства делают PR удобным и быстрым для ревью.
Опишите типичный жизненный цикл pull request — от ветки до merge — в команде, использующей код-ревью и CI. Затем объясните, какие свойства делают PR удобным и быстрым для ревью.
Ветка от main → push → открыть PR (что + зачем + как тестировать) → CI прогоняет lint/build/tests → ревьюеры комментят → автор правит → approval → merge. Лёгкий PR: маленький (<400 строк), одна тема, ясный заголовок, ссылка на issue, чистая история коммитов.
Типичные ошибки
- ✗Смешивать рефакторинг и фичу в одном PR — ревьюеры не видят саму фичу
- ✗Описание PR без контекста — ревьюеру приходится читать код, чтобы понять цель
- ✗Force-push во время ревью — комментарии теряют привязку
Уточняющие вопросы
- →Что такое stacked PR и когда он помогает с большими изменениями?
- →Как code-owners автоматизирует назначение ревьюеров?
MiddleТеорияОчень частоЧто такое CI/CD и какие преимущества это даёт разработчикам?
Что такое CI/CD и какие преимущества это даёт разработчикам?
CI: каждый push запускает автосборку и тесты, чтобы рано поймать баги интеграции. CD (Delivery): пайплайн производит артефакт и авто-деплоит в staging; production одобряют люди. CD (Deployment): полностью автоматический деплой в production при каждой зелёной сборке.
Типичные ошибки
- ✗Считать CI только запуском тестов — CI должен также запускать статический анализ, проверки покрытия и сканирование безопасности; выявлять больше проблем в конвейере
- ✗Запускать единственную задачу последовательно для всего — используйте параллельные задачи (линт, unit-тесты, интеграционные тесты, сборка) для сокращения длительности конвейера
- ✗Не кэшировать зависимости в CI — загрузка всех пакетов при каждом запуске тратит 2-5 минут; кэшируйте
~/.m2,build/илиnode_modulesмежду запусками
Уточняющие вопросы
- →В чём разница между конвейером развёртывания и конвейером релиза?
- →Как feature flags позволяют непрерывное развёртывание без раскрытия незавершённых функций пользователям?
MiddleДизайнОчень частоВаша feature-ветка отстала от main, и перед слиянием нужно подтянуть свежие изменения. Объясните, когда ветку стоит rebase, а когда merge — как каждый вариант влияет на форму истории и SHA коммитов, и какой из них небезопасен на общей ветке.
Ваша feature-ветка отстала от main, и перед слиянием нужно подтянуть свежие изменения. Объясните, когда ветку стоит rebase, а когда merge — как каждый вариант влияет на форму истории и SHA коммитов, и какой из них небезопасен на общей ветке.
Rebase переигрывает коммиты поверх целевой — линейная история, но переписывает SHA (никогда на общих ветках). Merge сохраняет топологию с merge-коммитом — точный audit trail. Типичный flow: rebase feature-ветки на свежий main, затем merge с --no-ff в main.
Типичные ошибки
- ✗Rebase'ить опубликованную ветку и заставлять всех восстанавливаться из reflog
- ✗Массово squash'ить merge и терять commit-level историю ревью
- ✗Избегать rebase полностью и получать запутанный merge-граф
Уточняющие вопросы
- →Что такое
git pull --rebaseи когда это правильный дефолт? - →Чем
git rebase --ontoотличается от обычного rebase?
JuniorТеорияЧастоЧто в общих чертах делает git rebase с вашими коммитами?
Что в общих чертах делает git rebase с вашими коммитами?
git rebase переносит коммиты вашей ветки поверх нового основания, создавая новые коммиты с новыми SHA. В отличие от merge, история получается линейной, без merge-коммита — но поскольку меняется идентичность коммитов, это безопасно только для ещё не опубликованных коммитов.
Типичные ошибки
- ✗Считать, что rebase и merge дают одинаковые объекты коммитов — rebase создаёт новые SHA, merge нет
- ✗Делать rebase ветки, которую коллеги уже стянули — это переписывает историю, на которую они опираются
- ✗Считать, что линейная история означает, что работа не шла параллельно
Уточняющие вопросы
- →Когда
merge— более безопасный выбор, чемrebase? - →Что позволяет
git rebase -iпомимо переноса коммитов?
JuniorТеорияЧастоЧем отличаются annotated и lightweight git-теги и как их использовать в релизах?
Чем отличаются annotated и lightweight git-теги и как их использовать в релизах?
Lightweight-тег (git tag v1.0) — именованный указатель на коммит. Annotated-тег (git tag -a v1.0 -m "...") — собственный объект с автором, датой, сообщением и опциональной GPG-подписью. Для релизов annotated — подписываемые первоклассные объекты.
Типичные ошибки
- ✗Использовать lightweight-теги для релизов — теряются при некоторых push'ах
- ✗Забыть
--tagsвgit push— теги не распространяются по умолчанию - ✗Смешивать стили semver-тегов (v1.0 vs 1.0) непоследовательно
Уточняющие вопросы
- →Как подписать тег GPG?
- →Что такое
git describeи как он использует теги?
MiddleТеорияЧастоЧто делает git cherry-pick и когда выбирать его вместо merge или rebase?
Что делает git cherry-pick и когда выбирать его вместо merge или rebase?
git cherry-pick <sha> применяет diff одного коммита поверх текущей ветки как новый коммит (новый SHA). Используйте для backport одного изменения (например, фикса в release). Избегайте для долгоживущих веток — дубли усложняют будущие merge.
Типичные ошибки
- ✗Cherry-pick'ать много коммитов вместо merge — остаются дубли
- ✗Cherry-pick'ать merge-commit без
-m Nдля выбора родителя - ✗Cherry-pick'ать зависящие друг от друга коммиты в неправильном порядке
Уточняющие вопросы
- →Как cherry-pick'нуть диапазон коммитов?
- →Что делает
cherry-pick -x?
MiddleТеорияЧастоКак изменить коммит (amend vs fixup)?
Как изменить коммит (amend vs fixup)?
git commit --amend заменяет последний коммит новым — переписывает историю, поэтому используйте до push. Для более глубоких коммитов: git commit --fixup <hash>, затем git rebase -i --autosquash <hash>^, или git rebase -i HEAD~N с пометкой edit.
Типичные ошибки
- ✗Использовать
--amendна уже запушенном коммите — требуетgit push --force, что перезаписывает remote и ломает всех, кто стянул исходный коммит - ✗Забывать
--no-editс--amendпри изменении только файлов —git commit --amend --no-editдобавляет подготовленные изменения без открытия редактора - ✗Запускать
git rebase -iс слишком большим диапазоном — включайте только коммиты, которые собираетесь изменить; больший диапазон увеличивает риск конфликтов
Уточняющие вопросы
- →В чём разница между
squashиfixupв интерактивном rebase? - →Как изменить сообщение коммита, который не является последним?
MiddleТеорияЧастоОбъясните интерактивный rebase и когда его использовать.
Объясните интерактивный rebase и когда его использовать.
git rebase -i <base> открывает редактор со списком коммитов от <base> до HEAD с действиями: pick, reword, edit, squash, fixup, drop. Используйте для чистки WIP перед PR, переупорядочивания или переноса на обновлённый main. Правило: rebase только локальных коммитов.
Типичные ошибки
- ✗Делать rebase запушенных коммитов на общей ветке — ваш
git push --forceперезаписывает историю remote и заставляет коллег делать reset или re-clone - ✗Забывать подготовить изменения и запустить
git rebase --continueпосле паузыedit— оставляет rebase в подвешенном состоянии - ✗Использовать rebase для 'скрытия' багов — squash коммитов не удаляет баги; не используйте rebase для маскировки истории отладки изучаемого бага
Уточняющие вопросы
- →Как работает
git rebase --onto <newbase> <oldbase> <branch>? - →В чём разница между
git merge --squashи squash вgit rebase -i?
SeniorТеорияЧастоОпишите стратегии ветвления (Gitflow, trunk-based и др.).
Опишите стратегии ветвления (Gitflow, trunk-based и др.).
Gitflow: main + develop; features от develop, релизы — release/x.y, хотфиксы от main. Trunk-based: все коммитят в main через ветки <1 дня; feature flags скрывают незавершённое. GitHub Flow: feature-ветка от main, PR, merge, деплой.
Типичные ошибки
- ✗Выбирать Gitflow для небольшой команды — накладные расходы Gitflow оправданы для продуктов с несколькими линейками релизов; небольшие команды, работающие над веб-сервисами, должны использовать GitHub Flow или TBD
- ✗Feature-ветки, живущие неделями — долгоживущие ветки расходятся с main и вызывают болезненные конфликты слияния; разбивайте функции на меньшие интегрируемые инкременты
- ✗Не удалять слитые ветки — устаревшие ветки загромождают репозиторий и путают разработчиков; автоматизируйте удаление в CI-системе после слияния
Уточняющие вопросы
- →Как feature flags обеспечивают trunk-based development и каковы их операционные риски?
- →Когда монорепо лучше, чем полирепо, и чем отличается стратегия ветвления?
SeniorДизайнЧастоРастущая организация решает, держать ли все сервисы в одном монорепо или разнести их по множеству маленьких репозиториев по сервису. Сравните оба варианта по сквозным изменениям, масштабированию сборки, переиспользованию кода, границам владения и версионированию зависимостей, и объясните, чего стоит каждый выбор.
Растущая организация решает, держать ли все сервисы в одном монорепо или разнести их по множеству маленьких репозиториев по сервису. Сравните оба варианта по сквозным изменениям, масштабированию сборки, переиспользованию кода, границам владения и версионированию зависимостей, и объясните, чего стоит каждый выбор.
Монорепо: атомарные cross-cutting изменения, общий тулинг, простой code sharing — но нужны масштабируемые сборки (Bazel/Buck), грубые permissions. Полирепо: чёткие границы, меньший scope, стандартный тулинг — но cross-cutting = много PR, версионирование сложнее.
Типичные ошибки
- ✗Внедрять монорепо без инвестиций в сборку / sparse checkout
- ✗Полирепо с lockstep-версионированием между многими — худшее из обоих миров
- ✗Хранить очень разные по размеру вещи (фронт + большие данные) в одном дереве без LFS
Уточняющие вопросы
- →Что такое sparse checkout и как он масштабирует монорепо?
- →Сравните Bazel и Buck для монорепо.
JuniorТеорияИногдаЧто такое Conventional Commits и что это даёт?
Что такое Conventional Commits и что это даёт?
Формат: <type>(<scope>): <description> с типами feat, fix, chore, docs и т.д. Footer BREAKING CHANGE: (или !) сигналит о несовместимости. Инструменты вроде semantic-release парсят лог и авто-бампят SemVer (feat = minor, fix = patch, breaking = major).
Типичные ошибки
- ✗Непоследовательно смешивать типы и scopes — ломает автоматизацию
- ✗Ставить
BREAKING CHANGE:для не-breaking refactor'ов - ✗Длинные, многоцелевые коммиты — один коммит = одна тема
Уточняющие вопросы
- →Как semantic-release использует историю коммитов для публикации версий?
- →Чем SemVer отличается от CalVer?
MiddleТеорияИногдаКак работает git bisect и когда его использовать?
Как работает git bisect и когда его использовать?
git bisect делает бинарный поиск по истории, чтобы найти коммит с багом. Указываете known-good и known-bad; bisect делает checkout середины, вы помечаете good/bad, поиск сужается за log₂ шагов. Автомат: git bisect run ./test.sh.
Типичные ошибки
- ✗Помечать коммит good/bad после нестабильного теста
- ✗Не выполнить
git bisect resetи застрять в detached HEAD - ✗Bisect через merge-commit без
--first-parent, когда нужна граница merge
Уточняющие вопросы
- →Как
git bisect skipпомогает при не собирающихся коммитах? - →Что такое
git blameи когда он дополняет bisect?
MiddleТеорияИногдаЧто такое git hooks и чем отличаются client-side и server-side?
Что такое git hooks и чем отличаются client-side и server-side?
Hooks — скрипты в .git/hooks/ (или hooksPath), срабатывающие на события. Client-side: pre-commit (линтер), commit-msg (валидация), pre-push (тесты). Server-side: pre-receive, update, post-receive (политика на push). Husky распространяет их через репо.
Типичные ошибки
- ✗Класть медленные тесты в
pre-commit— разработчики отключат hooks, чтобы работать - ✗Забывать, что
--no-verifyпропускает hooks — нельзя полагаться только на клиентские для безопасности - ✗Использовать server-side hooks там, где CI-пайплайн виднее и проще поддерживать
Уточняющие вопросы
- →Как
core.hooksPathпозволяет поставлять hooks через репозиторий? - →Почему server-side hooks не заменяют branch protection на хостинге?
MiddleТеорияИногдаЧто такое git reflog и как он спасает от «потерянных» коммитов?
Что такое git reflog и как он спасает от «потерянных» коммитов?
Reflog — per-ref лог всех позиций HEAD и tip'ов веток за последние 90 дней. После reset --hard, force-push или rebase прежние коммиты доступны через git reflog show HEAD. Восстановить: git reset --hard <sha>. Только локально.
Типичные ошибки
- ✗Паниковать после
reset --hard, не проверив reflog - ✗Забывать, что reflog только локальный
- ✗Позволить
git gcстереть старые записи, когда они нужны
Уточняющие вопросы
- →Сколько reflog хранит записи по умолчанию?
- →Как восстановить удалённую ветку через reflog?
MiddleТеорияИногдаКак работают git submodules и какие у них альтернативы?
Как работают git submodules и какие у них альтернативы?
Submodule привязывает вложенный репо к конкретному SHA внутри родителя — .gitmodules хранит URL, дерево родителя хранит SHA. Плюсы: точное pinning. Минусы: clone требует --recursive, обновление двухшаговое, конфликты путают. Альтернативы: монорепо, Conan/vcpkg.
Типичные ошибки
- ✗Клонировать без
--recursiveи получать пустые директории submodule - ✗Обновлять ветку submodule без коммита нового SHA в родитель
- ✗Позволять URL submodule расходиться между конфигами разработчиков
Уточняющие вопросы
- →Чем
git subtreeотличается от submodules? - →Что такое sparse-checkout и когда он помогает в монорепе?