linuxlab.io
Учебники▾
  • Линукс и сети
    Файловая система, процессы, TCP/IP, BGP и OSPF
    →
  • Terraform и IaC
    HCL, state, plan/apply на sandbox LocalStack
    →
  • Git и GitHub
    Объектная модель, plumbing, ветвление, GitHub Actions
    →
Все учебники →
ЦеныО платформеВойтиСоздать аккаунт
/
Intro
Lessons
Footer
linuxlab-УчебникиЦеныО платформеКонфиденциальность и куки
Copyright © 2026 LinuxLab. Все права защищены.
linuxlab.io
Учебники▾
  • Линукс и сети
    Файловая система, процессы, TCP/IP, BGP и OSPF
    →
  • Terraform и IaC
    HCL, state, plan/apply на sandbox LocalStack
    →
  • Git и GitHub
    Объектная модель, plumbing, ветвление, GitHub Actions
    →
Все учебники →
ЦеныО платформеВойтиСоздать аккаунт
/
  • Введение
  • Главы
  • How it works
  • Уроки
  • База знаний
  • Собеседование
home/git/lessons/git-lab-08-1-merge-vs-rebase

lesson ── git-labs ── ~20 мин ── 7 шагов

Merge против rebase: руками на одном репозитории

Цель - увидеть руками разницу между git merge и git rebase. Сначала поставишь две ветки в типичную ситуацию «разошлись», потом склеишь их одним способом, потом ещё раз тем же сценарием другим способом, и сравнишь графы истории.

Никакого реального GitHub не нужно. Всё локально, в эфемерном контейнере с git внутри. После - контейнер исчезает, репозитории удаляются.

▶ интерактивный sandbox

Поднимется контейнер gitlab/git-base с git, bash, pre-commit. В браузере откроется терминал, можно сразу git init. Каждый шаг проверяется автоматически. Сеть air-gapped, github.com недоступен.

запустить sandbox →

stack ── git · bash · 256 MB RAM · air-gapped · самоуничтожается через 30 мин простоя

