On Mon, Nov 26, 2012 at 12:23 PM, Matt McClure <matthewlmcclure@xxxxxxxxx> wrote: > I'm finding the behavior of `git difftool -d` surprising. It seems that it > only uses symlinks to the working copy for files that are modified in the > working copy since the most recent commit. I would have expected it to use > symlinks for all files whose version under comparison is the working copy > version, regardless of whether the working copy differs from the HEAD. > > I'm using > > $ git --version > git version 1.8.0 > > on a Mac from Homebrew. cc:ing Tim since he probably remembers this feature. This is a side-effect of how it's currently implemented, and the general-purpose nature of the "diff" command. diff can also be used for diffing arbitrary commits. The simplest way to implement that is to create two temporary directories containing "a/" and "b/" and then launch the tool against them. That's what difftool does; it creates a temporary index and uses `git checkout-index` to populate these two dirs. The worktree handling is a bolt-on that symlinks (or copies (on windows or with --no-symlinks)) modified worktree files into one of these temporary directories. When symlinks are used (the default) we avoid needing to copy these files back into the worktree; we can blindly remove the temporary directories without checking whether the tool edited any files. When copies are used we check their content for changes before deciding to copy them back into the worktree. Files that are not modified are not considered part of the set of files to check when copying back, or when symlinking, mostly because that's just how it's implemented right now. It seems that there is an edge case here that we are not accounting for: unmodified worktree paths, when checked out into the temporary directory, can be edited by the tool when comparing against older commits. These edits will be lost. If we had a way to know that either a/ or b/ can be replaced with the worktree itself then we could make it even simpler. Right now we don't because difftool barely parses the command-line at all; most of it is parsed by git-diff. Originally, difftool was a read-only tool so it was able to avoid needing to know too much about what diff is really doing. We would need to a way to re-use git's diff command-line parsing logic to answer: "is the worktree involved in this diff invocation?" When we can do that then we avoid needing to have a temporary directory altogether for any dir-diffs that involve the worktree. Does anyone know of a good way to answer that question? The input is the command-line provided to diff/difftool. The output is one of ('a', 'b', 'x'), where 'a' means the left side of the diff is the worktree, 'b' means the right side, and 'x' means neither (e.g. the command-line contains two refs). Assuming we can do this, it would also make dir-diff faster since we can avoid needing to checkout the entire tree for that side of the diff. -- David -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html