git添加比较和合并工具(meld)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了git添加比较和合并工具(meld)相关的知识,希望对你有一定的参考价值。

  git 下的(difftool)和(mergetool)是专门提供给使用者用自己的工具进行diff和merge的命令:

# git config --global  diff.tool  meld

# git config --global  merge.tool meld

 

然后直接使用命令进行两次提交的比较和合并:

# git difftool HEAD HEAD^1

 

缺点:

虽然使用git difftool已经基本满足了我的需要,但还有个小问题:如果我要比较两次提交之间的差异时,difftool只能一个文件一个文件的比较,每次都要提示你是否打开这个文件,然后打开meld进行比较,当你关闭meld后,才会提示下一个差异文件。这样非常浪费效率,下面一个方法直接利用meld的目录比较能力(参考: https://github.com/thenigan/git-diffall):

1.新建diffall文本文件

2.在diffall文件中添加如下代码:

技术分享
  1 #!/bin/sh
  2 # Copyright 2010 - 2012, Tim Henigan <[email protected]>
  3 #
  4 # Permission is hereby granted, free of charge, to any person obtaining
  5 # a copy of this software and associated documentation files (the
  6 # "Software"), to deal in the Software without restriction, including
  7 # without limitation the rights to use, copy, modify, merge, publish,
  8 # distribute, sublicense, and/or sell copies of the Software, and to
  9 # permit persons to whom the Software is furnished to do so, subject to
 10 # the following conditions:
 11 #
 12 # The above copyright notice and this permission notice shall be included
 13 # in all copies or substantial portions of the Software.
 14 #
 15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 16 # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 17 # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 18 # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 19 # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 20 # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 21 # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 22 
 23 
 24 # Perform a directory diff between commits in the repository using
 25 # the external diff or merge tool specified in the users config.
 26 
 27 USAGE=[--cached] [--copy-back] [-x|--extcmd=<command>] <commit>{0,2} [-- <path>*]
 28     --cached     Compare to the index rather than the working tree.
 29     --copy-back  Copy files back to the working tree when the diff
 30                  tool exits (in case they were modified by the
 31                  user).  This option is only valid if the diff
 32                  compared with the working tree.
 33     -x=<command>
 34     --extcmd=<command>  Specify a custom command for viewing diffs.
 35                  git-diffall ignores the configured defaults and
 36                  runs $command $LOCAL $REMOTE when this option is
 37                  specified. Additionally, $BASE is set in the
 38                  environment.
 39  40 
 41 SUBDIRECTORY_OK=1
 42 . "$(git --exec-path)/git-sh-setup"
 43 
 44 TOOL_MODE=diff
 45 . "$(git --exec-path)/git-mergetool--lib"
 46 
 47 merge_tool="$(get_merge_tool)"
 48 if test -z "$merge_tool"
 49 then
 50     echo "Error: Either the ‘diff.tool‘ or ‘merge.tool‘ option must be set."
 51     usage
 52 fi
 53 
 54 start_dir=$(pwd)
 55 
 56 # All the file paths returned by the diff command are relative to the root
 57 # of the working copy. So if the script is called from a subdirectory, it
 58 # must switch to the root of working copy before trying to use those paths.
 59 cdup=$(git rev-parse --show-cdup) &&
 60 cd "$cdup" || {
 61     echo >&2 "Cannot chdir to $cdup, the toplevel of the working tree"
 62     exit 1
 63 }
 64 
 65 # set up temp dir
 66 tmp=$(perl -e use File::Temp qw(tempdir);
 67     $t=tempdir("/tmp/git-diffall.XXXXX") or exit(1);
 68     print $t) || exit 1
 69 trap rm -rf "$tmp" EXIT
 70 
 71 left=
 72 right=
 73 paths=
 74 dashdash_seen=
 75 compare_staged=
 76 merge_base=
 77 left_dir=
 78 right_dir=
 79 diff_tool=
 80 copy_back=
 81 
 82 while test $# != 0
 83 do
 84     case "$1" in
 85     -h|--h|--he|--hel|--help)
 86         usage
 87         ;;
 88     --cached)
 89         compare_staged=1
 90         ;;
 91     --copy-back)
 92         copy_back=1
 93         ;;
 94     -x|--e|--ex|--ext|--extc|--extcm|--extcmd)
 95         if test $# = 1
 96         then
 97             echo You must specify the tool for use with --extcmd
 98             usage
 99         else
