git-diff 忽略 ^M

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1889559/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-10 07:29:54  来源:igfitidea点击:

git-diff to ignore ^M

gitdiffnewlinegit-diff

提问by neoneye

In a project where some of the files contains ^M as newline separators. Diffing these files are apparently impossible, since git-diff sees it as the entire file is just a single line.

在某些文件包含 ^M 作为换行符的项目中。区分这些文件显然是不可能的,因为 git-diff 认为整个文件只是一行。

How does one diff with the previous version?

一个与以前的版本有何不同?

Is there an option like "treat ^M as newline when diffing" ?

是否有“将 ^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:

更新:

now I have written a Ruby script that checks out the latest 10 revisions and converts CR to LF.

现在我已经编写了一个 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

采纳答案by nes1983

GitHub suggeststhat you should make sure to only use \n as a newline character in git-handled repos. There's an option to auto-convert:

GitHub 建议你应该确保在 git-handled repos 中只使用 \n 作为换行符。有一个选项可以自动转换:

$ git config --global core.autocrlf true

Of course, this is said to convert crlf to lf, while you want to convert cr to lf. I hope this still works …

当然,这个是说把crlf转为lf,而你想把cr转为lf。我希望这仍然有效……

And then convert your files:

然后转换您的文件:

# 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 is described on the man page.

core.autocrlf在手册页中有描述。

回答by Ryan Lundy

Developing on Windows, I ran into this problem when using git tfs. I solved it this way:

在 Windows 上开发,我在使用git tfs. 我是这样解决的:

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

This basically tells Git that an end-of-line CR is not an error. As a result, those annoying ^Mcharacters no longer appear at the end of lines in git diff, git show, etc.

这基本上告诉 Git 行尾 CR 不是错误。其结果是,那些烦人的^M字符不再出现在线路末端git diffgit show等等。

It appears to leave other settings as-is; for instance, extra spaces at the end of a line still show as errors (highlighted in red) in the diff.

其他设置似乎保持原样;例如,行尾的额外空格仍会在差异中显示为错误(以红色突出显示)。

(Other answers have alluded to this, but the above is exactly how to set the setting. To set the setting for only one project, omit the --global.)

(其他答案已经提到了这一点,但上面正是如何设置设置。要仅为一个项目设置设置,请省略--global.)

EDIT:

编辑

After many line-ending travails, I've had the best luck, when working on a .NET team, with these settings:

在经历了许多行结束的痛苦之后,我在 .NET 团队中工作时运气最好,使用以下设置:

  • NO core.eol setting
  • NO core.whitespace setting
  • NO core.autocrlf setting
  • When running the Git installer for Windows, you'll get these three options:
    • Checkout Windows-style, commit Unix-style line endings<-- choose this one
    • Checkout as-is, commit Unix-style line endings
    • Checkout as-is, commit as-is
  • 没有 core.eol 设置
  • 没有 core.whitespace 设置
  • 没有 core.autocrlf 设置
  • 运行适用于 Windows 的 Git 安装程序时,您将获得以下三个选项:
    • 签出 Windows 风格,提交 Unix 风格的行尾<-- 选择这个
    • 按原样结帐,提交 Unix 样式的行结尾
    • 按原样结帐,按原样提交

If you need to use the whitespace setting, you should probably enable it only on a per-project basis if you need to interact with TFS. Just omit the --global:

如果您需要使用空白设置,并且您需要与 TFS 交互时,您可能应该仅在每个项目的基础上启用它。只需省略--global

git config core.whitespace cr-at-eol

If you need to remove some core.* settings, the easiest way is to run this command:

如果您需要删除某些 core.* 设置,最简单的方法是运行以下命令:

git config --global -e

This opens your global .gitconfig file in a text editor, and you can easily delete the lines you want to remove. (Or you can put '#' in front of them to comment them out.)

