Контроль версий
Основы Git — merge и rebase, fetch и pull, работа через fork/pull request и модели ветвления.
9 вопросов
JuniorТеорияОчень частоЧто такое Git и какую основную задачу решает система контроля версий?
Что такое Git и какую основную задачу решает система контроля версий?
Git — это распределённая система контроля версий: она записывает снимки файлов проекта как коммиты, у каждого есть родитель, образуя историю, которую можно просматривать, откатывать и ветвить. Она позволяет многим работать параллельно в изолированных ветках и сливать изменения, храня полную локальную копию репозитория, так что большинству операций не нужен сервер.
Типичные ошибки
- ✗Называть Git централизованным — он распределённый, каждый клон хранит всю историю
- ✗Путать Git с GitHub, сервисом хостинга, построенным поверх него
- ✗Думать, что коммит хранит только diff, а не полный снимок с родителем
Уточняющие вопросы
- →Что именно идентифицирует SHA-хеш коммита в Git?
- →Почему большинство операций Git работают без сетевого соединения?
MiddleТеорияЧастоЧем git merge отличается от git rebase и когда rebase стоит избегать?
Чем git merge отличается от git rebase и когда rebase стоит избегать?
merge соединяет две ветки новым merge-коммитом, сохраняя реальную историю как нелинейный граф. rebase переносит ваши коммиты на новую базу, переписывая их с новыми хешами и давая линейную историю. Избегайте rebase коммитов, уже отправленных и общих — переписывание опубликованной истории вынуждает всех восстанавливаться, ведь их копии теперь расходятся с вашей.
Типичные ошибки
- ✗Считать, что rebase сохраняет исходные хеши коммитов
- ✗Делать rebase ветки, которую другие уже забрали и развили
- ✗Думать, что merge и rebase дают одинаковую форму истории
Уточняющие вопросы
- →Что позволяет
git rebase --onto, чего не может обычный rebase? - →Чем fast-forward merge отличается от merge, создающего коммит?
MiddleТеорияЧастоЧто делают git reset --soft, --mixed и --hard с HEAD, индексом и рабочим деревом?
Что делают git reset --soft, --mixed и --hard с HEAD, индексом и рабочим деревом?
Все три перемещают HEAD ветки на целевой коммит и отличаются лишь глубиной. --soft двигает только HEAD, изменения остаются в индексе. --mixed сбрасывает и индекс, оставляя изменения незастейдженными. --hard сбрасывает HEAD, индекс и рабочее дерево, отбрасывая незакоммиченную работу. Reset переписывает указатель ветки — локальная правка истории.
Типичные ошибки
- ✗Думать, что
--softотбрасывает изменения, хотя он оставляет их в индексе - ✗Считать, что reset добавляет обратный коммит, как
revert - ✗Делать
reset --hardна коммитах, уже отправленных в общую ветку
Уточняющие вопросы
- →Как восстановить коммиты, которые
reset --hardбудто бы выбросил? - →Почему для отмены коммита в
mainпредпочитаютgit revert, а неreset?
JuniorКодИногдаИсправьте сообщение последнего коммита и добавьте забытый файл через git commit --amend
Исправьте сообщение последнего коммита и добавьте забытый файл через git commit --amend
Добавьте забытый файл в индекс, затем git commit --amend -m 'фикс'. Amend заменяет последний коммит, вобрав config.yml и новое сообщение, — второй коммит не создаётся. Но amend переписывает коммит новым хешем: после отправки в общую историю он потребует push --force, ломающий других — правьте лишь неопубликованные коммиты.
Типичные ошибки
- ✗Править amend-ом коммит, который уже отправлен и стал общим
- ✗Думать, что amend добавляет новый коммит, а не заменяет последний
- ✗Считать, что amend меняет только сообщение, но не застейдженные файлы
Уточняющие вопросы
- →Почему amend уже отправленного коммита вынуждает делать
push --force? - →Чем полезен
git commit --amend --no-edit, когда вы лишь добавляете файл?
MiddleТеорияИногдаЧто такое модель ветвления Git вроде git-flow и какую задачу она решает?
Что такое модель ветвления Git вроде git-flow и какую задачу она решает?
Модель ветвления — это согласованное соглашение о том, какие ветки существуют и как изменения движутся между ними. git-flow использует долгоживущие main и develop плюс короткоживущие feature, release и hotfix. Она решает координацию: команда знает, где начинается работа, как она стабилизируется к релизу и как срочные правки попадают в продакшен, не мешая текущей разработке.
Типичные ошибки
- ✗Считать git-flow функцией Git, а не командным соглашением
- ✗Забывать, что hotfix-ветки идут в продакшен и обратно в develop
- ✗Полагать, что любому проекту нужен git-flow, а не более простая trunk-based модель
Уточняющие вопросы
- →Чем trunk-based разработка отличается от git-flow и когда она предпочтительнее?
- →Почему hotfix-ветка в git-flow сливается и в
main, и вdevelop?
MiddleТеорияИногдаЧто делает git cherry-pick и когда его применять?
Что делает git cherry-pick и когда его применять?
git cherry-pick <commit> применяет изменения одного коммита на текущую ветку как новый коммит с новым хешем. Используют для переноса исправления между ветками без слияния всей ветки — например, hotfix в релизную ветку. Возможны конфликты; флаг -x дописывает исходный хеш в сообщение для прослеживаемости.
Типичные ошибки
- ✗Думать, что cherry-pick переиспользует хеш исходного коммита
- ✗Считать, что он сливает всю исходную ветку, а не один коммит
- ✗Ожидать, что он удалит коммит из исходной ветки
Уточняющие вопросы
- →Чем
git cherry-pickотличается отgit mergeтой же ветки? - →Что флаг
-xдобавляет в сообщение перенесённого коммита?
MiddleТеорияИногдаЧем git fetch отличается от git pull и что такое submodule?
Чем git fetch отличается от git pull и что такое submodule?
fetch скачивает новые коммиты с удалённого репозитория в ваши remote-tracking ветки, не трогая рабочую ветку, так что можно сперва всё просмотреть. pull — это fetch с последующим merge (или rebase) в текущую ветку, обновляя её за один шаг. Submodule — это вложенный репозиторий, закреплённый на конкретном коммите, позволяющий одному репозиторию встроить другой на фиксированной версии.
Типичные ошибки
- ✗Думать, что fetch меняет рабочую ветку — он лишь обновляет tracking-ссылки
- ✗Не понимать, что pull — это fetch плюс автоматический merge или rebase
- ✗Считать, что submodule отслеживает последний коммит, а не закреплённый
Уточняющие вопросы
- →Как заставить
git pullпо умолчанию делать rebase вместо merge? - →Почему после клонирования репозитория с submodule нужен
git submodule update?
MiddleТеорияИногдаЧто делает git rebase и что добавляет интерактивный rebase?
Что делает git rebase и что добавляет интерактивный rebase?
git rebase <base> переносит коммиты на новую базу по одному, давая каждому новый хеш и линейную историю. Конфликты решаются по каждому переносимому коммиту. Интерактивный rebase (-i) позволяет переупорядочить, склеить, отредактировать, удалить или переименовать коммиты перед переносом.
Типичные ошибки
- ✗Думать, что rebase сохраняет исходные хеши коммитов
- ✗Считать, что rebase создаёт merge-коммит, как
merge - ✗Делать rebase коммитов, уже отправленных в общую ветку
Уточняющие вопросы
- →Почему нельзя делать rebase коммитов, которые отправлены и стали общими?
- →Как
git rebase --ontoпереносит диапазон коммитов на несвязанную базу?
MiddleКодИногдаВы отправили сломанный коммит в общий main — отмените его безопасно, не переписывая историю
Вы отправили сломанный коммит в общий main — отмените его безопасно, не переписывая историю
Добавьте обратный коммит через git revert a1b2c3d, затем git push. revert фиксирует обратный дифф плохого коммита новым коммитом: сломанное изменение отменяется, опубликованные коммиты на месте. История дополняется, а не переписывается — коллегам достаточно git pull, без force-push. reset или push --force — лишь для локальных коммитов.
Типичные ошибки
- ✗Хвататься за
reset --hardиpush --forceна общей ветке - ✗Думать, что
revertудаляет коммит, а не добавляет обратный - ✗Править уже отправленный коммит через
commit --amend
Уточняющие вопросы
- →Чем отличается revert merge-коммита и почему ему нужен флаг
-m? - →Когда переписывание истории через
resetвсё же допустимо?