Шаги

  1. 01

    Создай репо с двумя расходящимися ветками

    Сделаем минимальный репозиторий с одним общим коммитом, потом разойдёмся в две ветки и сделаем по коммиту в каждую. Это классическая ситуация «main ушёл вперёд, я работал в feature».

    bash
    cd /home/student/work
    mkdir merge-vs-rebase && cd merge-vs-rebase
    git init
    echo "v1" > file.txt
    git add file.txt
    git commit -m "init"
    git switch -c feature                # -c = создать ветку и переключиться
    echo "feature line" >> file.txt      # >> append, не перезатирает v1
    git commit -am "feature: add line"   # -a stage отслеживаемых, -m сообщение
    git switch main
    echo "main line" >> file.txt
    git commit -am "main: add line"

    Теперь main и feature разошлись от общего коммита init.

    подсказка

    Каждая команда отдельной строкой - если что-то не так, читай ошибку.

    ✓ Два расходящихся коммита от общего предка. Готов для эксперимента.

  2. 02

    Посмотри граф до слияния

    Граф показывает форму истории. Запусти:

    bash
    git log --oneline --graph --all   # --graph = ASCII-граф, --all = показать все refs

    Должен показать:

    * <sha> (main) main: add line
    | * <sha> (feature) feature: add line
    |/
    * <sha> init

    Это V-образное расхождение от init. Запомни форму - сравним её после merge и после rebase.

    подсказка

    Если nothing видно - убедись что ты в /home/student/work/merge-vs-rebase.

    ✓ V-форма видна. Дальше merge.

  3. 03

    Сделай merge feature в main

    Сейчас ты на main. Слей feature:

    bash
    git merge feature             # обе ветки ушли - получится three-way merge с конфликтом

    Откроется редактор с дефолтным сообщением merge-коммита. Сохрани без правок (Ctrl-O, Enter, Ctrl-X в nano). Будет конфликт - в file.txt: один и тот же файл правили в двух местах. Открой file.txt, удали маркеры <<<<<<<, =======, >>>>>>>, оставь обе строки в каком-то порядке. Сохрани.

    bash
    git add file.txt              # помечаем конфликт разрешённым
    git commit                    # без -m: откроет редактор с merge-сообщением

    Снова сохрани сообщение merge-коммита.

    подсказка

    Конфликт - это нормально. nano открывается через `nano file.txt`.

    ✓ Merge-коммит создан. Посмотри новый граф.

  4. 04

    Посмотри граф после merge

    bash
    git log --oneline --graph --all

    Теперь видишь:

    *   <sha> (HEAD -> main) Merge branch 'feature'
    |\
    | * <sha> (feature) feature: add line
    * | <sha> main: add line
    |/
    * <sha> init

    Сравни с тем, что было до merge. Прежние коммиты на месте, добавился merge-коммит сверху, история «затянулась» в одну точку. Это и есть merge: история сохранена ровно как было, плюс шов.

    ✓ Граф с merge-коммитом виден. Дальше - откатим и сделаем то же самое через rebase.

  5. 05

    Откати состояние до расхождения

    Чтобы попробовать rebase на той же ситуации, верни main до его состояния «один коммит после init». Тебе нужны два коммита: init и main: add line. Сейчас сверху лежит merge-коммит, его надо убрать.

    bash
    git reset --hard HEAD~1       # снять последний коммит (merge), стереть и working tree
    git log --oneline

    Должно остаться: main: add line и init. Feature не трогаем, она в стороне.

    подсказка

    `git reset --hard HEAD~1` снимает один последний коммит (merge) с потерей.

    ✓ main снова на месте до merge. Готов для rebase.

  6. 06

    Сделай rebase feature на main

    Теперь переключись на feature и сделай rebase на main:

    bash
    git switch feature
    git rebase main               # переписать коммиты feature поверх main

    Снова конфликт в file.txt (та же причина, что и на шаге merge). Открой файл:

    bash
    nano file.txt

    Внутри увидишь блок с маркерами конфликта - семь угловых скобок подряд (<<<<<<<), знаки равенства (=======), снова угловые (>>>>>>>). Сейчас файл выглядит примерно так:

    v1
    <<<<<<< HEAD
    main line
    =======
    feature line
    >>>>>>> 699c3b1 (feature: add line)

    Удали все три строки с маркерами (<<<<<<<, =======, >>>>>>>), строки main line и feature line оставь. Должно получиться ровно так - три строки, никаких угловых скобок и знаков равенства:

    v1
    main line
    feature line

    Сохрани (Ctrl-O, Enter, Ctrl-X). Теперь помечаем конфликт разрешённым и продолжаем rebase:

    bash
    git add file.txt              # помечаем конфликт разрешённым
    git rebase --continue         # после конфликта - не commit, а --continue

    Откроется редактор с сообщением переписанного коммита. Сохрани без правок. rebase завершится.

    подсказка

    Если verify красный - три самые частые причины, проверь их по порядку: 1. В file.txt остались маркеры `<<<<<<<`, `=======`, `>>>>>>>` - открой `nano file.txt` и убери их руками, оставь три строки без скобок. Потом `git add file.txt` и `git rebase --continue`. 2. Ты сделал `git commit` вместо `git rebase --continue` - это не доводит rebase до конца. Запусти `git status`, если видишь «interactive rebase in progress» - доделай через `git rebase --continue`. 3. Rebase ещё не закончен (есть незакоммиченные правки) - `git status` подскажет что именно осталось.

    ✓ Rebase прошёл. Граф изменится сильно.

  7. 07

    Посмотри граф после rebase

    bash
    git log --oneline --graph --all

    Видишь:

    * <sha> (HEAD -> feature) feature: add line
    * <sha> (main) main: add line
    * <sha> init

    Полностью линейная история. Никакого merge-коммита, никакой V-формы. Коммит «feature: add line» теперь стоит поверх main: add line, с другим SHA - потому что его базовый коммит изменился.

    Это и есть rebase: твоя ветка переписана так, будто она с самого начала ответвлялась от свежего main.

    ✓ Линейная история. Ты увидел разницу руками. Подробнее - в главе 8.

Что ты узнал

Merge сохраняет историю как было, ценой merge-коммита. Rebase переписывает поверх, ценой новых SHA. Граф git log --oneline --graph --all показывает разницу мгновенно.

команды

  • git log --oneline --graph --allувидеть ветки и их форму
  • git merge featureслить feature в текущую (с merge-коммитом)
  • git rebase mainпереписать текущую ветку поверх main
  • git reflogесли запутался - откатить через reflog

концепции

  • · merge не переписывает коммиты, только добавляет
  • · rebase меняет SHA, нужен force-push если ветка опубликована
  • · graph отвечает на вопрос 'что произошло' без угадывания

← предыдущая

Атомарные коммиты: add -p и amend

следующая →

Отмена: reset, revert, reflog

Footer
linuxlab-
Copyright © 2026 LinuxLab. Все права защищены.
Учебники
Цены
О платформе
Конфиденциальность и куки