Как последовательный rebase двух feature-веток влияет на историю Git?

«Как последовательный rebase двух feature-веток влияет на историю Git?» — вопрос из категории DevOps, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Последовательный rebase двух веток на общую родительскую ветку создаёт две независимые линейные истории, что может привести к конфликтам и потере контекста зависимостей между ветками.

Типичный сценарий:

# Исходное состояние:
# A---B---C  main
#      ---D---E  feature1
#           ---F---G  feature2

# Шаг 1: Rebase feature1 на main
git checkout feature1
git rebase main
# Результат: A---B---C---D'---E'  main, feature1

# Шаг 2: Rebase feature2 на main
git checkout feature2
git rebase main
# Проблема: feature2 пытается применить F---G поверх C,
# но теряет зависимость от D---E

Проблемы такого подхода:

  1. Потеря зависимостей: Если feature2 зависит от изменений в feature1, эта зависимость теряется
  2. Конфликты: Могут возникнуть конфликты, если ветки изменяли одни и те же файлы
  3. Дублирование коммитов: Изменения из feature1 могут быть применены повторно

Рекомендуемые стратегии:

  1. Rebase с зависимостью:

    # Сначала rebase feature2 на feature1
    git checkout feature2
    git rebase feature1
    # Затем rebase feature1 на main
    git checkout feature1
    git rebase main
    # И rebase feature2 на обновлённую feature1
    git checkout feature2
    git rebase feature1
  2. Использование merge:

    # Для публичных веток лучше использовать merge
    git checkout main
    git merge --no-ff feature1
    git merge --no-ff feature2
  3. Визуализация истории:

    git log --oneline --graph --all --decorate

Важные предупреждения:

  • Не rebase опубликованные коммиты — это переписывает историю
  • После rebase требуется git push --force-with-lease (безопаснее чем --force)
  • Используйте git rerere для автоматического разрешения повторяющихся конфликтов

Лучшие практики:

  1. Rebase только локальных веток
  2. Часто синхронизируйтесь с основной веткой
  3. Используйте интерактивный rebase для очистки истории: git rebase -i main