How do I pipe in FileMerge as a diff tool with git on OS X?

I’m new to git on OS X, and I’m using it via the command line. I come from the world of Tortoise SVN and Beyond Compare on Windows.

I want to be able to send diffs to FileMerge.

  • Difficulty in getting GitBook site to show up in GitHub page
  • Start/Stop and Restart Jenkins service on Windows
  • Interactively merge files tracked with git and untracked local files
  • How to list SVN tags and its revisions from command line
  • Using diffstat with subversion?
  • Git says “Warning: Permanently added to the list of known hosts”
  • I was able to do this with TextMate simply by using:

    git diff | mate
    

    But I’m not sure how to get that set up so I can use FileMerge instead?

  • Any way to guarantee that a git user doesn't use fake account info when commiting and pushing?
  • gitosis + git error: fatal: '/home/git/repositories/idea-generator.git' does not appear to be a git repository
  • how can I customize git's merge commit message?
  • Keep stash after git filter-branch --subdirectory-filter
  • How to manage multiple user configs in Git?
  • git: setting a single tracking remote from a public repo
  • 3 Solutions collect form web for “How do I pipe in FileMerge as a diff tool with git on OS X?”

    Although it’s not exactly the same as piping stdin into a script, you can do this:

    git difftool -t opendiff -y
    

    That will launch FileMerge once for each file. Doing the whole project tree at once takes a little scripting.

    See also this question.

    Create an executable script git-diff-cmd.sh

    #!/bin/bash
    
    xattr -w com.apple.TextEncoding "UTF-8;134217984" "$2"
    xattr -w com.apple.TextEncoding "UTF-8;134217984" "$5"
    
    /usr/bin/opendiff "$2" "$5" -merge "$1"
    

    Now edit your .gitconfig file to include the lines

    [diff]
        external = <path-to>/git-diff-cmd.sh
    

    …replacing <path-to> by the path to git-diff-cmd.sh.
    Now git diff will use FileMerge, and correctly display UTF-8 Unicode characters.

    Here’s a script (originally by Toby White) that I hacked up to compare the entire directory structure in FileMerge rather than opening each file individually.

    #!/bin/sh
    #
    # This script was written by Toby White under an unknown license, and published
    # on the Git mailing list:
    #
    #   http://kerneltrap.org/mailarchive/git/2007/11/21/435536
    #
    # Superficial changes were made by Nathan de Vries to allow the script to be
    # run under Leopard.
    #
    # Adapted by Daniel Miller : http://stackoverflow.com/a/12957945/10840
    # - allow changes to be saved back to the working copy when diffing against HEAD
    # - work when FileMerge is already open
    # - always compare archived copies so ignored files are excluded from the diff
    # - allow diff of unstaged changes (no arguments); creates a dangling commit
    #
    # Known issues:
    # - Always uses the same two directories (/tmp/git-opendiff-old and
    #   /tmp/git-opendiff-new); THEY WILL BE DELETED IF THEY ALREADY EXIST.
    #   Ugly, I know, but it makes the script work even if FileMerge is open.
    # - Does not show unstaged changes.
    
    if test "$1" = -h; then
        echo "usage: $0 [--cached | <ref>] [<ref>]"
        exit
    elif test $# = 0; then
        # diff unstaged changes
        # http://stackoverflow.com/a/12010656/10840
        NEW=$(git stash create)
        OLD=HEAD
    elif test "$1" = --cached; then
        # diff staged changes
        OLD=HEAD
        NEW=`git write-tree`
        shift
    fi
    if test $# -gt 0; then
        OLD="$1"; shift
    fi
    test $# -gt 0 && test -z "$CACHED" && NEW="$1"
    
    TMP_OLD=/tmp/git-opendiff-old
    TMP_NEW=/tmp/git-opendiff-new
    test -d $TMP_OLD && rm -rf $TMP_OLD; mkdir $TMP_OLD
    test -d $TMP_NEW && rm -rf $TMP_NEW; mkdir $TMP_NEW
    
    TMP_OLD=$TMP_OLD/$OLD; mkdir -p $TMP_OLD
    git archive --format=tar $OLD | (cd $TMP_OLD; tar xf -)
    
    if test -z "$NEW"; then
        SAVE_TO=$(git rev-parse --show-cdup)
        test -z "$cdup" && SAVE_TO=.
        git archive --format=tar HEAD | (cd $TMP_NEW; tar xf -)
        opendiff $TMP_OLD $TMP_NEW -merge $SAVE_TO
    else
        TMP_NEW=$TMP_NEW/$NEW; mkdir -p $TMP_NEW
        git archive --format=tar $NEW | (cd $TMP_NEW; tar xf -)
        opendiff $TMP_OLD $TMP_NEW
    fi
    

    Put this somewhere on your path. I prefer ~/bin/git-opendiff, which means git opendiff ... works as expected.

    Update: diff unstaged changes when called with no arguments, added -h (help) option.

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