100             diff_tool=$2
101             shift
102         fi
103         ;;
104     --)
105         dashdash_seen=1
106         ;;
107     -*)
108         echo Invalid option: "$1"
109         usage
110         ;;
111     *)
112         # could be commit, commit range or path limiter
113         case "$1" in
114         *...*)
115             left=${1%...*}
116             right=${1#*...}
117             merge_base=1
118             ;;
119         *..*)
120             left=${1%..*}
121             right=${1#*..}
122             ;;
123         *)
124             if test -n "$dashdash_seen"
125             then
126                 paths="$paths$1 "
127             elif test -z "$left"
128             then
129                 left=$1
130             elif test -z "$right"
131             then
132                 right=$1
133             else
134                 paths="$paths$1 "
135             fi
136             ;;
137         esac
138         ;;
139     esac
140     shift
141 done
142 
143 # Determine the set of files which changed
144 if test -n "$left" && test -n "$right"
145 then
146     left_dir="cmt-$(git rev-parse --short $left)"
147     right_dir="cmt-$(git rev-parse --short $right)"
148 
149     if test -n "$compare_staged"
150     then
151         usage
152     elif test -n "$merge_base"
153     then
154         git diff --name-only "$left"..."$right" -- $paths >"$tmp/filelist"
155     else
156         git diff --name-only "$left" "$right" -- $paths >"$tmp/filelist"
157     fi
158 elif test -n "$left"
159 then
160     left_dir="cmt-$(git rev-parse --short $left)"
161 
162     if test -n "$compare_staged"
163     then
164         right_dir="staged"
165         git diff --name-only --cached "$left" -- $paths >"$tmp/filelist"
166     else
167         right_dir="working_tree"
168         git diff --name-only "$left" -- $paths >"$tmp/filelist"
169     fi
170 else
171     left_dir="HEAD"
172 
173     if test -n "$compare_staged"
174     then
175         right_dir="staged"
176         git diff --name-only --cached -- $paths >"$tmp/filelist"
177     else
178         right_dir="working_tree"
179         git diff --name-only -- $paths >"$tmp/filelist"
180     fi
181 fi
182 
183 # Exit immediately if there are no diffs
184 if test ! -s "$tmp/filelist"
185 then
186     exit 0
187 fi
188 
189 if test -n "$copy_back" && test "$right_dir" != "working_tree"
190 then
191     echo "--copy-back is only valid when diff includes the working tree."
192     exit 1
193 fi
194 
195 # Create the named tmp directories that will hold the files to be compared
196 mkdir -p "$tmp/$left_dir" "$tmp/$right_dir"
197 
198 # Populate the tmp/right_dir directory with the files to be compared
199 while read name
200 do
201     if test -n "$right"
202     then
203         ls_list=$(git ls-tree $right "$name")
204         if test -n "$ls_list"
205         then
206             mkdir -p "$tmp/$right_dir/$(dirname "$name")"
207             git show "$right":"$name" >"$tmp/$right_dir/$name" || true
208         fi
209     elif test -n "$compare_staged"
210     then
211         ls_list=$(git ls-files -- "$name")
212         if test -n "$ls_list"
213         then
214             mkdir -p "$tmp/$right_dir/$(dirname "$name")"
215             git show :"$name" >"$tmp/$right_dir/$name"
216         fi
217     else
218         if test -e "$name"
219         then
220             mkdir -p "$tmp/$right_dir/$(dirname "$name")"
221             cp "$name" "$tmp/$right_dir/$name"
222         fi
223     fi
224 done < "$tmp/filelist"
225 
226 # Populate the tmp/left_dir directory with the files to be compared
227 while read name
228 do
229     if test -n "$left"
230     then
231         ls_list=$(git ls-tree $left "$name")
232         if test -n "$ls_list"
233         then
234             mkdir -p "$tmp/$left_dir/$(dirname "$name")"
235             git show "$left":"$name" >"$tmp/$left_dir/$name" || true
236         fi
237     else
238         if test -n "$compare_staged"
239         then
240             ls_list=$(git ls-tree HEAD "$name")
241             if test -n "$ls_list"
242             then
243                 mkdir -p "$tmp/$left_dir/$(dirname "$name")"
244                 git show HEAD:"$name" >"$tmp/$left_dir/$name"
245             fi
246         else
247             mkdir -p "$tmp/$left_dir/$(dirname "$name")"
248             git show :"$name" >"$tmp/$left_dir/$name"
249         fi
250     fi
251 done < "$tmp/filelist"
252 
253 LOCAL="$tmp/$left_dir"
254 REMOTE="$tmp/$right_dir"
255 
256 if test -n "$diff_tool"
257 then
258     export BASE
259     eval $diff_tool "$LOCAL" "$REMOTE"
260 else
261     run_merge_tool "$merge_tool" false
262 fi
263 
264 # Copy files back to the working dir, if requested
265 if test -n "$copy_back" && test "$right_dir" = "working_tree"
266 then
267     cd "$start_dir"
268     git_top_dir=$(git rev-parse --show-toplevel)
269     find "$tmp/$right_dir" -type f |
270     while read file
271     do
272         cp "$file" "$git_top_dir/${file#$tmp/$right_dir/}"
273     done
274 fi
View Code

3.保存,运行如下命令配置

# git config --global alias.diffall /PATH/diffall

 

以上是关于git添加比较和合并工具(meld)的主要内容,如果未能解决你的问题,请参考以下文章

在 Windows 上使用 Meld 的 Git 合并工具

使用 git 和 meld 进行交互式变基的 3 路合并中的三个文件是啥?

分享一款小巧好用的代码对比工具

分享一款小巧好用的代码对比工具

了解与 Git 合并的 Meld 3 方式 [重复]

git,用工具合并,而不是用工具解析