Возможно ли, что git -merge игнорирует разности строк?

Возможно ли, чтобы git merge проигнорировал разности строк?

Возможно, я задаю неправильный вопрос... но:

Я попробовал uisng config.crlf input, но все получилось немного грязным и неконтролируемым, особенно когда я применил его после факта.

С одной стороны, применение этой конфигурации после факта не влияет на файлы, которые были привязаны к репозиторию, прежде чем применять эту опцию. Другое дело, что внезапно все коммиты теперь приводят к множеству раздражающих предупреждающих сообщений о преобразовании CRLF в LF.

Честно говоря, мне все равно, что используется окончание строки, я лично предпочитаю стиль Unix \n, но что угодно. Все, о чем я забочусь, заключается в том, чтобы git merge быть более умным и игнорировать различия в концах строк.

Иногда у меня есть два одинаковых файла, но git будет помечать их как конфликтующие (а конфликт - весь файл) просто потому, что они используют другой символ окончания строки.

Обновление:

Я узнал, что git diff принимает параметр --ignore-space-at-eol, можно ли использовать git merge эту опцию?

Ответ 1

Обновление 2013:

Более поздние версии git разрешают использование слияния со стратегией recursive и стратегией (-X):

git merge -s recursive -Xignore-space-at-eol

Но использование "-Xignore-space-change" также возможно

  • Fab-V упоминает ниже: <Предварительно > git merge master -s recursive -X renormalize

jakub.g также комментарии, что стратегии работают также с выбором вишни:

git cherry-pick abcd123456 --strategy=recursive --strategy-option=renormalize 

Это работает намного лучше, чем ignore-all-space.


Оригинальный ответ (май 2009 г.)

Патч для игнорирования стиля eol был предложен в June 2007, но он касается только git diff --ignore-space-at-eol, а не git merge.

В то время вопрос был запрошен:

Должна ли --ignore-space-at-eol опция git-merge?
Слияния - вот где эта функциональность имеет значение.
Какова семантика слияния с автоматическим разрешением с этими действующими параметрами - используются ли они только для обнаружения переименования, или мы, например, не конфликтуем с конфликтами только с переменными пробелов? И если мы этого не делаем, какую версию мы принимаем автоматически?

Хулио С Хамано не был в восторге:

Это, конечно, соблазнительно, но я подозреваю, что его следует оставить на более поздние раунды.
Я подозреваю, что он представит концепцию двух разных видов различий, один из которых будет механически обработан (т.е. Использовать в слиянии с "git -merge-recursive" и применять с "git -am" ), а другой - для проверки людьми. Часто бывает полезно выполнить ввод данных для последнего случая, даже если результат сравнения помеченных входных файлов может быть легко использован для механического применения.

Общая идея, когда дело доходит до git merge, заключается в том, чтобы полагаться на сторонний инструмент слияния.

Например, я установил DiffMerge как инструмент для git merge, установив набор правил которые позволяют этому инструменту слияния игнорировать eol для определенных типов файлов.


Настройка в Windows с MSysGit1.6.3 для сеанса DOS или git bash с помощью DiffMerge или KDiff3:

  • установите каталог в PATH (здесь: c:\HOMEWARE\cmd).
  • добавьте в этот каталог script merge.sh(обертка для вашего любимого инструмента слияния)

merge.sh:

#!/bin/sh

# Passing the following parameters to mergetool:
#  local base remote merge_result

alocal=$1
base=$2
remote=$3
result=$4

if [ -f $base ]
then
    #"C:/Program Files/SourceGear/DiffMerge/DiffMerge.exe" "$alocal" "$base" "$remote" -m --result="$result" --title1="Mine" --title2="Merging to: $result" --title3="Theirs"

    # for merge respecting eol, KDiff3 is better than DiffMerge (which will always convert LF into CRLF)
    # KDiff3 will display eol choices (if Windows: CRLF, if Unix LF)
    "C:/Program Files/KDiff3/kdiff3.exe" -m "$base" "$alocal" "$remote" -o "$result"
