Question

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.
  • After committing, git show --name-only gets me exactly what I want. But that's too late (I'm implementing pre-commit after all :D)
Was it helpful?

Solution 2

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

OTHER TIPS

When you git add to resolve a conflict, you erase the record of the conflict. So to preserve this information without having to reconstruct it, preserve the index file:

cp .git/index .git/preserved-merge-index

and then

GIT_INDEX_FILE=.git/preserved-merge-index git ls-files --unmerged

will show you the conflicts, and

GIT_INDEX_FILE=.git/preserved-merge-index git diff-files --name-only

will show you everything in your work tree that's changed since it was recorded in the merge index.

From comments, you also might be adding files directly in the merge. To catch those, after you've resolved all your merge conflicts you can

GIT_INDEX_FILE=.git/preserved-merge-index git diff-index --name-only `git write-tree`
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top