📖 Теория — Merge-конфликты, monorepo

К оглавлению урока

⚡ Суть теории

  • Merge-конфликт = две ветки несовместимо изменили один файл/строку
  • Виды: конфликты файлов и конфликты слияния директорий
  • Разрешение: вручную / IDE / git-команды → git addgit merge --continue
  • Monorepo = несколько проектов в одном репозитории
  • Миграция: find . -type d -name ".git" -exec rm -rf {} + — ОПАСНО, теряет историю

Merge-конфликты

Merge-конфликты возникают в Git, когда Git не может автоматически слить изменения из разных веток из-за конфликта в изменениях в одном и том же файле или строке кода.

Виды merge-конфликтов

  • Конфликты файлов — когда две ветки вносят изменения в один и тот же файл, а изменения несовместимы. Например, изменения в одной ветке затрагивают строки кода, которые были удалены или изменены в другой ветке.
  • Конфликты слияния директорий — возникают, когда Git не может определить, как объединить изменения в директории из-за конфликтующих файлов.

Создание merge-конфликта (walk-through)

Полный пример из лекции — шаг за шагом:

Шаг 1: Инициализация репозитория

$ mkdir git-merge-test
$ cd git-merge-test
$ git init .
$ echo "this is some content to mess with" > merge.txt
$ git add merge.txt
$ git commit -am "we are commiting the inital content"
[main (root-commit) d48e74c] we are commiting the inital content
 1 file changed, 1 insertion(+)
 create mode 100644 merge.txt

Шаг 2: Создать ветку и изменить файл

$ git checkout -b new_branch_to_merge_later
$ echo "totally different content to merge later" > merge.txt
$ git commit -am "edited the content of merge.txt to cause a conflict"
[new_branch_to_merge_later 6282319] edited the content of merge.txt
 1 file changed, 1 insertion(+), 1 deletion(-)

Шаг 3: Вернуться на main и тоже изменить файл

git checkout main
echo "content to append" >> merge.txt
git commit -am "appended content to merge.txt"
[main 24fbe3c] appended content to merge.txt
 1 file changed, 1 insertion(+)

Шаг 4: Попытаться слить — конфликт!

$ git merge new_branch_to_merge_later
Auto-merging merge.txt
CONFLICT (content): Merge conflict in merge.txt
Automatic merge failed; fix conflicts and then commit the result.

Git сообщил о конфликте. Файл merge.txt теперь содержит маркеры конфликта:

<<<<<<< HEAD
this is some content to mess with
content to append
=======
totally different content to merge later
>>>>>>> new_branch_to_merge_later

Разрешение merge-конфликтов

1. Ручное разрешение

Открыть конфликтующий файл в текстовом редакторе. Убрать маркеры <<<<<<<, =======, >>>>>>> и оставить только нужный код.

2. Использование инструментов IDE

PyCharm, VS Code и другие IDE предоставляют визуальные инструменты разрешения конфликтов: показывают две версии рядом и позволяют выбрать нужную.

3. Git-команды для работы с конфликтом

Команда Пояснение
git status Показывает, какие файлы имеют конфликты после попытки слияния
git log --merge Создаёт журнал со списком коммитов, конфликтующих между объединяющимися ветвями
git diff Показывает изменения, которые вызвали конфликты
git mergetool Запускает внешний инструмент для разрешения конфликтов

4. Повторное слияние после разрешения

После разрешения конфликтов файлов добавьте изменения в индекс с помощью git add, а затем завершите слияние с помощью git merge --continue.

git add merge.txt
git merge --continue

Монорепозиторий (monorepo)

Существует концепция укрупнения репозиториев в Git, которая называется монорепозиторием или monorepo. Это означает объединение нескольких проектов или компонентов в один общий репозиторий.

Вместо того чтобы каждый проект имел свой собственный репозиторий, все проекты объединяются в один монорепозиторий. Особенно это полезно, когда у нас много разрозненных репозиториев, каждый из которых посвящён одному занятию или одной домашней работе.

Преимущества монорепозитория

  • Улучшение совместной работы
  • Упрощение поиска
  • Увеличение комфорта работы с проектами
  • Удобная группировка репозиториев

Недостатки

  • Увеличение размера репозитория и сложности его управления
  • Увеличение времени загрузки репозитория при клонировании
  • Возможные конфликты при работе над различными частями кода в одном репозитории

Миграция к monorepo

Для миграции разрозненных репозиториев (например, Lesson1..Lesson10) в один monorepo нужно:

  1. Создать новый репозиторий для monorepo
  2. Скопировать содержимое каждого репозитория в отдельные поддиректории
  3. Удалить директории .git в поддиректориях
  4. Добавить всё в новый репозиторий

Полезный инструмент для шага 3:

find . -type d -name ".git" -exec rm -rf {} +
⚠️ ОПАСНО: find . -type d -name ".git" -exec rm -rf {} +

Эта команда выполняет поиск (find) в текущей директории (.) и всех её поддиректориях директорий с именем .git и удаляет их рекурсивно (rm -rf).

Мы потеряем коммиты в индивидуальных репозиториях, так как удаляется .git вместе с содержимым. После выполнения команды вся история коммитов, ветки, теги и метаданные Git во всех вложенных репозиториях будут безвозвратно удалены.

Перед выполнением:
— Убедитесь, что история коммитов вам не нужна
— Создайте резервные копии репозиториев (git bundle или zip)
— Проверьте, что вы находитесь в правильной директории (pwd)
— Сначала протестируйте: find . -type d -name ".git" (без exec) — посмотреть что будет удалено
⚠️ Проверить по документации
Для продвинутой миграции с сохранением истории коммитов из каждого субрепозитория существуют инструменты git subtree и git submodule. Они позволяют объединить репозитории с сохранением истории, но значительно сложнее в использовании.