else
    #there is not always a common ancestor: DiffMerge needing 3 files, BASE will be the result
    #"C:/Program Files/SourceGear/DiffMerge/DiffMerge.exe" "$alocal" "$result" "$remote" -m --result="$result" --title1="Mine" --title2="Merging to: $result" --title3="Theirs"

    # KDiff3 however does know how to merge based on 2 files (not just 3)
    "C:/Program Files/KDiff3/kdiff3.exe" -m "$base" "$remote" -o "$result"
fi
  • Объявите свою оболочку слияния для Git

Git команды конфигурации:

git config --global merge.tool diffmerge
git config --global mergetool.diffmerge.cmd "merge.sh \"$PWD/$LOCAL\" \"$PWD/$BASE\" \"$PWD/$REMOTE\" \"$PWD/$MERGED\"
git config --global mergetool.diffmerge.trustExitCode false
git config --global mergetool.diffmerge.keepBackup false
  • Убедитесь, что autoCRLF false

Git config на системном уровне:

git config ---system core.autoCRLF=false
  • Проверьте, что, когда две строки идентичны (но их символы eol), оба DiffMerge или KDiff3 будут игнорировать эту строку во время слияния.

DOS script (примечание: команда dos2unix приходит отсюда и используется для имитации стиля UNIX-eol. был скопирован в каталог, упомянутый в начале этого ответа.):

C:\HOMEWARE\git\test>mkdir test_merge C:\HOMEWARE\git\test>cd test_merge C:\HOMEWARE\git\test\test_merge>git init C:\HOMEWARE\git\test\test_merge>echo a1 > a.txt & echo a2 >> a.txt C:\HOMEWARE\git\test\test_merge>git add a.txt C:\HOMEWARE\git\test\test_merge>git commit -m "a.txt, windows eol style" C:\HOMEWARE\git\test\test_merge>git checkout -b windows Switched to a new branch 'windows' C:\HOMEWARE\git\test\test_merge>echo a3 >> a.txt & echo a4 >> a.txt C:\HOMEWARE\git\test\test_merge>git add a.txt C:\HOMEWARE\git\test\test_merge>git commit -m "add two lines, windows eol style" C:\HOMEWARE\git\test\test_merge>git checkout master C:\HOMEWARE\git\test\test_merge>git checkout -b unix Switched to a new branch 'unix' C:\HOMEWARE\git\test\test_merge>echo au3 >> a.txt & echo au4 >> a.txt && echo au5 >> a.txt C:\HOMEWARE\git\test\test_merge>dos2unix a.txt Dos2Unix: Processing file a.txt ... C:\HOMEWARE\git\test\test_merge>git add a.txt C:\HOMEWARE\git\test\test_merge>git commit -m "add 3 lines, all file unix eol style" [unix c433a63] add 3 lines, all file unix eol style C:\HOMEWARE\git\test\test_merge>git merge windows Auto-merging a.txt CONFLICT (content): Merge conflict in a.txt Automatic merge failed; fix conflicts and then commit the result. C:\HOMEWARE\git\test\test_merge>git ls-files -u 100644 39b4c894078a02afb9b1dfeda6f1127c138e38df 1 a.txt 100644 28b3d018872c08b0696764118b76dd3d0b448fca 2 a.txt 100644 3994da66530b4df80189bb198dcfac9b8f2a7b33 3 a.txt C:\HOMEWARE\git\test\test_merge>git mergetool Merging the files: a.txt Normal merge conflict for 'a.txt': {local}: modified {remote}: modified Hit return to start merge resolution tool (diffmerge):

В этот момент (нажатие "return" ) откроется DiffMerge или KDiff3, и вы сами увидите, какие линии фактически объединены, а какие строки игнорируются.

Предупреждение: файл результатов всегда будет находиться в режиме Windows eol (CRLF) с помощью DiffMerge...
KDiff3 предлагает сохранить так или иначе.

Ответ 2

Я искал тот же ответ, и я узнал this

Объединение ветвей с различными атрибутами проверки/проверки

Если вы добавили атрибуты к файлу, которые вызывают каноническое формат репозитория для изменения этого файла, например, добавление фильтр очистки/размытия или атрибуты text/eol/ident, слияние чего-либо где атрибут не на месте, обычно вызывает слияние конфликты.

