К списку уроков
Блок 3 · Git и первый проект

Урок 5. Как попасть в реальный проект с автотестами?

Git, GitHub и Pull Request

Темы урока

Зачем Git автоматизатору, commit / branch / pull / merge, конфликт слияния, reset vs revert, cherry-pick, rebase, stash, Pull Request

Видео урока

Пройти тест по уроку

Конспект урока

Конспект — Урок 5: Как попасть в реальный проект с автотестами?

Главное за урок

Git — не «сохранить файл», а история снимков, ветки и совместная работа. Коммит, ветка, pull и PR — ежедневный минимум. Рядом с ними живут опасные операции: они переписывают историю или переносят чужие коммиты. Их отрабатывают в тренажёре, не на общем main.

После конспекта вы должны отличать reset от revert, понимать cherry-pick и rebase, знать, когда stash, и читать конфликт слияния.


Git и хостинги

Git — движок контроля версий на вашей машине. GitHub — один из хостингов удалённых репозиториев, не синоним Git.

Примеры
СКВ (движок) Git (раньше SVN, CVS)
Хостинг GitHub, GitLab, Bitbucket, SourceCraft

commit / branch / PR устроены так же на любом хостинге. Меняется оболочка, не идеи.


Базовые команды: снимок и ветка

Коммит — снимок проекта в момент времени плюс сообщение зачем. Это не Save в редакторе.

git status                 # что изменилось
git add tests/login.spec.ts
git commit -m "fix: ждать ошибку на неверном пароле"

git add выбирает, что войдёт в снимок (staging). git commit фиксирует выбранное. В сообщении пиши зачем, не «fix» и не то, что и так видно в diff.

Ветка — параллельная линия истории. main — стабильная. Своя ветка — черновик: пока вы в ней, чужой main не ломаете.

git checkout -b feature/login-error   # создать и переключиться
git branch                            # список; звёздочка — текущая

Два шага вместо одного: git branch feature/login-errorgit checkout feature/login-error. То же: git switch -c feature/login-error.


Подтянуть чужое и слить: pull, merge

Локальная копия — снимок на момент клона, не живая синхронизация. Пока вы работали, main на сервере мог уйти вперёд.

git checkout main
git pull origin main

git pull = git fetch (скачать коммиты) + git merge (влить в текущую ветку). Новую ветку заводят от свежего main, иначе потом лишние конфликты.

Merge соединяет две линии: «взять изменения из той ветки сюда».

git checkout main
git merge feature/login-error

Чистый merge — Git сам сложил истории. Если обе ветки правили одну и ту же строку — конфликт.


Конфликт слияния

Git не гадает, чью строку оставить. В файле маркеры:

<<<<<<< HEAD
ожидаем текст «Неверный пароль»
=======
ожидаем статус 401
>>>>>>> feature/login-error
  • <<<<<<< HEAD — то, что у вас сейчас.
  • ======= — разделитель.
  • >>>>>>> — то, что пришло из другой ветки.

Это не поломка репозитория, а выбор руками: оставить одно, другое или оба. Потом:

# правите файл, убираете маркеры
git add путь/к/файлу
git commit          # завершает merge

На rebase после правки — git add и git rebase --continue, не новый произвольный commit.


Опасные операции: что переписывает историю

«Опасно» здесь значит: команда меняет уже существующие коммиты или легко уничтожает незакоммиченное. На общей ветке, которую уже кто-то склонировал, так делать нельзя. На своей локальной, которую ещё не пушили, — можно, но сначала в тренажёре.

reset vs revert

Команда Что делает Когда
git reset --hard HEAD~1 Стирает последний коммит и рабочую папку до предыдущего снимка. Коммит как будто не существовал Только свой незапушенный коммит. После push коллеги уже видят этот хеш — reset сломает им историю
git revert HEAD Делает новый коммит, который отменяет изменения старого. История не врёт Коммит уже в общем main / запушен. Честный откат: «вот правка, вот её отмена»
git log --oneline          # посмотреть хеши
git reset --hard HEAD~1    # убрать последний локальный коммит
git revert abc123          # отменить конкретный общий коммит новым

HEAD~1 — «родитель текущего коммита», на один шаг назад. --hard выкидывает и индекс, и файлы. Есть ещё --soft (коммит убрали, изменения остались в staging) и --mixed (изменения в рабочей папке). Для новичка достаточно: --hard = жёстко стереть, только если коммит ещё не общий.

