Hi.
We wrote a post-receive hook that alerts users (via email) when
specific paths are modified by their peers. The implementation is
pretty simple: whenever a new commit is made, we ask git for the full
list of files modified by that commit:
git diff --name-only <COMMIT HASH>^!
This works well for regular commits, but breaks for merge commits.
For example, suppose we have the following basic merge scenario:
B
/ \
A D
\ /
C
Root A was branched to B and C, then merged into commit D.
Problem is, the diff for D^! will include all the changes introduced by C.
One obvious solution is to simply ignore merge commits, by parsing
`git cat-file commit D` and discarding all commits with parent count >
1. But merge commits may actually contain legitimate modified files if
there were any conflict resolutions.
So what's the best solution for this problem, oh wise Git wizards?
Thanks, D.
Dun Peal [off-list ref] writes:
We wrote a post-receive hook that alerts users (via email) when
specific paths are modified by their peers. The implementation is
pretty simple: whenever a new commit is made, we ask git for the full
list of files modified by that commit:
git diff --name-only <COMMIT HASH>^!
This works well for regular commits, but breaks for merge commits.
Note that <commit>^! is *range* specifier, and 'git diff' really takes
two *endpoints*.
From git-diff(1) manpage.
For a more complete list of ways to spell <commit>, see "SPECIFYING
REVISIONS" section in gitrevisions(1). However, "diff" is about
comparing two _endpoints_, not ranges, and the range notations
("<commit>..<commit>" and "<commit>...<commit>") do not mean a
range as defined in the "SPECIFYING RANGES" section in gitrevisions(1).
<commit>^1 means include given commit but exclude all of its parents
(see gitrevisions(7)).
For a merge commit r1^! means r1 ^p1 ^p2 (where p1 and p2 are parents
of r1), which for git-diff probably means "git diff p1 r1".
For example, suppose we have the following basic merge scenario:
B
/ \
A D
\ /
C
Root A was branched to B and C, then merged into commit D.
Problem is, the diff for D^! will include all the changes introduced by C.
See above.
Try
$ git diff-tree --name-only -c <COMMIT HADH>
instead. '-c' is to show merge commit as combined diff (noting changes
different from both parents). I'm not sure if this is what you want.
There is alwats '--cc' or '-m' instead of '-c'.
--
Jakub Narebski
Poland
ShadeHawk on #git