595

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

与以前的版本有何不同?

有没有像“差异时将 ^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
4

11 回答 11

479

GitHub 建议您应该确保在 git 处理的存储库中仅使用 \n 作为换行符。有一个自动转换的选项:

$ git config --global core.autocrlf true

当然,这里说的是把crlf转成lf,而你想把cr转成lf。我希望这仍然有效……</p>

然后转换您的文件:

# 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在手册页上有描述。

于 2009-12-11T17:43:44.587 回答
432

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

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

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

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

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

编辑

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

  • 没有 core.eol 设置
  • 没有 core.whitespace 设置
  • 没有 core.autocrlf 设置
  • 运行 Windows 的 Git 安装程序时,您将获得以下三个选项:
    • 签出 Windows 风格,提交 Unix 风格的行尾 <-- 选择这个
    • 按原样结帐,提交 Unix 风格的行尾
    • 按原样结帐,按原样提交

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

git config core.whitespace cr-at-eol

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

git config --global -e

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

于 2011-08-24T18:58:39.497 回答
155

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

于 2009-12-11T18:19:56.837 回答
111

另见:

core.whitespace = cr-at-eol

或等效地,

[core]
    whitespace = cr-at-eol

wherewhitespace前面有一个制表符。

于 2010-05-19T15:39:05.533 回答
52

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

就我而言,我正在从事一个在 Windows 中开发的项目,我使用的是 Linux。当我更改一些代码时,我^M在添加的行的末尾看到了git diff. 我认为^M之所以出现是因为它们的行尾与文件的其余部分不同。因为文件的其余部分是在 Windows 中开发的,所以它使用了CRLF行尾,而在 Linux 中它使用了LF行尾。

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

那么我们应该怎么做呢?

您可以让 Windows 用户重新安装 git 并使用“ Checkout Windows-style, commit Unix-style line endings ”选项。这是我更喜欢的,因为我认为 Windows 在其行尾字符中是一个例外,并且 Windows 以这种方式解决了它自己的问题。

但是,如果您选择此选项,则应该修复当前文件(因为它们仍在使用CRLF行尾)。我按照以下步骤做到了这一点:

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

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

     * 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 用户不想使用“ Checkout Windows-style, commit Unix-style line endings ”选项。

  5. 承诺并推动这一切。

  6. 删除并签出所有使用它们的系统上的适用文件。在 Windows 系统上,确保它们现在使用“ Checkout Windows-style, commit Unix-style line 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

于 2014-10-21T15:55:04.603 回答
48

有没有像“差异时将 ^M 视为换行符”这样的选项?

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

请参阅Junio C Hamano ( ) 的提交 e9282f0(2017 年 10 月 26 日。 帮助者:Johannes Schindelin ( )(由Junio C Hamano 合并——提交 10f65c2中,2017 年 11 月 27 日)gitster
dscho
gitster

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

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

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

于 2017-11-29T21:36:51.807 回答
36

TL;博士

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

这就是为什么

显示的那些讨厌的 ^M 是着色和寻呼机的产物。在此处输入图像描述 它是由less -R一个默认的 git pager 选项引起的。(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 配置文件,这是更新/添加的条目:

[core]
        pager = tr -d '\\r' | less -REX
于 2017-09-17T14:19:36.780 回答
24

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

git config  core.whitespace cr-at-eol

来源:https ://public-inbox.org/git/8d7e4807-9a79-e357-8265-95f22ab716e0@web.de/T/

于 2020-03-19T16:19:29.313 回答
14

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

而不是键入:

git diff <commitHash> <filename>

尝试:

git difftool <commitHash> <filename>
于 2011-08-16T04:10:44.767 回答
2

正如 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'

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

于 2019-10-04T14:47:27.940 回答
0

如果您只想要一个快速的线来制作git diff但不显示不同的结尾(因此^M)使用原始问题的第一条评论中的那个,它对我有用:

 git diff -b

考虑到,从长远来看,您应该正确设置行尾配置,正如所有其他答案所暗示的那样。

于 2022-02-17T18:45:40.617 回答