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 user‘s 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
3.保存,运行如下命令配置
# git config --global alias.diffall /PATH/diffall
时间: 2024-10-08 08:15:49