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

Re: What's the difference between `git show branch:file | diff -u - file` vs `git diff branch file`?

From
Nguyen Thai Ngoc Duy <pclouds@gmail.com>
Date
Aug 29, 2011, 16:09 UTC
Message-ID
<CACsJy8Dar5i3Fn+rhOq78vdsqRL4D+RNUc5G64BM-6DvKC=L5w@mail.gmail.com>
In-Reply-To
<loom.20110829T155805-331@post.gmane.org>
On Mon, Aug 29, 2011 at 9:48 PM, Marat Radchenko <marat@slonopotamus.org> wrote:
Show 6 quoted lines
> Nguyen Thai Ngoc Duy <pclouds <at> gmail.com> writes:
>>  - is "file" above at top repo, or is it actually very/deep/path/to/a/file?
> 3 levels deep. Most parent dir (one after repo root) contains 20k files.
>
>>  - how many entries in the tree that contain "file"?
> Sorry, didn't understand this.

You have already answered it. I was asking the size of parent dir, but phrased poorly.

Show 17 quoted lines
>>  - how is "git ls-files | wc -l"?
> $ time git ls-files | wc -l
> 603137
>
> real    0m0.417s
> user    0m0.440s
> sys     0m0.060s
>
>>  - how about "time git diff branch another-branch -- file >/dev/null"?
>> That'd remove unpack-trees code.
> Pretty fast:
>
> git diff HEAD branch -- file > /dev/null
>
> real    0m0.276s
> user    0m0.240s
> sys     0m0.030s

That may explain it. "git diff <ref>" walks through the index, unpacks tree objects along the way, matches up entries with the same path from the branch, the index then feeds matching entries to diff function. If tree cutting is not done efficiently, it could very well walk through every entry in the index (~600k entries in your case), unpacking all tree objects along the way.

And it looks like to me that diff_cache() in diff-lib.c, responsible for this case, does not do any prefix trimming. traverse_trees() also does not seem to do "never_interesting" optimization like in tree_interesting(), so if the traversed tree is big (~20k as you told me), it will take some time, even though you are only interested in a single entry.

> So the only troubled variant is `git diff branch -- file`.

No, I suspect "git diff --cached" would be also slow. "git merge" would be definitely slow. But we can hardly improve these cases because the commands are usually called tree-wide, no path limiting.

If you only work on a small subset of files, there's some (unfinished) code in narrow clone implementation that cuts down index size, which may speed up in big-index repositories like yours. Could be a good reason for me (or someone) to extract that part and get it in before full narrow clone is implemented.

-- 
Duy
Previous: Marat RadchenkoNext: Junio C Hamano
Message 15 of 56 in “What's the difference between `git show branch:file | diff -u - file` vs `git diff branch file`?”
  1. Marat RadchenkoAug 23, 2011
  2. Michael J GruberAug 23, 2011
  3. Marat RadchenkoAug 23, 2011
  4. Michael WittenAug 23, 2011
  5. Michael J GruberAug 23, 2011
  6. Marat RadchenkoAug 23, 2011
  7. Junio C HamanoAug 23, 2011
  8. Marat RadchenkoAug 23, 2011
  9. Michael J GruberAug 23, 2011
  10. Marat RadchenkoAug 25, 2011
  11. Junio C HamanoAug 25, 2011
  12. Marat RadchenkoAug 26, 2011
  13. Nguyen Thai Ngoc DuyAug 29, 2011
  14. Marat RadchenkoAug 29, 2011
  15. Nguyen Thai Ngoc DuyAug 29, 2011
  16. Junio C HamanoAug 29, 2011
  17. Junio C HamanoAug 29, 2011
  18. Junio C HamanoAug 29, 2011
  19. Junio C HamanoAug 29, 2011
  20. 0/3 Un-pessimize "diff-index $commit -- $pathspec"Junio C Hamano, Aug 29, 2011
  21. 1/3 traverse_trees(): allow pruning with pathspecJunio C Hamano, Aug 29, 2011
  22. Nguyen Thai Ngoc DuyAug 30, 2011
  23. Junio C HamanoAug 30, 2011
  24. Nguyen Thai Ngoc DuyAug 31, 2011
  25. Michael HaggertyOct 9, 2011
  26. Nguyen Thai Ngoc DuyOct 9, 2011
  27. Michael HaggertyOct 10, 2011
  28. 2/3 unpack-trees: allow pruning with pathspecJunio C Hamano, Aug 29, 2011
  29. Nguyen Thai Ngoc DuyAug 30, 2011
  30. Junio C HamanoAug 30, 2011
  31. David Michael BarrAug 30, 2011
  32. 3/3 diff-index: pass pathspec down to unpack-trees machineryJunio C Hamano, Aug 29, 2011
  33. Jonathan NiederJan 11, 2012
  34. Junio C HamanoJan 11, 2012
  35. Nguyen Thai Ngoc DuyJan 11, 2012
  36. Nguyen Thai Ngoc DuyJan 11, 2012
  37. Junio C HamanoJan 11, 2012
  38. tree_entry_interesting: make recursive mode defaultNguyễn Thái Ngọc Duy, Jan 12, 2012
  39. Junio C HamanoJan 12, 2012
  40. Nguyen Thai Ngoc DuyJan 12, 2012
  41. 1/2 Document limited recursion pathspec matching with wildcardsNguyễn Thái Ngọc Duy, Jan 14, 2012
  42. 2/2 tree_entry_interesting: make recursive mode defaultNguyễn Thái Ngọc Duy, Jan 14, 2012
  43. Junio C HamanoJan 15, 2012
  44. Nguyen Thai Ngoc DuyJan 15, 2012
  45. Junio C HamanoJan 16, 2012
  46. Nguyen Thai Ngoc DuyJan 18, 2012
  47. Junio C HamanoJan 15, 2012
  48. Nguyen Thai Ngoc DuyJan 15, 2012
  49. Linus TorvaldsAug 29, 2011
  50. Junio C HamanoAug 29, 2011
  51. Linus TorvaldsAug 29, 2011
  52. Junio C HamanoAug 29, 2011
  53. Marat RadchenkoAug 30, 2011
  54. Junio C HamanoAug 31, 2011
  55. Michael J GruberAug 30, 2011
  56. Junio C HamanoAug 30, 2011

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.