Merge branch 'tb/log-G-binary'
[git] / git-stash.sh
1 #!/bin/sh
2 # Copyright (c) 2007, Nanako Shiraishi
3
4 dashless=$(basename "$0" | sed -e 's/-/ /')
5 USAGE="list [<options>]
6    or: $dashless show [<stash>]
7    or: $dashless drop [-q|--quiet] [<stash>]
8    or: $dashless ( pop | apply ) [--index] [-q|--quiet] [<stash>]
9    or: $dashless branch <branchname> [<stash>]
10    or: $dashless save [--patch] [-k|--[no-]keep-index] [-q|--quiet]
11                       [-u|--include-untracked] [-a|--all] [<message>]
12    or: $dashless [push [--patch] [-k|--[no-]keep-index] [-q|--quiet]
13                        [-u|--include-untracked] [-a|--all] [-m <message>]
14                        [-- <pathspec>...]]
15    or: $dashless clear"
16
17 SUBDIRECTORY_OK=Yes
18 OPTIONS_SPEC=
19 START_DIR=$(pwd)
20 . git-sh-setup
21 require_work_tree
22 prefix=$(git rev-parse --show-prefix) || exit 1
23 cd_to_toplevel
24
25 TMP="$GIT_DIR/.git-stash.$$"
26 TMPindex=${GIT_INDEX_FILE-"$(git rev-parse --git-path index)"}.stash.$$
27 trap 'rm -f "$TMP-"* "$TMPindex"' 0
28
29 ref_stash=refs/stash
30
31 if git config --get-colorbool color.interactive; then
32        help_color="$(git config --get-color color.interactive.help 'red bold')"
33        reset_color="$(git config --get-color '' reset)"
34 else
35        help_color=
36        reset_color=
37 fi
38
39 no_changes () {
40         git diff-index --quiet --cached HEAD --ignore-submodules -- "$@" &&
41         git diff-files --quiet --ignore-submodules -- "$@" &&
42         (test -z "$untracked" || test -z "$(untracked_files "$@")")
43 }
44
45 untracked_files () {
46         if test "$1" = "-z"
47         then
48                 shift
49                 z=-z
50         else
51                 z=
52         fi
53         excl_opt=--exclude-standard
54         test "$untracked" = "all" && excl_opt=
55         git ls-files -o $z $excl_opt -- "$@"
56 }
57
58 prepare_fallback_ident () {
59         if ! git -c user.useconfigonly=yes var GIT_COMMITTER_IDENT >/dev/null 2>&1
60         then
61                 GIT_AUTHOR_NAME="git stash"
62                 GIT_AUTHOR_EMAIL=git@stash
63                 GIT_COMMITTER_NAME="git stash"
64                 GIT_COMMITTER_EMAIL=git@stash
65                 export GIT_AUTHOR_NAME
66                 export GIT_AUTHOR_EMAIL
67                 export GIT_COMMITTER_NAME
68                 export GIT_COMMITTER_EMAIL
69         fi
70 }
71
72 clear_stash () {
73         if test $# != 0
74         then
75                 die "$(gettext "git stash clear with parameters is unimplemented")"
76         fi
77         if current=$(git rev-parse --verify --quiet $ref_stash)
78         then
79                 git update-ref -d $ref_stash $current
80         fi
81 }
82
83 create_stash () {
84
85         prepare_fallback_ident
86
87         stash_msg=
88         untracked=
89         while test $# != 0
90         do
91                 case "$1" in
92                 -m|--message)
93                         shift
94                         stash_msg=${1?"BUG: create_stash () -m requires an argument"}
95                         ;;
96                 -m*)
97                         stash_msg=${1#-m}
98                         ;;
99                 --message=*)
100                         stash_msg=${1#--message=}
101                         ;;
102                 -u|--include-untracked)
103                         shift
104                         untracked=${1?"BUG: create_stash () -u requires an argument"}
105                         ;;
106                 --)
107                         shift
108                         break
109                         ;;
110                 esac
111                 shift
112         done
113
114         git update-index -q --refresh
115         if no_changes "$@"
116         then
117                 exit 0
118         fi
119
120         # state of the base commit
121         if b_commit=$(git rev-parse --verify HEAD)
122         then
123                 head=$(git rev-list --oneline -n 1 HEAD --)
124         else
125                 die "$(gettext "You do not have the initial commit yet")"
126         fi
127
128         if branch=$(git symbolic-ref -q HEAD)
129         then
130                 branch=${branch#refs/heads/}
131         else
132                 branch='(no branch)'
133         fi
134         msg=$(printf '%s: %s' "$branch" "$head")
135
136         # state of the index
137         i_tree=$(git write-tree) &&
138         i_commit=$(printf 'index on %s\n' "$msg" |
139                 git commit-tree $i_tree -p $b_commit) ||
140                 die "$(gettext "Cannot save the current index state")"
141
142         if test -n "$untracked"
143         then
144                 # Untracked files are stored by themselves in a parentless commit, for
145                 # ease of unpacking later.
146                 u_commit=$(
147                         untracked_files -z "$@" | (
148                                 GIT_INDEX_FILE="$TMPindex" &&
149                                 export GIT_INDEX_FILE &&
150                                 rm -f "$TMPindex" &&
151                                 git update-index -z --add --remove --stdin &&
152                                 u_tree=$(git write-tree) &&
153                                 printf 'untracked files on %s\n' "$msg" | git commit-tree $u_tree  &&
154                                 rm -f "$TMPindex"
155                 ) ) || die "$(gettext "Cannot save the untracked files")"
156
157                 untracked_commit_option="-p $u_commit";
158         else
159                 untracked_commit_option=
160         fi
161
162         if test -z "$patch_mode"
163         then
164
165                 # state of the working tree
166                 w_tree=$( (
167                         git read-tree --index-output="$TMPindex" -m $i_tree &&
168                         GIT_INDEX_FILE="$TMPindex" &&
169                         export GIT_INDEX_FILE &&
170                         git diff-index --name-only -z HEAD -- "$@" >"$TMP-stagenames" &&
171                         git update-index -z --add --remove --stdin <"$TMP-stagenames" &&
172                         git write-tree &&
173                         rm -f "$TMPindex"
174                 ) ) ||
175                         die "$(gettext "Cannot save the current worktree state")"
176
177         else
178
179                 rm -f "$TMP-index" &&
180                 GIT_INDEX_FILE="$TMP-index" git read-tree HEAD &&
181
182                 # find out what the user wants
183                 GIT_INDEX_FILE="$TMP-index" \
184                         git add--interactive --patch=stash -- "$@" &&
185
186                 # state of the working tree
187                 w_tree=$(GIT_INDEX_FILE="$TMP-index" git write-tree) ||
188                 die "$(gettext "Cannot save the current worktree state")"
189
190                 git diff-tree -p HEAD $w_tree -- >"$TMP-patch" &&
191                 test -s "$TMP-patch" ||
192                 die "$(gettext "No changes selected")"
193
194                 rm -f "$TMP-index" ||
195                 die "$(gettext "Cannot remove temporary index (can't happen)")"
196
197         fi
198
199         # create the stash
200         if test -z "$stash_msg"
201         then
202                 stash_msg=$(printf 'WIP on %s' "$msg")
203         else
204                 stash_msg=$(printf 'On %s: %s' "$branch" "$stash_msg")
205         fi
206         w_commit=$(printf '%s\n' "$stash_msg" |
207         git commit-tree $w_tree -p $b_commit -p $i_commit $untracked_commit_option) ||
208         die "$(gettext "Cannot record working tree state")"
209 }
210
211 store_stash () {
212         while test $# != 0
213         do
214                 case "$1" in
215                 -m|--message)
216                         shift
217                         stash_msg="$1"
218                         ;;
219                 -m*)
220                         stash_msg=${1#-m}
221                         ;;
222                 --message=*)
223                         stash_msg=${1#--message=}
224                         ;;
225                 -q|--quiet)
226                         quiet=t
227                         ;;
228                 *)
229                         break
230                         ;;
231                 esac
232                 shift
233         done
234         test $# = 1 ||
235         die "$(eval_gettext "\"$dashless store\" requires one <commit> argument")"
236
237         w_commit="$1"
238         if test -z "$stash_msg"
239         then
240                 stash_msg="Created via \"git stash store\"."
241         fi
242
243         git update-ref --create-reflog -m "$stash_msg" $ref_stash $w_commit
244         ret=$?
245         test $ret != 0 && test -z "$quiet" &&
246         die "$(eval_gettext "Cannot update \$ref_stash with \$w_commit")"
247         return $ret
248 }
249
250 push_stash () {
251         keep_index=
252         patch_mode=
253         untracked=
254         stash_msg=
255         while test $# != 0
256         do
257                 case "$1" in
258                 -k|--keep-index)
259                         keep_index=t
260                         ;;
261                 --no-keep-index)
262                         keep_index=n
263                         ;;
264                 -p|--patch)
265                         patch_mode=t
266                         # only default to keep if we don't already have an override
267                         test -z "$keep_index" && keep_index=t
268                         ;;
269                 -q|--quiet)
270                         GIT_QUIET=t
271                         ;;
272                 -u|--include-untracked)
273                         untracked=untracked
274                         ;;
275                 -a|--all)
276                         untracked=all
277                         ;;
278                 -m|--message)
279                         shift
280                         test -z ${1+x} && usage
281                         stash_msg=$1
282                         ;;
283                 -m*)
284                         stash_msg=${1#-m}
285                         ;;
286                 --message=*)
287                         stash_msg=${1#--message=}
288                         ;;
289                 --help)
290                         show_help
291                         ;;
292                 --)
293                         shift
294                         break
295                         ;;
296                 -*)
297                         option="$1"
298                         eval_gettextln "error: unknown option for 'stash push': \$option"
299                         usage
300                         ;;
301                 *)
302                         break
303                         ;;
304                 esac
305                 shift
306         done
307
308         eval "set $(git rev-parse --sq --prefix "$prefix" -- "$@")"
309
310         if test -n "$patch_mode" && test -n "$untracked"
311         then
312                 die "$(gettext "Can't use --patch and --include-untracked or --all at the same time")"
313         fi
314
315         test -n "$untracked" || git ls-files --error-unmatch -- "$@" >/dev/null || exit 1
316
317         git update-index -q --refresh
318         if no_changes "$@"
319         then
320                 say "$(gettext "No local changes to save")"
321                 exit 0
322         fi
323
324         git reflog exists $ref_stash ||
325                 clear_stash || die "$(gettext "Cannot initialize stash")"
326
327         create_stash -m "$stash_msg" -u "$untracked" -- "$@"
328         store_stash -m "$stash_msg" -q $w_commit ||
329         die "$(gettext "Cannot save the current status")"
330         say "$(eval_gettext "Saved working directory and index state \$stash_msg")"
331
332         if test -z "$patch_mode"
333         then
334                 test "$untracked" = "all" && CLEAN_X_OPTION=-x || CLEAN_X_OPTION=
335                 if test -n "$untracked" && test $# = 0
336                 then
337                         git clean --force --quiet -d $CLEAN_X_OPTION
338                 fi
339
340                 if test $# != 0
341                 then
342                         test -z "$untracked" && UPDATE_OPTION="-u" || UPDATE_OPTION=
343                         test "$untracked" = "all" && FORCE_OPTION="--force" || FORCE_OPTION=
344                         git add $UPDATE_OPTION $FORCE_OPTION -- "$@"
345                         git diff-index -p --cached --binary HEAD -- "$@" |
346                         git apply --index -R
347                 else
348                         git reset --hard -q
349                 fi
350
351                 if test "$keep_index" = "t" && test -n "$i_tree"
352                 then
353                         git read-tree --reset $i_tree
354                         git ls-files -z --modified -- "$@" |
355                         git checkout-index -z --force --stdin
356                 fi
357         else
358                 git apply -R < "$TMP-patch" ||
359                 die "$(gettext "Cannot remove worktree changes")"
360
361                 if test "$keep_index" != "t"
362                 then
363                         git reset -q -- "$@"
364                 fi
365         fi
366 }
367
368 save_stash () {
369         push_options=
370         while test $# != 0
371         do
372                 case "$1" in
373                 --)
374                         shift
375                         break
376                         ;;
377                 -*)
378                         # pass all options through to push_stash
379                         push_options="$push_options $1"
380                         ;;
381                 *)
382                         break
383                         ;;
384                 esac
385                 shift
386         done
387
388         stash_msg="$*"
389
390         if test -z "$stash_msg"
391         then
392                 push_stash $push_options
393         else
394                 push_stash $push_options -m "$stash_msg"
395         fi
396 }
397
398 have_stash () {
399         git rev-parse --verify --quiet $ref_stash >/dev/null
400 }
401
402 list_stash () {
403         have_stash || return 0
404         git log --format="%gd: %gs" -g --first-parent -m "$@" $ref_stash --
405 }
406
407 show_stash () {
408         ALLOW_UNKNOWN_FLAGS=t
409         assert_stash_like "$@"
410
411         if test -z "$FLAGS"
412         then
413                 if test "$(git config --bool stash.showStat || echo true)" = "true"
414                 then
415                         FLAGS=--stat
416                 fi
417
418                 if test "$(git config --bool stash.showPatch || echo false)" = "true"
419                 then
420                         FLAGS=${FLAGS}${FLAGS:+ }-p
421                 fi
422
423                 if test -z "$FLAGS"
424                 then
425                         return 0
426                 fi
427         fi
428
429         git diff ${FLAGS} $b_commit $w_commit
430 }
431
432 show_help () {
433         exec git help stash
434         exit 1
435 }
436
437 #
438 # Parses the remaining options looking for flags and
439 # at most one revision defaulting to ${ref_stash}@{0}
440 # if none found.
441 #
442 # Derives related tree and commit objects from the
443 # revision, if one is found.
444 #
445 # stash records the work tree, and is a merge between the
446 # base commit (first parent) and the index tree (second parent).
447 #
448 #   REV is set to the symbolic version of the specified stash-like commit
449 #   IS_STASH_LIKE is non-blank if ${REV} looks like a stash
450 #   IS_STASH_REF is non-blank if the ${REV} looks like a stash ref
451 #   s is set to the SHA1 of the stash commit
452 #   w_commit is set to the commit containing the working tree
453 #   b_commit is set to the base commit
454 #   i_commit is set to the commit containing the index tree
455 #   u_commit is set to the commit containing the untracked files tree
456 #   w_tree is set to the working tree
457 #   b_tree is set to the base tree
458 #   i_tree is set to the index tree
459 #   u_tree is set to the untracked files tree
460 #
461 #   GIT_QUIET is set to t if -q is specified
462 #   INDEX_OPTION is set to --index if --index is specified.
463 #   FLAGS is set to the remaining flags (if allowed)
464 #
465 # dies if:
466 #   * too many revisions specified
467 #   * no revision is specified and there is no stash stack
468 #   * a revision is specified which cannot be resolve to a SHA1
469 #   * a non-existent stash reference is specified
470 #   * unknown flags were set and ALLOW_UNKNOWN_FLAGS is not "t"
471 #
472
473 parse_flags_and_rev()
474 {
475         test "$PARSE_CACHE" = "$*" && return 0 # optimisation
476         PARSE_CACHE="$*"
477
478         IS_STASH_LIKE=
479         IS_STASH_REF=
480         INDEX_OPTION=
481         s=
482         w_commit=
483         b_commit=
484         i_commit=
485         u_commit=
486         w_tree=
487         b_tree=
488         i_tree=
489         u_tree=
490
491         FLAGS=
492         REV=
493         for opt
494         do
495                 case "$opt" in
496                         -q|--quiet)
497                                 GIT_QUIET=-t
498                         ;;
499                         --index)
500                                 INDEX_OPTION=--index
501                         ;;
502                         --help)
503                                 show_help
504                         ;;
505                         -*)
506                                 test "$ALLOW_UNKNOWN_FLAGS" = t ||
507                                         die "$(eval_gettext "unknown option: \$opt")"
508                                 FLAGS="${FLAGS}${FLAGS:+ }$opt"
509                         ;;
510                         *)
511                                 REV="${REV}${REV:+ }'$opt'"
512                         ;;
513                 esac
514         done
515
516         eval set -- $REV
517
518         case $# in
519                 0)
520                         have_stash || die "$(gettext "No stash entries found.")"
521                         set -- ${ref_stash}@{0}
522                 ;;
523                 1)
524                         :
525                 ;;
526                 *)
527                         die "$(eval_gettext "Too many revisions specified: \$REV")"
528                 ;;
529         esac
530
531         case "$1" in
532                 *[!0-9]*)
533                         :
534                 ;;
535                 *)
536                         set -- "${ref_stash}@{$1}"
537                 ;;
538         esac
539
540         REV=$(git rev-parse --symbolic --verify --quiet "$1") || {
541                 reference="$1"
542                 die "$(eval_gettext "\$reference is not a valid reference")"
543         }
544
545         i_commit=$(git rev-parse --verify --quiet "$REV^2") &&
546         set -- $(git rev-parse "$REV" "$REV^1" "$REV:" "$REV^1:" "$REV^2:" 2>/dev/null) &&
547         s=$1 &&
548         w_commit=$1 &&
549         b_commit=$2 &&
550         w_tree=$3 &&
551         b_tree=$4 &&
552         i_tree=$5 &&
553         IS_STASH_LIKE=t &&
554         test "$ref_stash" = "$(git rev-parse --symbolic-full-name "${REV%@*}")" &&
555         IS_STASH_REF=t
556
557         u_commit=$(git rev-parse --verify --quiet "$REV^3") &&
558         u_tree=$(git rev-parse "$REV^3:" 2>/dev/null)
559 }
560
561 is_stash_like()
562 {
563         parse_flags_and_rev "$@"
564         test -n "$IS_STASH_LIKE"
565 }
566
567 assert_stash_like() {
568         is_stash_like "$@" || {
569                 args="$*"
570                 die "$(eval_gettext "'\$args' is not a stash-like commit")"
571         }
572 }
573
574 is_stash_ref() {
575         is_stash_like "$@" && test -n "$IS_STASH_REF"
576 }
577
578 assert_stash_ref() {
579         is_stash_ref "$@" || {
580                 args="$*"
581                 die "$(eval_gettext "'\$args' is not a stash reference")"
582         }
583 }
584
585 apply_stash () {
586
587         assert_stash_like "$@"
588
589         git update-index -q --refresh || die "$(gettext "unable to refresh index")"
590
591         # current index state
592         c_tree=$(git write-tree) ||
593                 die "$(gettext "Cannot apply a stash in the middle of a merge")"
594
595         unstashed_index_tree=
596         if test -n "$INDEX_OPTION" && test "$b_tree" != "$i_tree" &&
597                         test "$c_tree" != "$i_tree"
598         then
599                 git diff-tree --binary $s^2^..$s^2 | git apply --cached
600                 test $? -ne 0 &&
601                         die "$(gettext "Conflicts in index. Try without --index.")"
602                 unstashed_index_tree=$(git write-tree) ||
603                         die "$(gettext "Could not save index tree")"
604                 git reset
605         fi
606
607         if test -n "$u_tree"
608         then
609                 GIT_INDEX_FILE="$TMPindex" git read-tree "$u_tree" &&
610                 GIT_INDEX_FILE="$TMPindex" git checkout-index --all &&
611                 rm -f "$TMPindex" ||
612                 die "$(gettext "Could not restore untracked files from stash entry")"
613         fi
614
615         eval "
616                 GITHEAD_$w_tree='Stashed changes' &&
617                 GITHEAD_$c_tree='Updated upstream' &&
618                 GITHEAD_$b_tree='Version stash was based on' &&
619                 export GITHEAD_$w_tree GITHEAD_$c_tree GITHEAD_$b_tree
620         "
621
622         if test -n "$GIT_QUIET"
623         then
624                 GIT_MERGE_VERBOSITY=0 && export GIT_MERGE_VERBOSITY
625         fi
626         if git merge-recursive $b_tree -- $c_tree $w_tree
627         then
628                 # No conflict
629                 if test -n "$unstashed_index_tree"
630                 then
631                         git read-tree "$unstashed_index_tree"
632                 else
633                         a="$TMP-added" &&
634                         git diff-index --cached --name-only --diff-filter=A $c_tree >"$a" &&
635                         git read-tree --reset $c_tree &&
636                         git update-index --add --stdin <"$a" ||
637                                 die "$(gettext "Cannot unstage modified files")"
638                         rm -f "$a"
639                 fi
640                 squelch=
641                 if test -n "$GIT_QUIET"
642                 then
643                         squelch='>/dev/null 2>&1'
644                 fi
645                 (cd "$START_DIR" && eval "git status $squelch") || :
646         else
647                 # Merge conflict; keep the exit status from merge-recursive
648                 status=$?
649                 git rerere
650                 if test -n "$INDEX_OPTION"
651                 then
652                         gettextln "Index was not unstashed." >&2
653                 fi
654                 exit $status
655         fi
656 }
657
658 pop_stash() {
659         assert_stash_ref "$@"
660
661         if apply_stash "$@"
662         then
663                 drop_stash "$@"
664         else
665                 status=$?
666                 say "$(gettext "The stash entry is kept in case you need it again.")"
667                 exit $status
668         fi
669 }
670
671 drop_stash () {
672         assert_stash_ref "$@"
673
674         git reflog delete --updateref --rewrite "${REV}" &&
675                 say "$(eval_gettext "Dropped \${REV} (\$s)")" ||
676                 die "$(eval_gettext "\${REV}: Could not drop stash entry")"
677
678         # clear_stash if we just dropped the last stash entry
679         git rev-parse --verify --quiet "$ref_stash@{0}" >/dev/null ||
680         clear_stash
681 }
682
683 apply_to_branch () {
684         test -n "$1" || die "$(gettext "No branch name specified")"
685         branch=$1
686         shift 1
687
688         set -- --index "$@"
689         assert_stash_like "$@"
690
691         git checkout -b $branch $REV^ &&
692         apply_stash "$@" && {
693                 test -z "$IS_STASH_REF" || drop_stash "$@"
694         }
695 }
696
697 test "$1" = "-p" && set "push" "$@"
698
699 PARSE_CACHE='--not-parsed'
700 # The default command is "push" if nothing but options are given
701 seen_non_option=
702 for opt
703 do
704         case "$opt" in
705         --) break ;;
706         -*) ;;
707         *) seen_non_option=t; break ;;
708         esac
709 done
710
711 test -n "$seen_non_option" || set "push" "$@"
712
713 # Main command set
714 case "$1" in
715 list)
716         shift
717         list_stash "$@"
718         ;;
719 show)
720         shift
721         show_stash "$@"
722         ;;
723 save)
724         shift
725         save_stash "$@"
726         ;;
727 push)
728         shift
729         push_stash "$@"
730         ;;
731 apply)
732         shift
733         apply_stash "$@"
734         ;;
735 clear)
736         shift
737         clear_stash "$@"
738         ;;
739 create)
740         shift
741         create_stash -m "$*" && echo "$w_commit"
742         ;;
743 store)
744         shift
745         store_stash "$@"
746         ;;
747 drop)
748         shift
749         drop_stash "$@"
750         ;;
751 pop)
752         shift
753         pop_stash "$@"
754         ;;
755 branch)
756         shift
757         apply_to_branch "$@"
758         ;;
759 *)
760         case $# in
761         0)
762                 push_stash &&
763                 say "$(gettext "(To restore them type \"git stash apply\")")"
764                 ;;
765         *)
766                 usage
767         esac
768         ;;
769 esac