git-diff ігнорувати ^ M


474

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

Чим відрізняється попередня версія?

Чи є такий варіант, як "трактувати ^ М як новий рядок, коли відрізняється"?

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>

ОНОВЛЕННЯ:

тепер я написав сценарій Ruby, який перевіряє останні 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

7
Ви , можливо, хотіли git diff -b- я показав це в stackoverflow.com/a/46265081/58794
Джейсон Pyeron

6
З Git 2.16 (Q1 2018) у вас буде git diff --ignore-cr-at-eol. Дивіться мою відповідь нижче .
VonC

7
@JasonPyeron і для майбутніх Googlers: мені довелося шукати, що git diff -bідентично git diff --ignore-space-change.
Гогович

Відповіді:


392

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 описано на сторінці man .


1
Ні, звичайно, ні, як тільки налаштування є, воно беззвучно перетворюється при здійсненні. Якщо все працює так, як я думаю, це робиться, тобто…
nes1983

1
Проблема полягає в тому, що у мене вже є деякі файли у сховищі, які мають закінчення CRLF, а інші - ні. Я підозрюю, що Adobe Flash додає CRLF, хоча я використовую версію Mac. Мені потрібно порівняти старі версії цих файлів. Перетворення закінчень рядків, починаючи з цього моменту, не вирішує проблеми зі старими версіями: - /
neoneye

65
Ви не працюєте з файлами CRLF тут, принаймні, не в тому прикладі, який ви розмістили. Це старий мак-файл (просто використовує \ r для EOL). Ось чому різниця відображається в одному рядку. Файл, що використовує dos EOL, буде чітко відображати кожен рядок із заднім ^ M, через який ви можете сказати, щоб отримати обробку через git config core.whitespace cr-at-eol.
jamessan

12
Я намагаюся це зробити, але я продовжую отримувати warning: LF will be replaced by CRLFзамість цього warning: CRLF will be replaced by LF, і я в Linux. Будь-яка ідея чому? Я хочу, щоб все закінчувалося на LF, а не на CRLF!
trusktr

5
@trusktr, зі мною це сталося те саме У Linux з випадковим CRLF, git config --global core.autocrlf inputвиконайте дії, виконайте кроки у цій відповіді (rm, add, commit), і ви отримаєте warning: CRLF will be replaced by LF. The file will have its original line endings in your working directory.. Видаліть файли (тому що вони мають оригінальний, неправильний CRLF) та перевірте їх ще раз з останнього комітету "Виправити CRLF".
jmmut

370

Розвиваючись в Windows, я зіткнувся з цією проблемою при використанні git tfs. Я вирішив це таким чином:

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

Це в основному говорить Git, що кінцевий рядок CR не є помилкою. Як результат, ці дратівливі ^Mсимволи більше не з’являються в кінці рядків у git diff,git show і т.д.

Схоже, інші налаштування залишаються такими, які є; наприклад, додаткові пробіли в кінці рядка все ще відображаються як помилки (виділені червоним кольором) у розл.

(Інші відповіді на це натякали, але вище вказано саме те, як встановити налаштування. Щоб встановити налаштування лише для одного проекту, опустіть --global.)

EDIT :

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

  • НЕТ налаштування core.eol
  • НЕ налаштування core.whitespace
  • НЕ налаштування core.autocrlf
  • Запустивши інсталятор Git для Windows, ви отримаєте ці три варіанти:
    • Оформити замовлення в стилі Windows, виконайте закінчення ліній у стилі Unix <- виберіть цей
    • Оформити замовлення як такий, виконайте закінчення ліній у стилі Unix
    • Оформити замовлення як є, зробити так, як є

Якщо вам потрібно використовувати параметр пробілу, вам, ймовірно, слід ввімкнути його лише на основі проекту, якщо вам потрібно взаємодіяти з TFS. Просто опустіть --global:

git config core.whitespace cr-at-eol

Якщо вам потрібно видалити деякі основні налаштування. * Найпростіший спосіб - запустити цю команду:

git config --global -e

Це відкриє ваш глобальний файл .gitconfig в текстовому редакторі, і ви можете легко видалити рядки, які ви хочете видалити. (Або ви можете поставити "#" перед ними, щоб прокоментувати їх.)


30
Для тих , хто знаходить це зараз, це варто відзначити , що Checkout Windows-стиль, роблять Unix-стиль лінія закінчення авто-набори core.autocrlfдляtrue
К. Карпентер

14
Зауважте, що лінія git config --global core.whitespace cr-at-eolбуде вимикати інші параметри, які за замовчуванням. Існує три параметри за замовчуванням: blank-at-eol, blank-at-eof та space-before-tab. Отже, щоб увімкнути cr-at-eol, зберігаючи інші, які вам знадобляться git config --global core.whitespace blank-at-eol,blank-at-eof,space-before-tab,cr-at-eol.
Zitrax

