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 нужно:
- Создать новый репозиторий для monorepo
- Скопировать содержимое каждого репозитория в отдельные поддиректории
- Удалить директории
.gitв поддиректориях - Добавить всё в новый репозиторий
Полезный инструмент для шага 3:
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. Они позволяют объединить репозитории с сохранением истории, но значительно сложнее в использовании.