cherry-pick — один коммит, не вся ветка

В чужой ветке десять коммитов, вам нужен один фикс (таймаут, опечатка в ассерт). Не мержить всю ветку.

git log feature/hotfix --oneline
git checkout main
git cherry-pick abc123

Git копирует патч этого коммита на текущую ветку. Получается новый коммит с тем же смыслом, но другим хешем. Если тот же патч не накладывается — конфликт, как при merge.

Не путать с merge: merge тащит всю историю ветки, cherry-pick — выбранные коммиты.

rebase — поставить свою ветку поверх свежего main

Пока вы писали фичу, в main влили чужие коммиты. Ваша ветка «отстала».

Merge main в фичу добавляет merge-коммит: история с развилкой.

Rebase отрывает ваши коммиты и накатывает их заново поверх нового main. История выглядит линейно: сначала чужое, потом ваше.

git checkout feature/login-error
git fetch origin
git rebase origin/main
# конфликт → правите файл → git add → git rebase --continue
# передумали → git rebase --abort

Почему опасно: rebase переписывает хеши ваших коммитов. Если ветку уже пушили и с неё кто-то ответвился, после rebase им придётся силой переписывать свою копию (push --force). Правило: rebase только свою ветку, которую ещё не шарят, или свою feature до мержа. Никогда не rebase чужой main на сервере.

merge rebase
История Развилка + merge-коммит Линия: ваши коммиты «переехали»
Хеши ваших коммитов Те же Новые
На запушенной общей ветке Безопасно Опасно

stash — спрятать незакоммиченное

Нужно срочно переключить ветку, а в файлах недоделанный тест. Коммитить рано, checkout ругается.

git stash              # прячет правки
git checkout main      # можно переключаться
git checkout feature/wip
git stash pop          # вернуть правки на стол

stash кладёт WIP на полку. Это не коммит в истории ветки. Потерять полку можно (stash drop) — поэтому долгую работу лучше коммитить в свою ветку, а не жить в stash неделями.


Карта: что делать в какой ситуации

Задача Команда
Посмотреть статус git status, git log --oneline
Своя ветка git checkout -b имя
Снимок git add …git commit -m "…"
Отправить ветку git push -u origin имя
Подтянуть main git checkout maingit pull
Влить ветку git merge имя
Конфликт убрать маркеры → git addgit commit (или rebase --continue)
Стереть свой последний незапушенный коммит git reset --hard HEAD~1
Отменить уже общий коммит git revert <хеш>
Забрать один чужой коммит git cherry-pick <хеш>
Поставить свою ветку на свежий main git rebase main (своя ветка, не общий main)
Спрятать WIP git stash / git stash pop

Опасные (reset --hard, rebase, cherry-pick на конфликтных файлах) сначала в Git-тренажёре, не на боевом main.


Pull Request

PR — просьба посмотреть diff вашей ветки относительно main, не «отправить файл в чат». В команде путь такой: ветка → коммит → push → PR → комментарии по строкам → новый коммит в ту же ветку (PR обновляется сам) → merge.

main часто защищён: пушить туда напрямую нельзя. Комментарий ревью — про строку кода, не про автора.


Ключевые тезисы для теста

  • Git — движок; GitHub / GitLab / Bitbucket / SourceCraft — хостинги.
  • add выбирает файлы, commit делает снимок; это не Save.
  • pull подтягивает чужие коммиты; новую ветку заводят от свежего main.
  • Конфликт: маркеры <<<<<<< / ======= / >>>>>>>, правка руками, затем add + commit.
  • reset --hard стирает незапушенный коммит; revert отменяет общий новым коммитом.
  • cherry-pick копирует один коммит, не всю ветку.
  • rebase переносит ваши коммиты поверх другой ветки и меняет их хеши — не делать на общем main.
  • stash прячет незакоммиченное, чтобы сменить ветку.

Домашнее задание

Индивидуальная проверка ДЗ — на Boosty

Конспект, видео и тест открыты всем. Текст задания и проверка работы — по подписке.

Индивидуальная проверка ДЗ на Boosty
База для QA — вопросы на собеседование, тренажёры и материалы