Git -дифф для игнорирования ^ M

В проекте, где некоторые из файлов содержат ^ M как разделители строк. Разделение этих файлов, по-видимому, невозможно, так как git -diff видит, что весь файл представляет собой только одну строку.

Как отличается от предыдущей версии?

Есть ли опция "treat ^ M как символ новой строки при различении"?

prompt> git-diff "HEAD^" -- MyFile.as 
diff --git a/myproject/MyFile.as b/myproject/MyFile.as
index be78321..a393ba3 100644
--- a/myproject/MyFile.cpp
+++ b/myproject/MyFile.cpp
@@ -1 +1 @@
-<U+FEFF>import flash.events.MouseEvent;^Mimport mx.controls.*;^Mimport mx.utils.Delegate
\ No newline at end of file
+<U+FEFF>import flash.events.MouseEvent;^Mimport mx.controls.*;^Mimport mx.utils.Delegate
\ No newline at end of file
prompt>

UPDATE:

теперь я написал script, который проверяет последние 10 версий и преобразует CR в LF.

require 'fileutils'

if ARGV.size != 3
  puts "a git-path must be provided"
  puts "a filename must be provided"
  puts "a result-dir must be provided"
  puts "example:"
  puts "ruby gitcrdiff.rb project/dir1/dir2/dir3/ SomeFile.cpp tmp_somefile"
  exit(1)
end

gitpath = ARGV[0]
filename = ARGV[1]
resultdir = ARGV[2]

unless FileTest.exist?(".git")
  puts "this command must be run in the same dir as where .git resides"
  exit(1)
end

if FileTest.exist?(resultdir)
  puts "the result dir must not exist"
  exit(1)
end
FileUtils.mkdir(resultdir)

10.times do |i|
  revision = "^" * i
  cmd = "git show HEAD#{revision}:#{gitpath}#{filename} | tr '\\r' '\\n' > #{resultdir}/#{filename}_rev#{i}"
  puts cmd 
  system cmd
end

Ответ 1

GitHub предлагает, что вы должны использовать только \n в качестве символа новой строки в git -обработанных репозиториях. Там есть возможность автоматического конвертирования:

$ git config --global core.autocrlf true

Конечно, говорят, что он преобразует crlf в lf, в то время как вы хотите преобразовать cr в lf. Я надеюсь, что это все еще работает...

И затем конвертируйте свои файлы:

# Remove everything from the index
$ git rm --cached -r .

# Re-add all the deleted files to the index
# You should get lots of messages like: "warning: CRLF will be replaced by LF in <file>."
$ git diff --cached --name-only -z | xargs -0 git add

# Commit
$ git commit -m "Fix CRLF"

core.autocrlf описывается справочная страница.

Ответ 2

Разработка в Windows, я столкнулся с этой проблемой при использовании git tfs. Я решил это так:

git config --global core.whitespace cr-at-eol

В основном это означает Git, что конец строки CR не является ошибкой. В результате эти раздражающие символы ^M больше не отображаются в конце строк в git diff, git show и т.д.

Похоже, что остальные настройки находятся как есть; например, дополнительные пробелы в конце строки по-прежнему отображаются как ошибки (выделенные красным цветом) в diff.

(Другие ответы ссылались на это, но выше всего точно, как установить параметр. Чтобы установить настройку только для одного проекта, опустите --global.)

ИЗМЕНИТЬ

После многих травм, заканчивающихся окончанием строки, мне повезло, когда я работаю над командой .NET с этими настройками:

  • НЕТ настроек core.eol
  • NO core.whitespace
  • НЕТ настроек core.autocrlf
  • При запуске установщика Git для Windows вы получите следующие три варианта:
    • Оформить заказ Windows-стиль, зафиксировать окончание строк в стиле Unix < - выбрать этот
    • Checkout as-is, фиксация строк в стиле Unix
    • Checkout as-is, commit as-is

Если вам нужно использовать параметр пробелов, возможно, вы должны включить его только для каждого проекта, если вам нужно взаимодействовать с TFS. Просто опустите --global:

git config core.whitespace cr-at-eol

Если вам нужно удалить некоторые основные настройки. *, самый простой способ - запустить эту команду:

git config --global -e

Это открывает ваш глобальный файл .gitconfig в текстовом редакторе, и вы можете легко удалить строки, которые хотите удалить. (Или вы можете поставить '#' перед ними, чтобы прокомментировать их.)

Ответ 3

Попробуйте git diff --ignore-space-at-eol или git diff --ignore-space-change или git diff --ignore-all-space.

Ответ 4

Также смотрите:

core.whitespace = cr-at-eol

или эквивалентно,

[core]
    whitespace = cr-at-eol

где whitespace предшествует символ табуляции.

Ответ 5

Почему вы получаете эти ^M в своем git diff?

В моем случае я работал над проектом, который был разработан в Windows, и я использовал OS X. Когда я изменил код, я увидел ^M в конце строк, которые я добавил в git diff. Я думаю, что ^M показывались, потому что они были разными окончаниями строк, чем остальная часть файла. Поскольку остальная часть файла была разработана в Windows, она использовала окончание строк CR, а в OS X использовала окончание строки LF.

По-видимому, разработчик Windows не использовал опцию "Checkout Windows-style, фиксация строк в стиле Unix" во время установки Git.

Итак, что нам с этим делать?

У вас могут быть пользователи Windows переустановить git и использовать опцию "Checkout Windows-style, commit Unix style endings" . Это то, что я бы предпочел, потому что я вижу Windows как исключение в этом символе окончания строки, и Windows исправляет эту проблему таким образом.