Чтобы предотвратить эти ненужные конфликты слияния, git может быть предложено запустить виртуальный выезд и регистрация всех трех этапов файла, когда разрешая трехстороннее слияние, установив merge.renormalize переменная конфигурации. Это предотвращает изменения, вызванные регистрацией преобразование из вызывающих ложных конфликтов слияния при преобразовании файла сливается с непревращенным файлом.

До тех пор, пока "smudge → clean" приводит к тому же выводу, что и "чистый", даже если файлы уже смазаны, эта стратегия будет автоматически разрешает все связанные с фильтрами конфликты. Фильтры, которые делают не действуют таким образом, могут вызывать дополнительные конфликты слияния, которые должны быть разрешено вручную.

Итак, запуск этой команды в любом репозитории сделает трюк:

git config merge.renormalize true

Ответ 4

Как в этом ответе: fooobar.com/questions/6463/...

Вы можете попробовать: git merge -s recursive -Xignore-space-at-eol

Ответ 5

То, что я сделал, это оставить все по умолчанию (т.е. autocrlf = true), коснуться всех файлов (find. -exec touch {} \;), позволить git видеть их как "измененные" и передавать их обратно, а также с этим. В противном случае вы всегда будете страдать от раздражающих сообщений или неожиданных различий или должны отключить все git пробельные функции.

Вы потеряете информацию о вине, но лучше сделать это раньше, чем позже:)

Ответ 6

"git merge -Xrenormalize" работает как шарм.

Ответ 8

http://stahlforce.com/dev/index.php?tool=remcrlf

Я попробовал, но если после последней строки вашего кода у вас еще нет CRLF, он добавляет сам LF, и файл выглядит измененным в git. Помимо этого он работает.

Ответ 9

Теперь мне кажется, что лучший способ - нормализовать окончания строк на обеих ветвях (и совершить) до их объединения.

Я googled "конвертировать crlf в lf" и нашел это в качестве первых результатов:
http://stahlforce.com/dev/index.php?tool=remcrlf

Я загрузил его и использовал, кажется хорошим инструментом.

>sfk remcr . .py

Обязательно укажите каталог и тип файла (например .py), иначе он может попытаться испортить содержимое каталога .git!

Ответ 10

AFAICT (я не пробовал), вы можете использовать git diff для сравнения ветки, которую хотите объединить с общим предком, а затем применить результаты с помощью git apply. Обе команды имеют опции --ignore-whitespace, чтобы игнорировать ошибки окончания строки и ошибки пробела.

К сожалению, если исправление не применяется чисто, вся операция прерывается. Вы не можете исправить конфликты слияния. Существует опция --reject, позволяющая оставить неуправляемые куски в файлах .rej, что помогает, но не совпадает с конфликтами слияния, показанными в одном файле.

Ответ 11

После чтения Разрешить конфликты слияния: принудительно перезаписать все файлы

Я наконец решил мою версию этой проблемы. Я пытался вытащить обновления из восходящего репо, но мой текущий имел проблемы, связанные с CRLF, и не смог слить в качестве результата. Следует отметить, что у меня не было ЛОКАЛЬНЫХ ИЗМЕНЕНИЙ, о которых мне нужно было беспокоиться. Следующие шаги решили мою проблему:

В соответствии с инструкциями github по синхронизации вилок (https://help.github.com/articles/syncing-a-fork/):

  • git fetch upstream

  • git reset --hard upstream/master
    Мое ограниченное понимание git говорит мне, что это делает то, что я хочу, - сворачивая свою вилку (без фактических незафиксированных изменений), чтобы получить все изменения, внесенные в исходный источник. Согласно исходной странице, этот шаг обычно не требуется, но проблема CRLF потребовала.

  • git merge upstream/master

  • git push

Ответ 12

однако я предлагаю использовать такой инструмент, как sed, для достижения правильных окончаний строк, а затем файлов diff. Я провел пару часов в разных проектах с различными окончаниями линии.

Лучший способ:

  • копировать только файлы проекта (опустить каталог .git) в другой каталог, создавать в нем репозиторий, затем добавлять файлы и фиксировать их (должно быть на главной ветке в новом репозитории).
  • копировать файлы из второго проекта в одну и ту же папку, но другую ветку, например dev (git checkout -b dev), фиксировать файлы в этой ветки и запускать (если первый проект находится в главном):      git diff master..dev --names-only для просмотра только имен измененных файлов