Make 'git diff'忽略M ^

在一个项目中,一些文件包含^M作为换行符 分隔器,区分这些文件显然是不可能的,因为

. git diff将整个文件视为一行 当比较当前和以前的git diff时,如何git diff 源代码文件的版本?< / p >

是否有一个选项,如“在区分时将^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>

更新:

我写了一个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
440352 次浏览

GitHub建议,你应该确保在git处理的回购中只使用\n作为换行符。有一个自动转换的选项:

$ 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"

核心。在手册页上描述了selflf。

试试git diff --ignore-space-at-eol,或者git diff --ignore-space-change,或者git diff --ignore-all-space

还看到:

core.whitespace = cr-at-eol

或者说,

[core]
whitespace = cr-at-eol

其中whitespace前面有一个选项卡字符。

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

而不是打字:

git diff <commitHash> <filename>

试一试:

git difftool <commitHash> <filename>

在Windows上开发时,我在使用git tfs时遇到了这个问题。我是这样解决的:

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

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

它似乎保持其他设置不变;例如,行尾的额外空格仍然在diff中显示为错误(用红色突出显示)。

(其他回答都提到了这一点,但上面说的正是如何设置设置。如果只为一个项目设置,请省略--global。)

# EYZ0:

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

  • 没有核心。终点设置
  • 没有核心。空白设置
  • 没有核心。autocrlf设置
  • 当在Windows上运行Git安装程序时,你会得到这三个选项:
    • 选择这个
    • 按原样签出,提交unix风格的行结束符
    • 按原样签出,按原样提交
    • 李< / ul > < / >

    如果您需要使用空白设置,那么如果您需要与TFS交互,则应该仅在每个项目上启用它。只需省略--global:

    git config core.whitespace cr-at-eol
    

    如果你需要去核的话。*设置,最简单的方法是运行这个命令:

    git config --global -e
    

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

为什么你的git diff里有^M ?

以我为例,我正在开发一个在Windows上开发的项目,我使用的是Linux。当我修改一些代码时,我在git diff中添加的行末尾看到了^M。我认为^M显示出来是因为它们与文件的其余部分不同。因为文件的其余部分是在Windows中开发的,所以使用了CRLF行结束符,而在Linux中使用了LF行结束符。

显然,Windows开发人员没有使用选项& 签出windows样式,提交unix样式的行结束符"在安装Git期间。

那么我们该怎么做呢?

您可以让Windows用户重新安装git,并使用& 签出windows样式,提交unix样式的行结束符"选择。这是我更喜欢的,因为我认为Windows在行尾字符方面是个例外,Windows用这种方式解决了自己的问题。

如果你选择这个选项,你应该修复当前文件(因为他们仍然使用CRLF行结束符)。我是通过以下步骤做到的:

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

     git rm --cached -r .
    
  2. 添加一个.gitattributes文件,强制某些文件使用LF作为行结束符。把这个放进文件里:

     * text=auto eol=lf
    
  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用户不想使用&;# eyz1 &;选择。

  5. 提交并全部推送。

  6. 删除并签出所有系统上使用它们的适用文件。在Windows系统上,确保他们现在使用&;# eyz0 &;选择。你也应该在你执行这些任务的系统上这样做,因为当你添加文件时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文件。

< p >更多信息: # EYZ0 < / p >

博士TL;

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,但启用color和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

有一个选项,如“对待^M换行时,差异”?

Git 2.16(2018年第一季度)将会出现一个问题,因为“diff”命令家族学会了忽略行末回车中的差异。

参见提交e9282f0(2017年10月26日) 得益于:# EYZ1。< br > (由滨野朱尼奥——gitster——提交10 f65c2合并,2017年11月27日)

diff: # EYZ0

一个新的选项--ignore-cr-at-eol告诉diff机器在(完整的)行末尾处理回车,就像它不存在一样。

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

正如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 diff选项。

还有另一种方式:

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

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

在我的例子中,这是一个命令:

git config  core.whitespace cr-at-eol

来源:# EYZ0

如果你只是想要一个快速的行,使git diff,但不显示不同的结尾(因此,^M)使用一个在最初的问题的第一个评论,它为我工作:

 git diff -b

考虑到这一点,从长远来看,您应该像所有其他答案所建议的那样,正确配置行结束符。

如果git补丁已经在windows机器上生成,并且您正在使用它,您可以在Linux中使用dos2unix实用程序格式化补丁。

find -name "*.patch"| xargs dos2unix

这将解决^M在EOL,你将能够git应用补丁在你的linux机器。