16

After doing a merge from the origin/base branch into my feature branch, I had to resolve one conflict on the file Parameter.java. I launched my Git merge tool and I resolved it. Once it was resolved, I performed a git commit and this opened Vim with the default merge commit message.

Thing is, this default commit message contains the list of conflicts, but starting with #, therefore they will be ignored in the commit message.

Merge remote-tracking branch 'origin/base' into feature # Conflicts: # Parameter.java # # It looks like you may be committing a merge. # If this is not correct, please remove the file # .git/MERGE_HEAD # and try again. # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # On branch feature # All conflicts fixed but you are still merging. # # Changes to be committed: # modified: Parameters.java # modified: SpecialParameters.java # modified: Traveller.java 

Is there some config to add to put these conflicts lines automatically in the commit message? Therefore removing the # on the conflicting files in the Conflicts part?

4 Answers 4

12

I found a way to do this without any hooks or scripts: Use ---cleanup scissors:

% git commit --cleanup scissors 

This results in a default commit message of:

Merge branch 'branch' # Conflicts: # baz.txt # foo.txt # ------------------------ >8 ------------------------ # Do not modify or remove the line above. # Everything below it will be ignored. # # It looks like you may be committing a merge. # If this is not correct, please remove the file # .git/MERGE_HEAD # and try again. # Please enter the commit message for your changes. Lines starting # with '#' will be kept; you may remove them yourself if you want to. # An empty message aborts the commit. # # On branch master # All conflicts fixed but you are still merging. # # Changes to be committed: # modified: bar.txt # modified: baz.txt # modified: foo.txt # 

And if you just accept this, you get the following commit message:

% git log -1 commit 64425eab687f9d4fc531da69495dcb401372104b (HEAD -> master) Merge: efd152d 474a8f4 Author: Dave Dribin <[email protected]> Date: Fri Oct 19 23:47:19 2018 -0500 Merge branch 'branch' # Conflicts: # baz.txt # foo.txt 

This doesn't remove the # prefix, but it does include the list of conflicted files. Why does this work? It will cut everything after the special "scissors" line, rather than a comment string prefix. Here's the documentation for --cleanup scissors from the git-commit(1) man page

 --cleanup=<mode> This option determines how the supplied commit message should be cleaned up before committing. The <mode> can be strip, whitespace, verbatim, scissors or default. strip Strip leading and trailing empty lines, trailing whitespace, commentary and collapse consecutive empty lines. whitespace Same as strip except #commentary is not removed. verbatim Do not change the message at all. scissors Same as whitespace except that everything from (and including) the line found below is truncated, if the message is to be edited. "#" can be customized with core.commentChar. # ------------------------ >8 ------------------------ default Same as strip if the message is to be edited. Otherwise whitespace. The default can be changed by the commit.cleanup configuration variable (see git-config(1)). 
Sign up to request clarification or add additional context in comments.

3 Comments

Unfortunately, this behaviour was changed in Git 2.22.0 (Git 2.22.0 Release Notes).
@aaron: That's unfortunate. I haven't tried Git 2.22.0 yet, but hopefully it's just a matter of moving the scissors line down?
That and deleting the next two lines (the three lines were shifted to before Conflicts), so it's kinda inconvenient but mostly still works.
11
+50

You can use the prepare-commit-msg hook to do so.

Copy .git/hooks/prepare-commit-msg.sample to .git/hooks/prepare-commit-msg

The example inside it actually adds # to the Conflicts part:

case "$2,$3" in merge,) /usr/bin/perl -i.bak -ne 's/^/# /, s/^# #/#/ if /^Conflicts/ .. /#/; print' "$1" ;; 

This hook makes sense because previous versions were doing this by default (like in Linux git version 1.7.10.4).

Now what you want to do is exactly the opposite: removing # on the Conflicts part. Indeed, the git version 2.6.2.windows.1 comments out by default the Conflicts part so you can just update the command in prepare-commit-msg with:

/usr/bin/perl -i.bak -ne 's/^#// if /^# Conflicts/ .. /^#\R/; print' "$1" ;; 

2 Comments

# This hook includes three examples. The first comments out the "Conflicts:" part of a merge commit. is written at the beginning of the file, so it does actually the opposite. Anyway, I tried renaming it as you suggested, I restarted Git bash but it still doesn't work, the conflicts part is still commented out.
For the perl, substitute sed -i.bak '/^# Conflicts:/,/^#$/ s/..//' "$1"
3

I use this which uses sed's ranges by patterns (and is based on jthill's answer)

Read in human language: In the range of lines between # Conflicts: and # or (blank line), remove preceding #(space) or # (# \?).

sed -i '/start/,/stop/ s/# \?//' 

prepare-commit-msg hook:

# prepare-commit-msg case "$2,$3" in merge,) # Uncomment Conflicts section in merge commit body sed -i '/^# Conflicts:/,/^#\?$/ s/# \?//' "$1" ;; *) ;; esac 

which results in

Conflicts: GIT-VERSION-GEN RelNotes 

Comments

-1

You don't need to add it to the commit message yourself. Once you've made a merge commit, if there were conflicts git will tell you where they were. Just run a git show --name-only [commit sha] on a commit that was a merge containing conflicts and you'll see it as part of the message.

4 Comments

Can you show example? I have tested it and it doesn't seem to work. As far as I know, once commit is done, Git does not store any information about conflicts.
You can see an example here: help.github.com/articles/…
Interesting. Maybe it is a matter of git version. I didn't see it when trying it.
Whether the results of git show on the merge commit contain enough information to see the original conflict depend on how the conflict was resolved. If the merge commit has differences from both parents in a small region then you'll see it in git show. But if, e.g., the commit was resolved by taking all from one parent then it won't show up in the git show.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.