Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Git add trailing TAB to the "+++ b/" line of the diff when the file name contains spaces?

This is more an idle curiosity question but I've just discovered that Git adds TABs to the names of files containing spaces in git-diff output. E.g.

$ git init test
$ cd test
$ echo 'test' > 'file with spaces'
$ git add .
$ git commit -m 'Add'
$ git show | grep '<literal-TAB-here>' | od -c
0000000   +   +   +       b   /   f   i   l   e       w   i   t   h    
0000020   s   p   a   c   e   s  \t  \n
0000030

Why does it do this and is there some way to prevent this from happening? Using -z option and/or setting core.quotepath = false doesn't change this behaviour.

like image 210
VZ. Avatar asked Oct 31 '25 06:10

VZ.


2 Answers

Thanks to @ElpieKay I found the answer to my own question in the commit message of this commit which says

It is because GNU patch expects to find TAB (and trailing timestamp) on ---/+++ (old_name and new_name) lines after the filenames.

This, of course, just begs the question of why does GNU patch expect to find a TAB in this case and the best answer to this I have is that it comes from patch 2.5.6 (imported in GNU patch repository in the 712cce6fdd396508038dde727f3b1d41d3bb3f61 back in 2009 but actually released in 2002, apparently) which added the following comment:

/* Allow file names with internal spaces,
   but only if a tab separates the file name from the date.
*/
like image 190
VZ. Avatar answered Nov 01 '25 23:11

VZ.


git diff and git status and git show are "porcelain", human-convenience commands with output that's been postprocessed for human consumption. I expect the tab is there as a separator for notes that turn out to be empty here.

If you want the just-the-facts-ma'am diff, use the core command, the "plumbing":

git diff-tree -p @

where -p says you want the patch, not just differing ids, and @ is there because core commands have very few defaults, you say exactly what you want and they do that. For instance, git diff notices if you're diffing a root commit and supplies an ersatz empty base tree to diff against, for your example situation, a root commit, with nothing to compare against, you actually have to supply an empty tree to compare against:

git diff-tree -p `git hash-object --stdin -t tree <&-` @

(personally I think git diff-tree should have supplied an empty parent to diff against for root commits automatically, the way git diff does, but it's waayyyyy too late to change that now, because production scripts are allowed to rely on the exact behavior of core commands).

like image 28
jthill Avatar answered Nov 02 '25 01:11

jthill