How to “git show” a merge commit with combined diff output even when every changed file agrees with one of the parents?

After doing a “simple” merge (one without conflicts), git show usually only shows something like

commit 0e1329e551a5700614a2a34d8101e92fd9f2cad6 (HEAD, master)
Merge: fc17405 ee2de56
Author: Tilman Vogel <email@email>
Date:   Tue Feb 22 00:27:17 2011 +0100

Merge branch 'testing' into master

This is because, for merges, git show uses the combined diff format which omits files that agree with either of the parent versions.

  • How can I use github api to find most recent repositories?
  • git Undo auto merging on a specific file only not the whole branch
  • GitLab 6.9.0 - “hook declined to update refs/heads/master”
  • Can I add a username & password to git clone using the --recursive option (for submodules)?
  • When push in github, why git didn't ask me to type username and password?
  • What does HEAD point to?
  • Is there a way to force git to still show all differences in combined diff mode?

    Doing git show -m will show the differences (using pairwise diffs between the new and all parent versions respectively) but I would prefer to have that with the differnces marked by +/- in the respective columns like in combined mode.

  • How can I determine why a git merge deleted some lines of code?
  • Git merge single file without rebasing
  • In Git, how can I write the current commit hash to a file in the same commit
  • How to undo git pull from unrelated project?
  • Pushing using Git from a pc to another without using Github
  • Store custom metadata against individual files in a Git repository
  • 8 Solutions collect form web for “How to “git show” a merge commit with combined diff output even when every changed file agrees with one of the parents?”

    No, there is no way to do this. But it would certainly be nice sometimes, and it would probably be relatively easy to implement in the git source code (after all, you just have to tell it to not trim out what it thinks is extraneous output), so the patch to do so would probably be accepted by the git maintainers.

    Be careful what you wish for, though; merging a branch with a one-line change that was forked three months ago will still have a huge diff versus the mainline, and so such a full diff would be almost completely unhelpful. That’s why git doesn’t show it.

    Look at the commit message:

    commit 0e1329e551a5700614a2a34d8101e92fd9f2cad6 (HEAD, master)
    Merge: fc17405 ee2de56
    Author: Tilman Vogel <email@email>
    Date:   Tue Feb 22 00:27:17 2011 +0100
    
    Merge branch 'testing' into master
    

    notice the line:

    Merge: fc17405 ee2de56
    

    take those two commit ids and reverse them. so in order get the diff that you want, you would do:

    git diff ee2de56..fc17405
    

    to show just the names of the changed files:

    git diff --name-only ee2de56..fc17405
    

    and to extract them, you can add this to your gitconfig:

    exportfiles = !sh -c 'git diff $0 --name-only | "while read files; do mkdir -p \"$1/$(dirname $files)\"; cp -vf $files $1/$(dirname $files); done"'
    

    then use it by doing:

    git exportfiles ee2de56..fc17405 /c/temp/myproject
    

    As pointed out by Kris Nuttycombe, the by far best solution is to

    git diff fc17405...ee2de56
    

    for the merge commit

    commit 0e1329e551a5700614a2a34d8101e92fd9f2cad6 (HEAD, master)
    Merge: fc17405 ee2de56
    Author: Tilman Vogel <email@email>
    Date:   Tue Feb 22 00:27:17 2011 +0100
    

    to show all of the changes on ee2de56 that are reachable from commits on fc17405. Note the order of the commit hashes – it’s the same as shown in the merge info: Merge: fc17405 ee2de56

    Also note the 3 dots ... instead of two!

    For a list of changed files, you can use:

    git diff fc17405...ee2de56 --name-only
    

    You can create branch which HEAD will be one commit before merge. Then, you can do:

    git merge --squash testing
    

    This will merge, but not commit. Then:

    git diff
    

    I think you just need ‘git show -c $ref’. Trying this on the git repository on a8e4a59 shows a combined diff (plus/minus chars in one of 2 columns). As the git-show manual mentions, it pretty much delegates to ‘git diff-tree’ so those options look useful.

    Seems like answered here:
    http://thread.gmane.org/gmane.comp.version-control.git/191553/focus=191557

    So in a similar way, running

    $ git diff –cc $M $M^1 $M^2 $(git merge-base $M^1 $M^2)

    should show a combined patch that explains the state at $M relative to the
    states recorded in its parents and the merge base.

    in your case you just need to

    git diff HEAD^ HEAD^2
    

    or just hash for you commit:

    git diff 0e1329e55^ 0e1329e55^2
    

    I built a general-purpose approach to doing various operations on a merge’s commits.

    Step One: Add an alias to git by editing ~/.gitconfig:

    [alias]
      range = "!. ~/.githelpers && run_on_merge_range"
    

    Step Two: In ~/.githelpers, define a bash function:

    run_on_merge_range() {
      cmd=$1; shift
      commit=$1; shift
      range=$(git show $commit | grep Merge: | awk '{print $2 "..." $3}')
      echo "git $cmd $range $@"
      if [ -z $range ]; then
        echo "No merge detected"
        exit 1
      fi
      git $cmd $range $@
    }
    

    Step Three: Profit!

    git range log <merge SHA> --oneline
    git range diff <merge SHA> --reverse -p
    git range diff <merge SHA> --name-only
    

    There is probably a LOT of room for improvement here, I just whipped this together to get past an annoying situation. Feel free to mock my bash syntax and/or logic.

    Git Baby is a git and github fan, let's start git clone.