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

Re: Using Filemerge.app as a git-diff viewer

From
Jeff King <peff@peff.net>
Date
Nov 21, 2007, 14:36 UTC
Message-ID
<20071121143658.GA24108@sigill.intra.peff.net>
In-Reply-To
<47442E57.8010004@cam.ac.uk>
On Wed, Nov 21, 2007 at 01:10:47PM +0000, Toby White wrote:
> And in any case, that launches Filemerge repeatedly
> on every file separately, which makes reviewing a large diff
> time-consuming and not very helpful.

I think that particular complaint of GIT_EXTERNAL_DIFF has come up before. It probably wouldn't be too hard to support a separate environment variable to mean "diff these two trees" (or tree/cache, or cache/working tree, etc) rather than "diff these two files".

Show 9 quoted lines
> Am I misunderstanding the documentation? From man git-write-tree
>
> "Conceptually, git-write-tree sync()s the current index contents into a
>  set of tree files. In order to have that match what is actually in your
>  directory right now, you need to have done a git-update-index phase
>  before you did the git-write-tree."
>
> So git-write-tree precisely does give you the index not the working tree,
> by my reading.

What you are doing isn't _wrong_, but it is not the most efficient way of doing it, and it is a little bit awkward, I think.

There are basically three conceptual "spots" for files in git:
  - in the object database (i.e., tree objects pointing to blobs)
  - in the index (the blobs are actually in the object db)
  - in the working tree (i.e., actual files)

git-write-tree moves data from the index into the object database (git-commit is more or less git-write-tree followed by git-commit-tree). git-archive (piped to tar) moves data from the object database (because it takes a tree object name) into the working tree.

So you are basically moving data into the object db, and then out to the working tree. But there is a command that moves data directly from the index to the working tree: git-checkout-index.

Now, what you are doing is not terribly inefficient in that sense, since creating a tree object is usually pretty inexpensive. But it does involve writing to the object db for a diff, which is conceptually a read-only operation.

However, git-checkout-index also avoids piping through tar, which is likely to be faster for a large data set.

> Erm, ok, this is rapidly approaching the limit of my git knowledge,

BTW, I don't mean to nitpick your script, which obviously works for you. I'm just trying to increase your git knowledge. :)

Show 8 quoted lines
> but while I can see git-read-tree will write a tree-ish into a temp
> index,
>
> (so presumably
> git-read-tree --index-output=$TMPFILE <commit>
> ought to work. Except it doesn't, I get the error message
> fatal: unable to write new index file
> ),

Are you perhaps running against the rename(2)-ability boundaries mentioned in the man page? --index-output is relatively new, and I'm not sure of the reasons surrounding it. I think what you really want to work with a temp index is to set GIT_INDEX_FILE.

> I can't see how to make git-checkout-index read from a temp index.

It should read from GIT_INDEX_FILE. So the correct incantation for checking out a tree should be:

GIT_INDEX_FILE=$TMPFILE git-read-tree <commit> GIT_INDEX_FILE=$TMPFILE git-checkout-index -a --prefix=$TMPDIR/

and of course, for the --cached case, you can just use the existing index:

git-checkout-index -a --prefix=$TMPDIR/

(btw, I have no idea if creating a temp index is actually faster than piping through tar. I suspect it is, but haven't tested. So it may be sane to use checkout-index for the --cached case, which is what I was originally suggesting, and simply use git-archive for the tree case).

> And I'm assuming I don't want to go stomping all over the current
> index just in order to do a diff, which shouldn't change the state
> of my repository.
Correct.
> Is there a canonical way to checkout a given commit object into
> a fresh directory?

git-archive piped to tar is the canonical porcelain way (again, I was suggesting checkout-index mainly for the --cached case). The way I showed above is the "plumbing" way (and is what underlies git-checkout, for example, though of course a temp index is not needed in that case).

Hope that make sense.
-Peff
Previous: Wincent Colaiuta
Message 9 of 9 in “Using Filemerge.app as a git-diff viewer”
  1. Toby WhiteNov 21, 2007
  2. Jonathan del StrotherNov 21, 2007
  3. Jeff KingNov 21, 2007
  4. Wincent ColaiutaNov 21, 2007
  5. Jeff KingNov 21, 2007
  6. Jakub NarebskiNov 21, 2007
  7. Toby WhiteNov 21, 2007
  8. Wincent ColaiutaNov 21, 2007
  9. Jeff KingNov 21, 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.