views:

1196

answers:

3

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.

How does one diff with the previous version?

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:

now I have written a 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
+4  A: 

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.

nes1983
ouch.. will I have to do this for every revision of that file?
neoneye
No, of course not, once the setting is there, it will silently convert upon commit. If everything works the way I think it does, that is …
nes1983
The problem is that I already have some files in the repository that have CRLF endings and others that doesn't. I suspect that Adobe Flash adds CRLF even though I'm using the Mac version. I need to compare against older revisions of these files. Converting line endings starting from now on does not solve the problem with older revisions :-/
neoneye
Well … you can write a script and change all the past commits :) It's not pretty, but you can re-write the history of your project. (At the risk of ruining your repo, that is)
nes1983
yeah, that is unfortunate. I actually have quite a few repositories and I have never needed to diff CRLF files before. I wish I had known about this option a long time ago. Thank you for enlighten me.
neoneye
You're not working with CRLF files here, at least not in the example you posted. That's an old-style mac file (just uses \r for EOL). That's why the diff is being shown on one line. A file using dos EOL would show each line distinctly with a trailing ^M, which you could tell get to handle via `git config core.whitespace cr-at-eol`.
jamessan
@jamessan yeah I just realized that too.. some of the files uses only CR and others LF. There are no CRLF involved. So only the CR files are causing trouble.
neoneye
If I may quote my original, unmodified answer: "Of course, this is said to convert crlf to lf, while you want to convert cr to lf. I hope this still works …"
nes1983
the git config core.whitespace cr-at-eol thing would work. and of course you can write your own commit-hook that transforms cr to lf.
nes1983
+1  A: 

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

Jakub Narębski
None of that really affects the character that identifies the newline.
nes1983
I also tried with "-w" but no luck, still treats it as a single line. Next project I must remember to never ever get any CR into the source code.
neoneye
Just remember git config --global core.autocrlf true, or bug the git folks until they make it default :)
nes1983
+4  A: 

Also see:

core.whitespace = cr-at-eol

CyberShadow