Конфликт Git Merge - Что значит «по-разному изменять одну и ту же часть одного и того же файла»? - PullRequest
2 голосов
/ 11 апреля 2019

Глава 3.2 книги Git гласит:

& hellip; Иногда этот процесс не проходит гладко. Если вы изменили одну и ту же часть одного и того же файла по-разному в двух ветвях, которые вы объединяете, Git не сможет объединить их чисто. & Hellip;

Как следует интерпретировать неоднозначное выражение ", изменяющее одну и ту же часть одного и того же файла, по-разному "? Git выполняет внутренне построчное сравнение в конфликтующем файле через ветви?


Пример

Предположим, на ветке L Я добавляю дополнительную новую строку в начале README.md. Означает ли это, что изменение в любой строке, отличной от первой в README.md в другой ветви R , вызовет конфликт после слияния?

Можно ожидать, что наивное построчное сравнение потерпит неудачу, так как все строки смещены на L , а некоторая часть строк в R останется без сдвига.

Ответы [ 2 ]

1 голос
/ 11 апреля 2019

То, что сказал Торек, правильно, но я просто хочу еще раз подчеркнуть основные моменты, поскольку, похоже, именно здесь вы боретесь.

Когда вы объединяете две ветви, каждая ветвь представляет одну историюусилие или изменения.Например, представьте, что вы и ваш коллега Боб оба работаете над одним и тем же проектом с разных компьютеров в одно и то же время.

Когда вы начинали, у вас была точно такая же версия, что и у Боба.Но поскольку вы работаете независимо, легко заметить, что вы и Боб могли бы одновременно изменить файл README .Возможно, вы заметили, что в первом предложении есть слово с ошибкой и исправили его.Тем временем Боб решает, что введение вводит в заблуждение, поэтому он переписывает первые два абзаца.В версии Боба орфографическая ошибка по-прежнему существует, но теперь она находится на другой линии.

Теперь существует конфликт между вашей версией Боба и README.Когда вы и Боб решите объединить свои изменения вместе, этот конфликт будет обнаружен git merge, и он будет жаловаться вам.Вы не хотите, чтобы слияние отбросило ваши изменения, так как Боб не заметил орфографическую ошибку.Но вы тоже не хотите отказываться от работы Боба.Поэтому решение объединить изменения вашего README и README Боба должен принять человек.

Теперь, в этом случае, вы и Боб изменили одну и ту же строку README.Но что, если вы коснулись разных строк?В качестве меры предосторожности, git merge все равно будет жаловаться, если ваши измененные строки достаточно близки к измененным строкам Боба, потому что все еще может быть конфликт.

Но git merge не может (и не может) обнаружить все возможныеконфликт.Иногда результат слияния не имеет смысла, хотя git merge не жаловался.Например, если в то же время, когда вы исправляете орфографическую ошибку, вы также добавляете предложение в конце README, которое ссылается на что-то, упомянутое в первом абзаце, ваши изменения могут не иметь смысла вместе с Бобом.Однако git не может сказать, что последняя строка и первый абзац связаны, потому что он не может угадать значение или семантику файла, который он объединяет.То же самое относится и к кодовым файлам.

1 голос
/ 11 апреля 2019

Помните, что Git делает не один, а два diffs:

  • существует базовый коммит слияния B с некоторыми файлами,
  • и L с левой стороны, зафиксировать с некоторыми файлами,
  • с правой стороны R с некоторыми файлами.

База слияния B одинакова в обеих git diff командах:

git diff --find-renames <hash-of-B> <hash-of-L>    # what we changed
git diff --find-renames <hash-of-B> <hash-of-R>    # what they changed

Итак, предположим, что мы и они оба изменили файл F.ext.Из различий first ясно, какие строки F.ext мы изменили: те, которые перечислены как удаленные в блоке различий относительно B, плюс еще одна линия «между» на краюдля безопасности - край идет вперед, поэтому, если мы заменили исходную строку 3, мы «коснулись» линий 3 и «3 с половиной».Если мы не удалили никаких строк - если мы вставили строку после строки 3 перед строкой 4 - то мы коснулись строки «3 с половиной».

Между тем, это также ясно из second diff, какие строки F.ext они изменились.Применяются те же правила: если они заменили исходную строку 3 строкой замены 3, то они коснулись строки 3 (которая включает в себя строку «3.5»).Так что, если мы коснулись строки 3 или строки 3.5, у нас возникнет конфликт.В противном случае конфликт не возникает: Git может просто принять изменение с любой стороны, которая внесла изменения в рассматриваемые строки.

(Обратите внимание, что git diff представляет разницу как unified context diff. В коде слияния используется необработанный, неунифицированный diff. Поэтому в нем есть список, который говорит: «в строке X оригинала, удалите D строк и вставьте I новые сменные линии ", где не более одной из D или I может быть ноль. Достигнутый промежуток - это линия X через линию X + D + 0,5 , более или менее. С моим странным «плюс половина» я просто энергично машу руками, чтобы скрыть проблему с пустым промежутком, которая является проблемой. Вам придется поэкспериментировать с Git, чтобы увидеть, что именно он делает в каждом случае.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...