Возможно ли для git-merge игнорировать различия в конце строки? - PullRequest
140 голосов
/ 14 мая 2009

Возможно ли для git merge игнорировать различия в конце строки?

Может быть, я задаю не тот вопрос ... но:

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

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

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

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

Обновление:

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

Ответы [ 12 ]

107 голосов
/ 14 мая 2009

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

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

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

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

  • Fab-V упоминает ниже :
    git merge master -s recursive -X renormalize
    
    </ul>
    
    <hr>
    
    <p><a href="https://stackoverflow.com/users/245966/jakub-g">jakub.g</a> also <a href="/674365/vozmozhno-li-dlya-git-merge-ignorirovat-razlichiya-v-kontse-strokicomment41273803_862920">comments</a> that the <strong>strategies work also with cherry-picking</strong>: </p>
    
    <pre><code>git cherry-pick abcd123456 --strategy=recursive --strategy-option=renormalize 
    </code>

    Это работает намного лучше, чем 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, установив ruleset , который позволяет этому инструменту слияния игнорировать eol для файлов определенного типа.


    Установка в Windows, с MSysGit1.6.3, для сеансов DOS или Git bash, с DiffMerge или KDiff3:

    • установить каталог в вашей PATH (здесь: c:\HOMEWARE\cmd).
    • добавьте в этот каталог скрипт 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 config:

    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 (примечание: отсюда поступает команда 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):

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

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

89 голосов
/ 30 августа 2012

Я искал тот же ответ и узнал это

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

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

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

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

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

git config merge.renormalize true
22 голосов
/ 17 апреля 2013

После прочтения https://stackoverflow.com/a/12194759/1441706 и https://stackoverflow.com/a/14195253/1441706

для меня эта команда отлично справилась:

git merge master -s recursive -X renormalize
6 голосов
/ 07 января 2013

Как и в этом ответе: https://stackoverflow.com/a/5262473/943928

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

4 голосов
/ 05 сентября 2013

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

4 голосов
/ 14 мая 2009

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

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

1 голос
/ 24 января 2011

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

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

1 голос
/ 14 мая 2009

Не похоже, что это можно сделать напрямую, но этот пост предлагает обходной путь.

http://osdir.com/ml/git/2009-02/msg02532.html

0 голосов
/ 18 марта 2015

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

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

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

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

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

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

  1. git fetch upstream

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

  3. git merge upstream/master

  4. git push
...