如何在 OS X 上使用 git 将 FileMerge 作为差异工具进行管道传输?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2466821/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I pipe in FileMerge as a diff tool with git on OS X?
提问by doug
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.
我是 OS X 上的 git 新手,我通过命令行使用它。我来自 Windows 上的 Tortoise SVN 和 Beyond Compare 的世界。
I want to be able to send diffs to FileMerge.
我希望能够将差异发送到 FileMerge。
I was able to do this with TextMate simply by using:
我可以通过使用 TextMate 来做到这一点:
git diff | mate
But I'm not sure how to get that set up so I can use FileMerge instead?
但我不确定如何设置以便我可以改用 FileMerge?
回答by undees
Although it's not exactly the same as piping stdin into a script, you can do this:
尽管这与将 stdin 管道化到脚本中并不完全相同,但您可以这样做:
git difftool -t opendiff -y
That will launch FileMerge once for each file. Doing the whole project tree at once takes a little scripting.
这将为每个文件启动一次 FileMerge。一次完成整个项目树需要编写一些脚本。
See also this question.
另请参阅此问题。
回答by Syzygies
Create an executable script git-diff-cmd.sh
创建可执行脚本 git-diff-cmd.sh
#!/bin/bash
xattr -w com.apple.TextEncoding "UTF-8;134217984" ""
xattr -w com.apple.TextEncoding "UTF-8;134217984" ""
/usr/bin/opendiff "" "" -merge ""
Now edit your .gitconfig
file to include the lines
现在编辑您的.gitconfig
文件以包含这些行
[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.
...替换<path-to>
为git-diff-cmd.sh
. 现在git diff
将使用 FileMerge,并正确显示 UTF-8 Unicode 字符。
回答by millerdev
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.
这是一个脚本(最初由 Toby White 编写),我使用它来比较 FileMerge 中的整个目录结构,而不是单独打开每个文件。
#!/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
# - allow diff of subdirectory within the repo
#
# 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.
OLD=
NEW=
FILEPATH=
HAS_ARGS=no
IGNORE_TO_PATH=no
# loosely based on https://stackoverflow.com/a/14787208/10840
while [ "$#" -ge 1 ]; do
HAS_ARGS=yes
case "" in
-h)
echo "usage: #!/bin/sh
dir=$PWD
until [ -e "$dir/.git" ]; do
if [ "$dir" == "/" ]; then
echo "Not a git repository" >&2
exit 1;
fi
dir=`dirname "$dir"`
done
open -a FileMerge -n -W --args -left "$dir/" -right "" -merge ""
[--cached | <ref> [<ref>]] [-- <path>]"
exit 0
;;
--cached)
# diff staged changes
NEW=$(git write-tree)
OLD=HEAD
IGNORE_TO_PATH=yes
shift
;;
--)
shift
FILEPATH="$@"
break
;;
*)
if [[ "$IGNORE_TO_PATH" == "no" ]]; then
if [ -z "$OLD" ]; then
OLD=""
else
NEW=""
IGNORE_TO_PATH=yes
fi
fi
shift
;;
esac
done
if [ -z "$OLD" ]; then
OLD=HEAD
fi
if [[ "$HAS_ARGS" == "no" ]]; then
# diff unstaged changes
# http://stackoverflow.com/a/12010656/10840
NEW=$(git stash create)
echo "diff unstaged changes"
fi
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 $FILEPATH | (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 $FILEPATH | (cd $TMP_NEW; tar xf -)
opendiff $TMP_OLD/$FILEPATH $TMP_NEW/$FILEPATH -merge $SAVE_TO &> /dev/null &
else
TMP_NEW=$TMP_NEW/$NEW; mkdir -p $TMP_NEW
git archive --format=tar $NEW $FILEPATH | (cd $TMP_NEW; tar xf -)
opendiff $TMP_OLD/$FILEPATH $TMP_NEW/$FILEPATH &> /dev/null &
fi
Put this somewhere on your path. I prefer ~/bin/git-opendiff
, which means git opendiff ...
works as expected.
把它放在你路径上的某个地方。我更喜欢~/bin/git-opendiff
,这意味着git opendiff ...
按预期工作。
Update: diff unstaged changes when called with no arguments, added -h
(help) option.
更新:在不带参数的情况下调用时 diff 未暂存的更改,添加了-h
(帮助)选项。
Update: diff subdirectory with -- <path>
. Also better argument parsing.
更新: diff 子目录与-- <path>
. 还有更好的参数解析。