git/list[1] front-page[2] threads[3] people[4] search[5] about
 

bug with .gitattributes diff and embedded NUL

From
Eric Blake <ebb9@byu.net>
Date
Dec 19, 2007, 05:07 UTC
Message-ID
<4768A70F.8020904@byu.net>

The man page for gitattributes suggests that one use of the diff attribute is to force text-based diffs, even when the file contains embedded NULs. Yet actually trying this falls flat, since git generates invalid diffs when encountering embedded NUL.

Here is a pared-down example showing the bug. I based it off of what I was trying to do in the git repository for GNU m4, where I was working on adding testcases to make m4 seamlessly handle embedded NUL.

$ git --version
git version 1.5.4.rc0.67.gf9c5
$ mkdir sample
$ cd sample
$ git init
Initialized empty Git repository in .git/
$ printf 'context with\0embedded nul\nbefore\nmore context\n' > file
$ git add file
$ git commit -m initial
Created initial commit 25108f6: initial
 1 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 file
$ git tag t1
$ sed -i 's/before/after/' file
$ git add file
$ git commit -m later
Created commit a5ee10c: later
 1 files changed, 0 insertions(+), 0 deletions(-)
$ git tag t2
$ git reset --hard t1
HEAD is now at 25108f6... initial
$ sed -i 's/more/some &/' file
$ echo 'file diff' > .gitattributes
$ git add .gitattributes file
$ git commit -m 'switch file to text mode'
Created commit 0f2a9b2: switch file to text mode
 2 files changed, 2 insertions(+), 1 deletions(-)
 create mode 100644 .gitattributes
$ git tag t3
$ git reset --hard t2
HEAD is now at a5ee10c... later
$ git rebase --onto t3 t1
First, rewinding head to replay your work on top of it...
HEAD is now at 0f2a9b2... switch file to text mode
Applying later
error: patch failed: file:1
error: file: patch does not apply
Using index info to reconstruct a base tree...
error: patch failed: file:1
error: file: patch does not apply
Did you hand edit your patch?
It does not apply to blobs recorded in its index.
Cannot fall back to three-way merge.
Patch failed at 0001.

When you have resolved this problem run "git rebase --continue". If you would prefer to skip this patch, instead run "git rebase --skip". To restore the original branch and stop rebasing run "git rebase --abort".

Looking closer at .dotest/0001, the diff is indeed invalid, containing the single line

 context with-before
instead of the desired two lines
 context with^@embedded nul
-before

I'm also wondering if using GIT_EXTERNAL_DIFF would provide a way to work around this bug in git diff, since GNU diffutils doesn't seem to have any problems when doing text-mode diffs with embedded NUL:

$ diff -u -a <(git show t1:file) <(git show t2:file) | cat -v --- /dev/fd/63 2006-11-30 17:00:00.000000000 -0700 +++ /dev/fd/62 2006-11-30 17:00:00.000000000 -0700

@@ -1,3 +1,3 @@
 context with^@embedded nul
-before
+after
 more context
-- 
Don't work too hard, make some time for fun as well!

Eric Blake             ebb9@byu.net
Next: Junio C Hamano
Message 1 of 3 in “bug with .gitattributes diff and embedded NUL”
  1. Eric BlakeDec 19, 2007
  2. Junio C HamanoDec 19, 2007
  3. Eric BlakeDec 19, 2007

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.