How do I pipe in FileMerge as a diff tool with git on OS X?
I want to be able to send diffs to FileMerge.
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?
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
#!/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
<path-to> by the path to
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.