2
Що стосується мого проекту (це було оформлення замовлення в Windows, і я переглядаю його в Linux), я cr-at-eolпозбувся ^Mв кінці рядків git diffвсе в порядку, але GIT все одно показав ці рядки як різні, хоча закінчення рядка було єдиною різницею.
Jānis Elmeris

SourceInsight продовжує натискати символ ^ M, а git як і раніше показує різницю в кінцях рядків. @ Команда Zitrax - це правильна відповідь на мій випадок, git diff показує гарний та чистий вихід.
Lê Quang Duy

3
Я думаю, що git потребує трохи більшої складності, ще декілька суперечливих налаштувань для кінця рядка. Я думаю, що git повинен більше турбуватися про мої пробіли. Наприклад, киньте непов’язану фатальну помилку і залиште сховище у пошкодженому стані, коли натрапите на закінчення рядків Mac на машині Windows (але не Linux). Я маю на увазі, чому я б використовував VCS, який би заперечував, що це бізнес, і дозволити мені використовувати будь-які закінчення рядка, які я хочу? Я бачу, що вони намагаються, але вони повинні зайняти ще півдесятка більше рядкових поведінки, щоб вирішити проблему, яка не існує. Вони майже там! Так тримати.
Рольф

125

Спробуйте git diff --ignore-space-at-eol, або git diff --ignore-space-change, або git diff --ignore-all-space.


22
Ніщо з цього насправді не впливає на персонажа, що ідентифікує новий рядок.
nes1983

4
Я також спробував "-w", але не пощастило, все ще трактує це як єдиний рядок. Наступний проект Я повинен пам’ятати, щоб ніколи не вводити жодного CR у вихідний код.
neoneye

3
Просто запам’ятайте git config --global core.autocrlf true, або помиліть git folks до тих пір, поки вони не зроблять його за замовчуванням :)
nes1983

10
Це вирішило мою проблему, не змінюючи autocrlfналаштувань. Дякую!
nneonneo

11
ці прапори не впливають на мене ... все ще відображається ^ M як різниться
Магнус

103

Також дивіться:

core.whitespace = cr-at-eol

або рівнозначно,

[core]
    whitespace = cr-at-eol

де whitespaceпередує символ табуляції .


4
Так, це зробило інструмент git diff (також використовується в git show), перестаньте клопотати мене про ^Mзмінені лінії! :)
Rijk

2
з будь-якої причини це не працювало для мене. Спробував це як зі знаком =, так і без =. git diffвсе ще відображається ^ М символів.
Денніс

6
Два способи зробити це: один, додайте рядок вище дословно у свій .gitconfig або в .git / config, або в ~ / .gitconfig; два, git config --global core.whitespace cr-at-eol(де - глобальний необов’язковий, якщо ви просто хочете його на репо, на якому ви працюєте)
К. Карпентер

Це працювало для мене в Windows 7, хоча я просто помістив його, [core]щоб я міг замінити core.префікс символом TAB.
Rufflewind

Це питання було вище , як сховатися ^Mв git diff, а не про те , як не ставити в ^ М , в першу чергу. Це означає, що прийнята відповідь про зміну core.autocrlfне найкраща, оскільки вона мовчки змінює файли без підтвердження користувача.
деддебм

45

Чому ти їх отримуєш ^Mу своєму git diff?

У моєму випадку я працював над проектом, розробленим в Windows, і я використовував OS X. Коли я змінив код, я побачив ^Mнаприкінці рядків, які я додав git diff. Я думаю, що ^Mвони з'являлися, тому що вони були різними закінченнями рядків, ніж решта файлу. Оскільки решта файлу була розроблена в Windows, він використовував CRзакінчення рядків, а в OS X використовує LFзакінчення рядків.

Мабуть, розробник Windows під час встановлення Git не використовував опцію " Оформити стиль в Windows, скопіювати закінчення ліній у стилі Unix ".

То що нам робити з цього приводу?

Можна дозволити користувачам Windows перевстановити git та використовувати " Checkout Windows-style, здійснити завершення рядків у стилі Unix опцією ". Це те, що я б хотів, тому що я бачу Windows як виняток у рядку, що закінчується символами, і Windows таким чином виправляє свою проблему.

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

  1. Видаліть усі файли з сховища, але не з вашої файлової системи.

    git rm --cached -r .
    
  2. Додайте .gitattributesфайл, який примушує певні файли використовувати для LFзакінчення рядка. Помістіть це у файл:

    *.ext text eol=crlf
    

    Замініть .extрозширення файлів, які ви хочете відповідати.

  3. Додайте всі файли ще раз.

    git add .
    

    Це покаже такі повідомлення:

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

  5. Покладіть і просуньте все це.

  6. Видаліть і перевірте відповідні файли в усіх системах, де вони використовуються. У системах Windows переконайтесь, що вони тепер використовують опцію " Оформити замовлення в стилі Windows, ввести лінійні закінчення в стилі Unix ". Ви також повинні зробити це в системі, де ви виконували ці завдання, тому що при додаванні файлів 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


