💻 Примеры — Merge-конфликты, monorepo

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

⚡ Создать и разрешить конфликт

# Создать конфликт
git checkout -b feature; echo "feature content" > file.txt; git commit -am "feature"
git checkout main; echo "main content" >> file.txt; git commit -am "main"
git merge feature    # CONFLICT!

# Посмотреть конфликты
git status
git log --merge

# Разрешить и завершить
nano file.txt    # убрать маркеры <<<<<<< ======= >>>>>>>
git add file.txt
git merge --continue

Полный walk-through: создание и разрешение конфликта

Воспроизводим пример из лекции шаг за шагом.

Шаг 1: Создать репозиторий с файлом

# git-merge-test/merge.txt

$ mkdir git-merge-test
$ cd git-merge-test
$ git init .
Initialized empty Git repository in /home/user/git-merge-test/.git/

$ 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
Switched to a new branch '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
Switched to branch '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: Merge — конфликт!

$ 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.

Шаг 5: Посмотреть конфликт

$ git status
On branch main
You have unmerged paths.
  (fix conflicts and run "git commit")

Unmerged paths:
  (use "git add <file>..." to mark resolution)
        both modified:   merge.txt

$ cat merge.txt
<<<<<<< HEAD
this is some content to mess with
content to append
=======
totally different content to merge later
>>>>>>> new_branch_to_merge_later
Маркеры конфликта:
<<<<<<< HEAD — начало вашей версии (текущая ветка)
======= — разделитель
>>>>>>> branch_name — версия из сливаемой ветки

Нужно удалить маркеры и оставить нужный код (или объединить обе версии).

Шаг 6: Разрешить конфликт вручную

Открыть файл в редакторе, убрать маркеры:

# После редактирования merge.txt должен содержать только нужное:
this is some content to mess with
content to append

Шаг 7: Завершить слияние

$ git add merge.txt
$ git merge --continue
[main e4f5c6a] Merge branch 'new_branch_to_merge_later'

# Или через git commit:
$ git commit
# Откроется редактор с сообщением коммита слияния

Пример структуры monorepo

Миграция от разрозненных репозиториев к monorepo:

# Было: отдельные репозитории

github.com/user/Lesson1   (git init, 5 commits)
github.com/user/Lesson2   (git init, 3 commits)
github.com/user/Lesson3   (git init, 7 commits)
...
github.com/user/Lesson10  (git init, 4 commits)

# Стало: один monorepo

github.com/user/linux-git-course/
  ├── bash-lessons/
  │   ├── lesson01/
  │   ├── lesson02/
  │   └── lesson03/
  ├── git-lessons/
  │   ├── lesson04/
  │   └── lesson05/
  └── README.md

# migrate-to-monorepo.sh

#!/bin/bash
# Создать новый репозиторий
mkdir my-monorepo
cd my-monorepo
git init

# Скопировать содержимое каждого репозитория
cp -r ../Lesson1 bash-lessons/lesson01
cp -r ../Lesson2 bash-lessons/lesson02
# ... и т.д.

# Удалить директории .git из скопированных репозиториев
# ВНИМАНИЕ: история коммитов будет потеряна!
# Сначала проверить что именно будет удалено:
find . -type d -name ".git" -not -path "./.git"

# Только потом удалять (ОПАСНО):
# find . -type d -name ".git" -exec rm -rf {} +

# Добавить в новый репозиторий
git add .
git commit -m "Initial monorepo: migrate 10 lesson repositories"
git remote add origin https://github.com/user/my-monorepo.git
git push -u origin main