Если вы перейдете к этой опции, вы должны исправить текущие файлы (потому что они все еще используют окончания строки CR). Я сделал это, выполнив следующие шаги:

  • Удалите все файлы из репозитория, но не из вашей файловой системы.

    git rm --cached -r .
    
  • Добавьте файл .gitattributes, который принудительно использует определенные файлы для использования окончаний строки LF. Поместите это в файл:

    *.ext text eol=crlf
    

    Замените .ext на расширения файлов, которые вы хотите сопоставить.

  • Добавьте все файлы снова.

    git add .
    

    Здесь будут отображаться такие сообщения:

    warning: CRLF will be replaced by LF in <filename>.
    The file will have its original line endings in your working directory.
    
  • Вы можете удалить файл .gitattributes, если у вас нет упрямых пользователей Windows, которые не хотят использовать опцию "Checkout Windows-style, commit Unix style endings" .

  • Зафиксируйте и нажмите все.

  • Удалите и проверьте соответствующие файлы во всех системах, где они используются. В системах Windows убедитесь, что они теперь используют опцию "Checkout Windows-style, commit Unix style endings" . Вы также должны сделать это в системе, где вы выполнили эти задачи, потому что, когда вы добавили файлы git, сказали:

    The file will have its original line endings in your working directory.
    

    Вы можете сделать что-то вроде этого, чтобы удалить файлы:

    git ls | grep ".ext$" | xargs rm -f
    

    И затем это, чтобы вернуть их с правильными окончаниями строки:

    git ls | grep ".ext$" | xargs git checkout
    

    Конечно, заменив .ext на нужное расширение.

Теперь ваш проект использует только символы LF для окончаний строки, а отвратительные символы CR никогда не возвращаются:).

Другой вариант - принудительное завершение строк в стиле Windows. Вы также можете использовать файл .gitattributes для этого.

Дополнительная информация: https://help.github.com/articles/dealing-with-line-endings/#platform-all

Ответ 6

  Есть ли такая опция, как "трактовать ^ M как перевод строки при изменении"?

Будет один с Git 2.16 (Q1 2018), так как семейство команд "diff" научилось игнорировать различия в возврате каретки в конце строки.

См. коммит e9282f0 (26 октября 2017 г.) автора Джунио С. Хамано (gitster).
При поддержке: Йоханнес Шинделин (dscho).
(Merged by Junio C Hamano -- [TG43] -- in commit 10f65c2, 27 Nov 2017)

diff: --ignore-cr-at-eol

Новая опция --ignore-cr-at-eol говорит механизму сравнения обрабатывать возврат каретки в конце (полной) строки, как будто она не существует.

Как и другие опции "--ignore-*", позволяющие игнорировать различные различия между пробелами, это поможет проанализировать реальные изменения, которые вы внесли, не отвлекаясь на ложные преобразования CRLF<->LF, сделанные вашей программой-редактором.

Ответ 7

TL; DR

Измените core.pager на "tr -d '\r' | less -REX", а не на исходный код

Вот почему

Эти показные ^ M являются артефактом раскрашивания и пейджера. enter image description here Это вызвано less -R, опцией git-пейджера по умолчанию. (Git по умолчанию пейджер less -REX)

Первое, что следует отметить, это то, что git diff -b не будет отображать изменения в пустом пространстве (например,\r\n vs\n)

Установка:

git clone https://github.com/CipherShed/CipherShed
cd CipherShed

Быстрый тест для создания файла Unix и изменения концов строк не покажет изменений с помощью git diff -b:

echo -e 'The quick brown fox\njumped over the lazy\ndogs.' > test.txt
git add test.txt
unix2dos.exe test.txt
git diff -b test.txt

Мы отмечаем, что при наведении канала на less не отображается ^ M, но при включении цвета и less -R отображается:

git diff origin/v0.7.4.0 origin/v0.7.4.1 | less
git -c color.ui=always diff origin/v0.7.4.0 origin/v0.7.4.1 | less -R

Исправление показано с помощью канала, чтобы убрать \r (^ M) из вывода:

git diff origin/v0.7.4.0 origin/v0.7.4.1
git -c core.pager="tr -d '\r' | less -REX"  diff origin/v0.7.4.0 origin/v0.7.4.1

Неразумная альтернатива - использовать less -r, потому что он будет проходить через все управляющие коды, а не только цветовые коды.

Если вы хотите просто отредактировать файл конфигурации git напрямую, это запись для обновления/добавления:

[core]
        pager = tr -d '\\r' | less -REX

Ответ 8

Я долгое время боролся с этой проблемой. Самым простым решением является не беспокоиться о символах ^ M и просто использовать инструмент визуального разграничения, который может обрабатывать их.

Вместо ввода:

git diff <commitHash> <filename>

попробовать:

git difftool <commitHash> <filename>

Ответ 9

Как отмечает VonC, это уже было включено в git 2. 16+. К сожалению, название опции (--ignore-cr-at-eol) отличается от того, которое используется в GNU diff, к которому я привык (--strip-trailing-cr).

Когда я столкнулся с этой проблемой, я решил использовать GNU diff вместо встроенного в git diff, потому что мой git старше 2.16. Я сделал это с помощью этой командной строки:

GIT_EXTERNAL_DIFF='diff -u --strip-trailing-cr "$2" "$5";true;#' git diff --ext-diff

Это позволяет использовать --strip-trailing-cr и любые другие параметры различий в GNU.

Есть и другой способ:

git difftool -y -x 'diff -u --strip-trailing-cr'

но он не использует настроенные параметры пейджера, поэтому я предпочитаю первый.

Ответ 10

Если вы используете Eclipse, вы можете отключить ^M от git diff, установив File > Convert Line Delimiter To > Unix (LF, \n, 0A, ¶)