Как решать конфликты в коде при одновременной работе нескольких разработчиков
gitверсионированиекомандная работаконфликтыпараллельная разработка
Что проверяют
Практику работы с Git, а не теорию: понимает ли кандидат, откуда берётся конфликт, умеет ли его разрешить руками и, главное, что делает, чтобы конфликты не возникали пачками. Ответ уровня «мы используем ветки и общаемся» засчитывают редко.
Как отвечать
Конфликт возникает, когда две ветки изменили одни и те же строки, и Git не может выбрать сторону сам. Всё остальное он сливает автоматически.
Разрешение по шагам:
git statusиgit diff --name-only --diff-filter=Uпоказывают файлы в конфликте.- В файле правится участок между
<<<<<<<,=======и>>>>>>>. Результат почти никогда не равен одной из сторон целиком: обычно нужно совместить обе правки по смыслу. git add <файл>, затемgit rebase --continueилиgit commitдля merge.- Прогнать тесты. Синтаксически валидный результат слияния регулярно оказывается семантически сломанным: обе стороны переименовали одно и то же по-разному.
- Если стало хуже, чем было,
git merge --abortилиgit rebase --abortвозвращают состояние до начала.
Пара тонкостей, которые отличают опытного кандидата:
--oursи--theirsменяются местами при rebase. В mergeoursэто ваша текущая ветка. В rebase ваши коммиты накладываются поверх чужих, поэтомуoursэто ветка, на которую вы перебазируетесь, аtheirsваши собственные изменения. Автоматом выбирать сторону вслепую опасно именно из-за этого.git rerereзапоминает, как вы разрешили конкретный конфликт, и применяет то же решение при повторе. Незаменимо при долгой ветке, которую регулярно ребейзят.git log --merge -p <файл>показывает коммиты обеих сторон, затронувшие конфликтный файл, то есть контекст, зачем правка вообще делалась.
Профилактика важнее лечения:
- короткие ветки и частые вливания:
git pull --rebaseили регулярный merge из основной ветки, чтобы расхождение измерялось часами, а не неделями; - задачи нарезаются так, чтобы разработчики не жили в одном файле; крупный рефакторинг согласуется заранее и вливается отдельно от продуктовых правок;
- единый автоформатер, зафиксированный в конфиге и в pre-commit (
black,ruff format,isortдля Python), убирает конфликты из-за стиля и переносов строк; массовое переформатирование делается отдельным коммитом и заносится в.git-blame-ignore-revs; - сгенерированные файлы не мержатся руками, а перегенерируются:
poetry.lock,uv.lock, миграции. Конфликт нумерации миграций Alembic решаетсяalembic merge, в Djangomakemigrations --merge, а не подгонкой текста; - фичефлаги позволяют вливать незаконченное в основную ветку маленькими кусками вместо ветки на месяц.
Где спотыкаются
Разрешают конфликт «по-быстрому», принимая свою сторону целиком, и молча выкидывают чужую правку. Второе типичное: не запускают тесты после слияния, потому что «конфликт же решён», и ловят ошибку уже на CI или в проде.