4
Щоб виправити всі закінчення рядків у певному файлі, якщо використовується Sublime Text, ви можете перейти до View-> Line Endingsта натиснути на Unix.
Топ Хант

Що саме це ^Mозначає? Це вікно чи Linux Linux? Або це просто "інший" новий рядок порівняно з іншими новинками у файлі?
buhtz

Хороший, я думаю, що це просто "інший" новий рядок (відрізняється від більшості інших)
gitaarik

-1, оскільки перевстановлення git для виконання git config --global core.autocrlf trueє надмірним, а анти-Windows / антикампанія CRвидається дотичною для питання.
RJFalconer

41

Чи є такий варіант, як "трактувати ^ М як новий рядок, коли відрізняється"?

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

Див. Комісію e9282f0 (26 жовтня 2017) Хуніо С Хамано ( gitster) .
Допомагав: Йоганнес Шинделін ( dscho) .
(Об'єднав Хуніо С Хамано - gitster- у комітеті 10f65c2 , 27 листопада 2017 р.)

різн .: --ignore-cr-at-eol

Новий варіант --ignore-cr-at-eolповідомляє, що машини диференціюватимуть поводження з поверненням у вагоні наприкінці (повної) лінії так, ніби її не існує.

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


@kaartic Дякую, що ви відредагували відповідь та посилалися на правильний комітет!
VonC

3
Незважаючи на те, що це загальнодобрана практика встановити так, git config --global core.autocrlf trueяк у прийнятій відповіді, це відповідає на питання ОП пряміше: "Чи існує варіант, як" трактувати ^ М як новий рядок, коли змінюється "?"
drkvogel

1
Станом на Git 2.20 це не приховує ^ M's
user1944491

@ user1944491 Я не помітив жодної регресії, тобто підвіконня ігнорує eol під час відміни цього параметра в Git 2.26.
VonC

@VonC Використання цього аргументу в команді git diff не працювало. Також не було встановлено значення core.whitespace, git version 2.20.1 (Apple Git-117)але додавання відповіді core.pager Джейсона Пієрона виправлено це. YMMV очевидно.
користувач1944491

26

TL; DR

Змініть core.pagerна "tr -d '\r' | less -REX", а не вихідний код

Ось чому

Показані ті досадні ^ М - артефакт колоризації та пейджера. введіть тут опис зображення Це викликано 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

Зауважимо, що примушування труби до меншої кількості не відображає ^ 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 config файл безпосередньо, це запис для оновлення / додавання:

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

У мене була ця проблема в репо, де деякі файли мали \r\nзакінчення рядків, а деякі - \nзакінчення рядків (не знаю, чи це актуально); відмінності колишніх показали ^Mв модифікованих лініях (тобто +лініях). core.autocrlfбуло встановлено true. Біг git config core.pager "tr -d '\r' | less -REX"позбувся набридливих ^Mс. Дякую!
labreuer

5
Дякую за це Це єдина відповідь, якщо вам потрібно працювати з різними закінченнями рядків у ваших репортажах - наприклад, ви використовуєте замовлення як таке є, цілеспрямовано виконувати як є.
Майк

git diff -bце те, що я шукав, але я вдячний за ретельне пояснення.
Мартін Берч

Це відповідь! Дякую. прапор -b для мене не працював.
Кріс

Так! З усіх відповідей на це запитання зміна [core]розділу файлу git "config" шляхом додавання pager = tr -d '\\r' | less -REXбула єдиною відповіддю, яка працювала для мене. Дякую!
Рашики

13

Я довго боровся з цією проблемою. На сьогодні найпростіше рішення - не турбуватися про ^ М символи та просто використовувати візуальний розрізний інструмент, який може впоратися з ними.

Замість введення:

git diff <commitHash> <filename>

спробуйте:

git difftool <commitHash> <filename>

1
Дякую! Також я просто запустив "git difftool", і в основному порівняв усі змінені файли в циклі
Bhanuprakash D


2

Як зазначає VonC, це вже включено в git 2.16+. На жаль, назва параметра ( --ignore-cr-at-eol) відрізняється від тієї, яку використовує GNU diff, до якої я звик ( --strip-trailing-cr).

Коли я стикався з цією проблемою, моїм рішенням було викликати GNU diff замість вбудованої diff git, оскільки мій 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'

але він не використовує налаштовані налаштування пейджера, тому я віддаю перевагу першим.


Цікава альтернатива моїй відповіді. Отримано.
VonC
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.