Question

I'm doing some directory-level reorganization in my repository. The resulting commits show a lot of file-level renames, which obscures the fact that conceptually all I've done is one or two git mv dir1/ dir2/ commands.

Is there a way to make git log summarize this sort of operation to show that, conceptually, an entire directory was moved? I thought that --dirstat or --summarize would get me at least close, but they don't seem to do what I want.

(I understand that git's repository model does not track any information about directories, only files. However, the same is true of file renames, yet it's able to derive information about file-level renames after the fact.)

Here's a simple example:

#setup
git init
mkdir dir1
for f in foo bar baz; do echo $f > dir1/$f; done
git add dir1
git commit -m 'dir1'

#do the directory move
git mv dir1 dir2
git commit -m 'rename dir1 to dir2'

At this point I'd like to see something like this:

$ git log -1 --what-options-go-here?
b0ba9c9 rename dir1 to dir2
0       0       {dir1 => dir2}/

Instead, I can only seem to produce things like this:

$ git log -1 --numstat --oneline
b0ba9c9 rename dir1 to dir2
0       0       {dir1 => dir2}/bar
0       0       {dir1 => dir2}/baz
0       0       {dir1 => dir2}/foo
Était-ce utile?

La solution

Git dynamically computes the file renames (using a "similarity index", see diff -M option; also -B and -C). If, given commits c1 and c2, the path path1 has disappeared from c1 and path2 has appeared in c2, that's a "rename candidate". If the file contents of path2 are sufficiently similar to those of path1, the file must have been renamed (and possibly modified as well, if -M is less than 100%).

To decide that a rename was a "directory rename" you'd need to add code of the form:

  • every file in dir1 disappeared (including untracked and ignored files)
  • no file appeared in dir2 before (including untracked and ignored files)
  • given the dynamically-detected renames, "enough" files with name dir1 were renamed so that dir1 became dir2 in the path, while the rest of the name remained the same

to decide that dir1 was renamed to dir2. (The "enough" in the last point allows a few files to have been renamed outside of the new dir2.)

The really sticky point here is the two parenthentical bits, "including untracked and ignored files". Clearly git can't tell you about the history of such files. (One could of course just assume that no such files exist, perhaps under control of an option flag.) I'm not sure if this was a factor in deciding not to write that bit of algorithm; but as far as I know, it's not in there.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top