3 # Show changes in the diff format
4 # Copyright (c) Petr Baudis, 2005
6 # Outputs a diff for converting the first tree to the second one.
7 # By default compares the current working tree to the state at the
8 # last commit. The output will automatically be displayed in a pager
9 # unless it is piped to a program.
14 # Colorize the output. You can customize the colors using the
15 # $CG_COLORS environment variable (see below).
17 # --diffcore ARGS:: Diffcore arguments to pass the Git diff command
18 # Pass the given diffcore arguments the called Git diff command.
19 # See e.g. git-diff-tree(1) documentation for the list of possible
20 # arguments; '-R', '-B', and '-C' might be of particular interest
21 # ('-M' is already passed by default).
23 # --no-renames:: Do not detect renames
24 # By default, `cg-diff` will automatically detect file renames.
25 # Diff produced by the rename-aware `cg-diff` will be unappliable
26 # using patch(1) (you need to use `cg-patch`) and the renames
27 # detection can add slight extra performance penalty. This switch
28 # will turn the rename detection off.
30 # -p:: Diff against commit parent
31 # Show diff to the parent of the current commit (or the commit
32 # specified by the -r parameter).
34 # -s:: Summarize and show diff stat
35 # Summarize the diff by showing a histogram for removed and added
36 # lines (similar to the output of diffstat(1)) and information
37 # about added and renamed files and mode changes.
39 # -r FROM_ID[..TO_ID]:: Limit to revision range
40 # Specify the revisions to diff using either '-r rev1..rev2' or
41 # '-r rev1 -r rev2'. If no revision is specified, the current
42 # working tree is implied. Note that no revision is different from
43 # empty revision which means '-r rev..' compares between 'rev' and
44 # 'HEAD', while '-r rev' compares between 'rev' and working tree.
46 # -m:: Base the diff at the merge base
47 # Base the diff at the merge base of the -r arguments (defaulting
48 # to HEAD and 'origin' or the current branch's default remote
49 # branch, see `cg-fetch` for details).
51 # ENVIRONMENT VARIABLES
52 # ---------------------
54 # The pager to display log information in, defaults to `less`.
57 # Flags to pass to the pager.
60 # Colon-separated list of 'name=color' pairs, where name is
61 # one of diffhdr, diffhdradd, diffhdrmod, diffhdrrem, diffadd,
62 # diffmod, diffrem, diffhunk, diffctx, default, and value is
63 # an ECMA-48 SGR sequence (see e.g. console_codes(4)).
66 # Even if -c was passed or specified in ~/.cgrc, if this option
67 # is set, use colors only when the output is a terminal and it
71 # This is what the $LESS environment variable value will be set
72 # to before invoking $PAGER. It defaults to $LESS concatenated
73 # with the `R` flag to allow displaying of colorized output.
75 # CONFIGURATION VARIABLES
76 # -----------------------
77 # The following GIT configuration file variables are recognized:
80 # If enabled, colorify the output like with -c if the output
85 # The ':' is equivalent to '..' in revisions range specification (to make
86 # things more comfortable to SVN users). See cogito(7) for more details
87 # about revision specification.
91 USAGE
="cg-diff [-c] [-m] [-s] [-p] [-r FROM_ID[..TO_ID]] [FILE]..."
94 .
"${COGITO_LIB}"cg-Xlib ||
exit 1
99 colorify_setup
"$colorify_diffcolors"
100 # It could've been turned on by diff.usecolor
106 if [ "$opt_color" ]; then
108 s/^diff --git.*/'$coldiffhdr'&'$coldefault'/
109 s/^+++.*/'$coldiffhdradd'&'$coldefault'/
110 s/^---.*/'$coldiffhdrrem'&'$coldefault'/
111 s/^[+].*/'$coldiffadd'&'$coldefault'/
112 s/^[-].*/'$coldiffrem'&'$coldefault'/
113 s/^new\( file\)\{0,1\} mode .*/'$coldiffadd'&'$coldefault'/
114 s/^\(deleted file\|old\) mode .*/'$coldiffrem'&'$coldefault'/
115 s/^rename to .*/'$coldiffadd'&'$coldefault'/
116 s/^rename from .*/'$coldiffrem'&'$coldefault'/
117 s/^\(@@ -.* +.* @@\)\(.*\)/'$coldiffhunk'\1'$coldiffctx'\2'$coldefault'/
126 id2
=" " # means working copy
137 elif optparse
--diffcore=; then
139 elif optparse
-p; then
140 [ "$mergebase" ] && optconflict
-m
142 elif optparse
-R || optparse
--no-renames; then
144 elif optparse
-s; then
146 elif optparse
-r=; then
147 if echo "$OPTARG" | fgrep
-q '..'; then
150 elif echo "$OPTARG" |
grep -q ':'; then
153 elif [ "$id1" = " " ]; then
155 elif [ "$id2" = " " ]; then
158 die
"too many revisions"
160 elif optparse
-m; then
161 [ "$parent" ] && optconflict
-p
169 colorify_detect
"$opt_color" diff && setup_colors
171 [ "$id1" = " " ] && id1
=HEAD
173 if [ "$parent" ]; then
174 [ "$id2" = " " ] || die
"too many revisions"
177 ids
="$(cg-object-id -p "$id2")" ||
exit 1
178 [ "$(echo "$ids" | wc -l)" -gt 1 ] && \
179 warn
"choosing the first parent of a merge commit. This may not be what you want."
180 id1
="$(echo "$ids" | head -n 1)" ||
exit 1
182 elif [ "$mergebase" ]; then
183 [ "$id2" = " " ] && { id2
="$(choose_origin refs/heads "what to
diff against?
")" ||
exit 1; }
185 id1
="$(cg-object-id -c "$id1")" ||
exit 1
186 id2
="$(cg-object-id -c "$id2")" ||
exit 1
188 conservative_merge_base
"$id1" "$id2" ||
exit 1
189 [ "$_cg_base_conservative" ] &&
190 warn
-b "multiple merge bases, picking the most conservative one"
194 id1
="$(cg-object-id -t "$id1")" ||
exit 1
198 if [ "$id2" = " " ]; then
199 [ "$_git_no_wc" ] && die
"only cg-diff between two revisions allowed outside a working copy"
201 # Make sure we only diff modified files
202 git-update-index
--refresh >/dev
/null
204 diffprog
=git-diff-index
208 id2
="$(cg-object-id -t "$id2")" ||
exit 1
209 [ "$id1" = "$id2" ] && exit 0
211 diffprog
=git-diff-tree
212 diffargs
=("$id1" "$id2")
216 diffargs
[${#diffargs[@]}]="--"
217 if [ ! "$ARGS" ]; then
218 diffargs
[${#diffargs[@]}]="${_git_relpath:-.}"
220 for file in "${ARGS[@]}"; do
221 diffargs
[${#diffargs[@]}]="$_git_relpath$file"
225 # FIXME: Update ret based on what did we match. And take "$@"
226 # to account after all.
228 $diffprog -r $renames $diffcore $style "${diffargs[@]}" | colorize | pager
229 #[ "$ret" ] && die "no files matched"