Возможно ли для git-merge игнорировать различия в конце строки?
Это возможно для git merge
игнорировать различия в конце строки?
Возможно я задаю не тот вопрос... но:
Я пытался использовать config.crlf input
но все стало немного грязно и вышло из-под контроля, особенно когда я применил его после свершившегося факта.
Во-первых, применение этой конфигурации после факта, похоже, не влияет на файлы, которые были зафиксированы в хранилище до применения этой опции. Другое дело, что внезапно все коммиты теперь приводят к большому количеству раздражающих предупреждающих сообщений о преобразовании CRLF в LF.
Если честно, мне все равно, какой конец строки используется, я лично предпочитаю стиль Unix \n
, но что угодно. Все, что меня волнует, для git merge
быть немного умнее и игнорировать различия в окончаниях строк.
Иногда у меня есть два идентичных файла, но git помечает их как конфликтующие (и конфликт - это весь файл) просто потому, что в них используется другой символ окончания строки.
Обновить:
я узнал что git diff
принимает --ignore-space-at-eol
вариант, можно ли было git merge
использовать эту опцию, а?
12 ответов
Обновление 2013:
Более поздние версии git разрешают использовать слияние со стратегией recursive
и вариант стратегии (-X
):
git merge -s рекурсивный -Xignore-space-at-eol
Но с помощью -Xignore-space-change
" также есть возможность
jakub.g также отмечает, что стратегии работают также с сбором вишни:
git cherry-pick abcd123456 --strategy=recursive --strategy-option=renormalize
Это работает намного лучше, чем ignore-all-space
,
Оригинальный ответ (май 2009 г.)
Патч для игнорирования стиля eol был предложен в июне 2007 года, но он касается только git diff --ignore-space-at-eol
не git merge
,
В то время был задан вопрос:
Должен
--ignore-space-at-eol
быть вариантомgit-merge
?
Слияния, где эта функциональность имеет значение.
Какова семантика автоматического разрешения слияния с этими действующими параметрами - используются ли они только для обнаружения переименования, или мы, например, не помечаем конфликтами только изменения пробелов? И если мы не делаем, какую версию мы принимаем автоматически?
Хулио С Хамано не был в восторге:
Это, конечно, заманчиво, но я подозреваю, что это следует оставить на более поздние этапы.
Я подозреваю, что это представило бы концепцию двух различных типов различий: один для механической обработки (т. Е. Использовать в слиянии с "git-merge-recursive" и применять с "git-am"), а другой - для проверки люди, чтобы понять.
Часто может оказаться полезным выполнить входные данные в последнем случае, даже если выходные данные, полученные при сравнении файлов с входными данными, могут быть нелегко использовать для механического применения.
Общая идея, когда дело доходит до git merge
, полагаться на сторонний инструмент слияния.
Например, я настроил DiffMerge как инструмент для слияния Git, установив набор правил, которые позволяют этому инструменту слияния игнорировать eol для файлов определенного типа.
Настройка в Windows, с MSysGit1.6.3, для сеансов DOS или Git bash, с DiffMerge или KDiff3:
- установить каталог в ваш путь (здесь:
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 предлагает сохранить так или иначе.
Я искал тот же ответ, и я узнал это
Объединение веток с различными атрибутами checkin / checkout
Если вы добавили в файл атрибуты, которые приводят к изменению канонического формата хранилища для этого файла, например, добавление фильтра clean / smudge или атрибутов text / eol / идент, объединение чего-либо, где атрибут отсутствует, обычно вызывает конфликты слияния,
Чтобы предотвратить эти ненужные конфликты слияния, git может сказать, что нужно выполнить виртуальную проверку и регистрацию всех трех этапов файла при разрешении трехстороннего слияния, задав переменную конфигурации merge.renormalize. Это предотвращает изменения, вызванные преобразованием при регистрации, из-за ложных конфликтов слияния, когда преобразованный файл объединяется с не преобразованным файлом.
До тех пор, пока "smudge → clean" приводит к тому же результату, что и "clean" даже к файлам, которые уже были загрязнены, эта стратегия автоматически разрешает все конфликты, связанные с фильтрами. Фильтры, которые не действуют таким образом, могут вызвать дополнительные конфликты слияния, которые должны быть разрешены вручную.
Таким образом, выполнение этой команды в любом хранилище сделает свое дело:
git config merge.renormalize true
После прочтения /questions/36786287/vozmozhno-li-dlya-git-merge-ignorirovat-razlichiya-v-kontse-stroki/36786306#36786306 и /questions/36786287/vozmozhno-li-dlya-git-merge-ignorirovat-razlichiya-v-kontse-stroki/36786309#36786309
для меня эта команда сделала свое дело отлично:
git merge master -s recursive -X renormalize
Как и в этом ответе: /questions/10544358/git-merge-i-ispravlenie-smeshannyih-probelov-i-vkladok-s-dvumya-vetvyami/10544375#10544375
Вы можете попробовать: git merge -s recursive -Xignore-space-at-eol
Что я сделал, так это оставил все по умолчанию (т.е. autocrlf=true), коснулся всех файлов (найдите. -Exec touch {} \;), позволил git увидеть их как "модифицированные" и зафиксировать их обратно, и покончим с этим. В противном случае вы всегда будете страдать от раздражающих сообщений или неожиданных различий, или вам придется отключить все пробелы в git.
Вы потеряете информацию о вине, но лучше сделать это раньше, чем позже:)
http://stahlforce.com/dev/index.php?tool=remcrlf
Я попробовал это сделать, но если после последней строки в вашем коде у вас еще не было CRLF, он добавляет сам LF, и файл выглядит измененным в git. Кроме этого это работает.
Не похоже, что это можно сделать напрямую, но этот пост предлагает обходной путь.
AFAICT, (я не пробовал) вы могли бы использовать git diff
сравнить ветвь, которую вы хотите объединить с общим предком, а затем применить результаты с git apply
, Обе команды имеют --ignore-whitespace
варианты игнорировать конец строки и ошибки пробела.
К сожалению, если патч не применяется корректно, вся операция прерывается. Вы не можете исправить конфликты слияния. E сть --reject
возможность оставить безошибочные куски в .rej
файлы, что помогает, но не то же самое, что конфликты слияния, показанные в одном файле.
Сейчас мне кажется, что лучший способ - это нормализовать окончания строк в обеих ветвях (и зафиксировать) перед их объединением.
Я погуглил "convert crlf to lf" и нашел это как первые результаты:
http://stahlforce.com/dev/index.php?tool=remcrlf
Я скачал его и использовал, похоже, хороший инструмент.
>sfk remcr . .py
Обязательно укажите каталог и тип файла (например,.py), иначе он может попытаться связываться с содержимым .git
каталог!
После прочтения Решить конфликты слияния: принудительно перезаписать все файлы
Я наконец решил свою версию этой проблемы. Я пытался получить обновления из вышестоящего репозитория, но у моего текущего были проблемы, связанные с 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
Тем не менее, я предлагаю использовать инструмент, подобный sed, для достижения правильных окончаний строк, а затем diff файлов. Я потратил пару часов на различные проекты с различными окончаниями.
Наилучшим способом было:
- копировать только файлы проекта (опустить
.git
каталог) в другой каталог, создайте в нем хранилище, затем добавьте файлы и зафиксируйте их (должно быть в главной ветке в новом хранилище). - скопировать файлы из второго проекта в ту же папку, но другую ветку, например
dev
(git checkout -b dev
), зафиксируйте файлы в этой ветке и запустите (если первый проект находится в master):git diff master..dev --names-only
видеть только имена измененных файлов