制作“git diff”忽略^M

发布于 2024-08-15 03:07:27 字数 1514 浏览 7 评论 0原文

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

比较当前和上一个时如何使用 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

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

How does one git diff when comparing the current and previous
versions of a source code file?

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

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:

I have written a Ruby script that checks out the latest 10 revisions and converts CR to 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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(13

如果没有 2024-08-22 03:07:27

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 在手册页上进行了描述

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

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

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.

无尽的现实 2024-08-22 03:07:27

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

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

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

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

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

编辑

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

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

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

git config core.whitespace cr-at-eol

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

git config --global -e

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

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

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 ^M characters no longer appear at the end of lines in git diff, git show, etc.

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.)

EDIT:

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

  • 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

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:

git config core.whitespace cr-at-eol

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

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.)

ま昔日黯然 2024-08-22 03:07:27

尝试 git diff --ignore-space-at-eol 或 git diff --ignore-space-change 或 git diff --ignore-all-空间。

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

就此别过 2024-08-22 03:07:27

另请参阅:

core.whitespace = cr-at-eol

或等效的,

[core]
    whitespace = cr-at-eol

其中 空格 前面有一个 制表符 字符。

Also see:

core.whitespace = cr-at-eol

or equivalently,

[core]
    whitespace = cr-at-eol

where whitespace is preceded by a tab character.

多情癖 2024-08-22 03:07:27

为什么你的 git diff 中会出现这些 ^M

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

显然,Windows 开发人员在安装 Git 期间没有使用“签出 Windows 风格,提交 Unix 风格行结尾”选项。

那么对此我们应该做什么呢?

您可以让 Windows 用户重新安装 git 并使用“签出 Windows 风格,提交 Unix 风格行结尾”选项。这是我更喜欢的,因为我认为 Windows 的行结束字符是一个例外,并且 Windows 通过这种方式修复了自己的问题。

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

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

    <前><代码> git rm --cached -r 。

  2. 添加.gitattributes< /a> 文件,强制某些文件使用 LF 作为行结尾。将其放入文件中:


    <前><代码> * text=auto eol=lf

  3. 再次添加所有文件。

    <前><代码> git add .

    这将显示如下消息:

     警告:<文件名> 中的 CRLF 将被 LF 替换。
     该文件将在您的工作目录中保留其原始行结尾。
    
  4. 您可以删除 .gitattributes 文件,除非您有顽固的 Windows 用户,不想使用“签出 Windows 风格,提交 Unix-样式行结尾”选项。

  5. 承诺并推动一切。

  6. 删除并签出使用这些文件的所有系统上的适用文件。在 Windows 系统上,确保它们现在使用“签出 Windows 样式,提交 Unix 样式行结尾”选项。您还应该在执行这些任务的系统上执行此操作,因为当您添加文件时 git 会说:

     该文件将在您的工作目录中保留其原始行结尾。
    

    您可以执行以下操作来删除文件:

    <前> <代码> git ls | grep“.ext$”| xargs rm -f

    然后这样做可以让它们返回正确的行结尾:

    <前> <代码> git ls | grep“.ext$”| xargs git 结账

    .ext 替换为您想要匹配的文件扩展名。

现在,您的项目仅使用 LF 字符作为行结尾,而讨厌的 CR 字符将永远不会出现:)。

另一个选项是强制执行 Windows 样式行结尾。您还可以使用 .gitattributes 文件来实现此目的。

更多信息:
https://help.github.com/articles/dealing-带行结尾/#platform-all

Why do you get these ^M in your git diff?

In my case I was working on a project which was developed in Windows and I used Linux. When I changed some code, I saw ^M at the end of the lines I added in git diff. I think the ^M were 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 CRLF line endings, and in Linux it uses LF line endings.

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

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.

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

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

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

     * text=auto eol=lf
    
  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 .gitattributes file 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
    quot; | xargs rm -f
    

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

     git ls | grep ".ext
    quot; | xargs git checkout
    

    Replacing .ext with the file extensions you want to match.

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

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

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

走过海棠暮 2024-08-22 03:07:27

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

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

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

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

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

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

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

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.

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)

diff: --ignore-cr-at-eol

A new option --ignore-cr-at-eol tells 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<->LF conversion made by your editor program.

疯到世界奔溃 2024-08-22 03:07:27

就我而言,这是这个命令的作用:

git config  core.whitespace cr-at-eol

来源:https://public-inbox.org/git/ [电子邮件受保护]/T/

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/

如果没有你 2024-08-22 03:07:27

TL;DR

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

这就是为什么

显示的那些讨厌的 ^M 是着色和寻呼机的产物。 输入图像描述这里
它是由默认的 git pager 选项 less -R 引起的。 (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

TL;DR

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

This is why

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

The first thing to note is that git diff -b will not show changes in white space (e.g. the \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:

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 -R does:

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:

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.

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

[core]
        pager = tr -d '\\r' | less -REX
与他有关 2024-08-22 03:07:27

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

不要输入:

git diff <commitHash> <filename>

尝试:

git difftool <commitHash> <filename>

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.

Instead of typing:

git diff <commitHash> <filename>

try:

git difftool <commitHash> <filename>
默嘫て 2024-08-22 03:07:27

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

 git diff -b

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

If you just want a quick line that makes the git diff but does not show the different endings (thus the ^M) use the one in the first comments to the original question, it worked for me:

 git diff -b

Take into account that, in the long run, you should get your line endings configuration right, as all other answers suggest.

红颜悴 2024-08-22 03:07:27

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

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

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).

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:

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

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

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.

旧城空念 2024-08-22 03:07:27

如果 git 补丁已经在 Windows 计算机中生成并且您正在使用它,则可以在 Linux 中使用 dos2unix 实用程序格式化该补丁。

find -name "*.patch"| xargs dos2unix

这将解决 EOL 时的 ^M 问题,并且您将能够在 Linux 计算机中 git apply patch。

If the git patch is already generated in a windows machine and you are using it you can format the patch with dos2unix utility in Linux.

find -name "*.patch"| xargs dos2unix

This will solve the ^M at EOL and you will be able to git apply patch in your linux machine.

诠释孤独 2024-08-22 03:07:27

core.autocrlf=true 设置与 --ignore-space-at-eol 参数结合起来以忽略行结束更改:

git -c "core.autocrlf=true" diff --ignore-space-at-eol

Combine the core.autocrlf=true setting with the --ignore-space-at-eol paramerer to ignore line ending changes:

git -c "core.autocrlf=true" diff --ignore-space-at-eol
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文