Background: I'm working on a pre-commit tool. As a developer it can be quite frustrating to pull another developer's branch and have the pre-commit hook complain loudly about files that I haven't even touched.
What I'd like to be able to do in my implementation is in a merge-commit case only run the hooks on files that were either conflicting or manually edited by me locally during the merge conflict.
What I've tried so far:
git diff --staged
- This is what the current solution does and isn't correct because it contains all of the files including the ones that merged cleanly.git diff MERGE_HEAD
- This is pretty close, but if the branch I am merging in branched from master after I did, this contains all of the changes from master that I haven't yet merged..git/MERGE_MSG
contains the list of conflicting files. This seems like a good starting point but does not contain locally edited files.git show --name-only
gets me exactly what I want. But that's too late (I'm implementing pre-commit after all :D)I believe the solution is git diff -m
. I found the doc on this very confusing, so here's my summary. Given the command git diff -m child parent1 parent2 ....
you'll see a multi-parent diff that shows how to get from each parent to the child. parent1
represented in the first column of [ +-]
and so on. The major roadblock here is that the child in your question has no referenceable name. git write-tree
comes to the rescue here; it creates a name for the currently-staged files, and prints it out.
Note that write-tree will fail if there are any unmerged files, which is probably what you want, but you'll need to make sure your system does something intelligible in that case.
$ CURRENTLY_ADDED=`git write-tree`
$ git diff -m $CURRENTLY_ADDED HEAD MERGE_HEAD
diff --cc README
index 2ef4a65,8e2e466..be3d46e
--- a/README
+++ b/README
@@@ -1,10 -1,5 +1,10 @@@
-deleted only in <theirs>
+added only in <theirs>
- deleted only in <ours>
+ added only in <ours>
--deleted during merge
++added during merge