Страницы

Поиск по вопросам

среда, 13 февраля 2019 г.

Слияние веток в Git-е: непонятный конфликт строк

Всем доброго времени суток.
Изучаю Git. Использую гуй SourceTree. Репозиторий лежит на BitBucket. Создал два аккаунта, чтоб воспроизвести совместную разработку. Когда делаю слияние изменений в одной ветке - в блок HEAD помещается только конфликтные строки. Когда делаю слияние изменений из разных веток - в этот блок попадают все строки.
Например, два автора меняют одну и ту же строку в файле index.php в ветке master. Мой воображаемый "напарник" успешно пушит свои изменения. А вот я уже должен выполнить слияние, перед тем как отправить свои изменения. Делаю пул. Файл принимает следующее состояние:
<<<<<<< HEAD echo "This is my master branch"; ======= echo "This is test branch"; >>>>>>> 18baca2cbbf6685dbe946554f436312e93bd4ff3 exit();
// I don't have new ideas... (((
Тут всё понятно. Строка echo... является конфликтной и я самостоятельно решаю что мне с ней сделать. А теперь представим тот же файл index.php, но из разных веток. Отличия между ними лишь в том, что в ветке test появляется две строки: одна из них пустая, а вторая содержит комментарий. Как мне подумалось, слияние должно вообще пройти без проблем в автоматическом режиме, ведь нет никаких разных изменений в одной и той же строке. Однако, здравствуйте. Содержимое файла index.php при попытке слияния:
<<<<<<< HEAD echo "This is master branch"; exit();
// I don't have new ideas... ((( ======= // This is my test branch
echo "This is master branch"; exit();
// I don't have new ideas... ((( >>>>>>> test
И в конце файла ещё одна пустая строка (после строки >>>>>>> test).
На этом моменте я завис. Не могу понять откуда вообще появились конфликтные строки. Их быть не должно. Ведь в тесте всего лишь 2 новые строки, не более. Кто может мне объяснить, где я чего не понял? Это так и должно быть, или я, криворукий, где-то допустил ошибку, которая приводит к такому результату?
Заранее благодарю за помощь. С уважением, Юрий.


Ответ

Если у двух строк разные окончания - то они считаются гитом различными. Поэтому важно правильно договариваться об окончаниях строк внутри команды.
Также есть вариант принудительно настроить окончания строк для репозитория, это делается в файле .gitattributes
Пример настройки в этом файле:
*.cs text eol=crlf
Здесь написано, что все файлы с расширением .cs надо считать текстовыми, хранить в репозитории с LF окончаниями строк - а в рабочей копии загружать с окончанием строк CRLF.
Или вот другой пример:
*.xml text eol=lf
Здесь во всех xml-файлах окончания строк всегда будут LF.

Немного о том, что вообще такое "окончания строк". Окончание строки - это набор невидимых символов, которые отделяют в файле одну строку от другой. Исторически, имеется два разных символа, которые пришли к нам еще с пишущих машинок и телетайпов:
CR - возврат каретки, этот символ возвращал каретку в начало текущей строки LF - перевод строки, этот символ переводил каретку к следующей строке, не смещая ее
Для электрических печатных машинок или матричных принтеров это были две разные команды (а у машинок - еще и две разные кнопки). Но когда встала задача обработки текстов на компьютере, два разных символа оказалось избыточно, поэтому некоторые системы пошли по пути упрощения.
В современном UNIX-мире сейчас принято разделение строк при помощи одного символа LF, на старых маках использовался символ CR - ну а DOS и потом винда остались на CRLF.
Тем не менее, все нормальные текстовые редакторы сейчас уже умеют автоматически определять окончания строк или даже работать со смешанными окончаниями строк в одном файле - поэтому вы про них ничего и не знали.
Но git работает не с текстом, а с байтами - поэтому в гите важно приводить окончания строк для файла к одному виду.

Комментариев нет:

Отправить комментарий