这将在文本编辑器中打开您的全局 .gitconfig 文件,您可以轻松删除要删除的行。(或者您可以在它们前面加上“#”以将它们注释掉。)

回答by Jakub Nar?bski

Try git diff --ignore-space-at-eol, or git diff --ignore-space-change, or git diff --ignore-all-space.

试试git diff --ignore-space-at-eol、 或git diff --ignore-space-change、 或git diff --ignore-all-space

回答by Vladimir Panteleev

Also see:

另见:

core.whitespace = cr-at-eol

or equivalently,

或等效地,

[core]
    whitespace = cr-at-eol

where whitespaceis preceded by a tabcharacter.

wherewhitespace前面是制表符。

回答by gitaarik

Why do you get these ^Min your git diff?

你为什么把这些^M放在你的git diff

In my case I was working on a project which was developed in Windows and I used OS X. When I changed some code, I saw ^Mat the end of the lines I added in git diff. I think the ^Mwere showing up because they were different line endings than the rest of the file. Because the rest of the file was developed in Windows it used CRline endings, and in OS X it uses LFline endings.

就我而言,我正在处理一个在 Windows 中开发的项目,我使用的是 OS X。当我更改一些代码时,我看到^Mgit diff. 我认为^M它们之所以出现是因为它们的行尾与文件的其余部分不同。因为文件的其余部分是在 Windows 中开发的,所以它使用CR行尾,而在 OS X 中它使用LF行尾。

Apparently, the Windows developer didn't use the option "Checkout Windows-style, commit Unix-style line endings" during the installation of Git.

显然,Windows 开发人员在安装 Git 期间没有使用选项“ Checkout Windows-style, commit Unix-style lineendings”。

So what should we do about this?

那么我们应该怎么做呢?

You can have the Windows users reinstall git and use the "Checkout Windows-style, commit Unix-style line endings" option. This is what I would prefer, because I see Windows as an exception in its line ending characters and Windows fixes its own issue this way.

您可以让 Windows 用户重新安装 git 并使用“ Checkout Windows-style, commit Unix-style lineendings”选项。这是我更喜欢的,因为我将 Windows 视为其行尾字符的例外,而 Windows 以这种方式修复了自己的问题。

If you go for this option, you should however fix the current files (because they're still using the CRline endings). I did this by following these steps:

如果您选择此选项,则应该修复当前文件(因为它们仍在使用CR行尾)。我按照以下步骤完成了此操作:

  1. Remove all files from the repository, but not from your filesystem.

    git rm --cached -r .
    
  2. Add a .gitattributesfile that enforces certain files to use a LFas line endings. Put this in the file:

    *.ext text eol=crlf
    

    Replace .extwith the file extensions you want to match.

  3. Add all the files again.

    git add .
    

    This will show messages like this:

    warning: CRLF will be replaced by LF in <filename>.
    The file will have its original line endings in your working directory.
    
  4. You could remove the .gitattributesfile unless you have stubborn Windows users that don't want to use the "Checkout Windows-style, commit Unix-style line endings" option.

  5. Commit and push it all.

  6. Remove and checkout the applicable files on all the systems where they're used. On the Windows systems, make sure they now use the "Checkout Windows-style, commit Unix-style line endings" option. You should also do this on the system where you executed these tasks because when you added the files git said:

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

    You can do something like this to remove the files:

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

    And then this to get them back with the correct line endings:

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

    Of course replacing .extwith the extension you want.

  1. 从存储库中删除所有文件,但不从文件系统中删除。

    git rm --cached -r .
    
  2. 添加.gitattributes强制某些文件使用 aLF作为行结尾的文件。把它放在文件中:

    *.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 用户不想使用“ Checkout Windows 风格,提交 Unix 风格行尾”选项。

  5. 承诺并推动这一切。

  6. 删除并签出所有使用它们的系统上的适用文件。在 Windows 系统上,确保他们现在使用“ Checkout Windows-style, commit Unix-style lineendings”选项。您还应该在执行这些任务的系统上执行此操作,因为在添加文件时 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你想要的扩展名替换。

Now your project only uses LFcharacters for the line endings, and the nasty CRcharacters won't ever come back :).

现在你的项目只使用LF字符作为行尾,讨厌的CR字符永远不会回来:)。

The other option is to enforce windows style line endings. You can also use the .gitattributesfile for this.

另一种选择是强制使用 Windows 样式的行尾。您也可以.gitattributes为此使用该文件。

More info: https://help.github.com/articles/dealing-with-line-endings/#platform-all

更多信息:https: //help.github.com/articles/dealing-with-line-endings/#platform-all

回答by VonC

Is there an option like "treat ^M as newline when diffing" ?

是否有“将 ^M 视为换行符”之类的选项?

There will be one with Git 2.16 (Q1 2018), as the "diff" family of commands learned to ignore differences in carriage return at the end of line.

Git 2.16(2018 年第一季度)将有一个,因为“ diff”命令系列学会了忽略行尾回车符的差异。

See commit e9282f0(26 Oct 2017) by Junio C Hamano (gitster).
Helped-by: Johannes Schindelin (dscho).
(Merged by Junio C Hamano -- gitster--in commit 10f65c2, 27 Nov 2017)

请参阅Junio C Hamano() 的提交 e9282f0(2017 年 10 月 26 日。 帮助者:约翰内斯·辛德林 ( )(由Junio C Hamano合并-- --commit 10f65c2,2017 年 11 月 27 日)gitster
dscho
gitster

diff: --ignore-cr-at-eol

A new option --ignore-cr-at-eoltells the diff machinery to treat a carriage-return at the end of a (complete) line as if it does not exist.

Just like other "--ignore-*" options to ignore various kinds of whitespace differences, this will help reviewing the real changes you made without getting distracted by spurious CRLF<->LFconversion made by your editor program.

差异: --ignore-cr-at-eol

一个新选项--ignore-cr-at-eol告诉 diff 机制将(完整)行末尾的回车视为不存在。

就像--ignore-*忽略各种空白差异的其他“ ”选项一样,这将有助于查看您所做的真实更改,而不会被CRLF<->LF编辑器程序所做的虚假转换分心。

回答by Jason Pyeron

TL;DR

TL; 博士

Change the core.pagerto "tr -d '\r' | less -REX", not the source code

更改core.pager"tr -d '\r' | less -REX",而不是源代码

This is why

这就是为什么

Those pesky ^M shown are an artifact of the colorization and the pager. enter image description hereIt is caused by less -R, a default git pager option. (git's default pager is less -REX)

显示的那些讨厌的 ^M 是着色和寻呼机的产物。在此处输入图片说明它是由less -R默认的 git pager 选项引起的。(git 的默认寻呼机是less -REX

The first thing to note is that git diff -bwill not show changes in white space (e.g. the \r\n vs \n)

首先要注意的是git diff -b不会显示空白处的变化(例如\r\n vs \n)

setup:

设置:

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

A quick test to create a unix file and change the line endings will show no changes with git diff -b:

创建 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

We note that forcing a pipe to less does not show the ^M, but enabling color and less -Rdoes:

我们注意到强制管道减少不会显示 ^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

The fix is shown by using a pipe to strip the \r (^M) from the output:

通过使用管道从输出中去除 \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

An unwise alternative is to use less -r, because it will pass through all control codes, not just the color codes.

一个不明智的选择是使用less -r,因为它将通过所有控制代码,而不仅仅是颜色代码。

If you want to just edit your git config file directly, this is the entry to update/add:

如果你只想直接编辑你的 git 配置文件,这是更新/添加的条目:

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

回答by Ian Wojtowicz

I struggled with this problem for a long time. By far the easiest solution is to not worry about the ^M characters and just use a visual diff tool that can handle them.

我在这个问题上挣扎了很长时间。到目前为止,最简单的解决方案是不用担心 ^M 字符,只需使用可以处理它们的视觉差异工具。

Instead of typing:

而不是键入:

git diff <commitHash> <filename>

try:

尝试:

git difftool <commitHash> <filename>

回答by alesub

In my case, what did it was this command:

就我而言,这是什么命令:

git config  core.whitespace cr-at-eol

Source: https://public-inbox.org/git/[email protected]/T/

来源:https: //public-inbox.org/git/[email protected]/T/

回答by Pedro Gimeno

As noted by VonC, this has already been included in git 2.16+. Unfortunately, the name of the option (--ignore-cr-at-eol) differs from the one used by GNU diff that I'm used to (--strip-trailing-cr).

正如 VonC 所指出的,这已经包含在 git 2.16+ 中。不幸的是,选项 ( --ignore-cr-at-eol)的名称与我习惯的 GNU diff 使用的名称 ( ) 不同--strip-trailing-cr

When I was confronted with this problem, my solution was to invoke GNU diff instead of git's built-in diff, because my git is older than 2.16. I did that using this command line:

当我遇到这个问题时,我的解决方案是调用GNU diff而不是git的内置diff,因为我的git是2.16以上的。我是用这个命令行做到的:

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

That allows using --strip-trailing-crand any other GNU diff options.

这允许使用--strip-trailing-cr和任何其他 GNU 差异选项。

There's also this other way:

还有另一种方式:

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

but it doesn't use the configured pager settings, which is why I prefer the former.

但它不使用配置的寻呼机设置,这就是我更喜欢前者的原因。