Skip to content
Navigation Menu
Toggle navigation
Sign in
In this repository
All GitHub Enterprise
↵
Jump to
↵
No suggested jump to results
In this repository
All GitHub Enterprise
↵
Jump to
↵
In this organization
All GitHub Enterprise
↵
Jump to
↵
In this repository
All GitHub Enterprise
↵
Jump to
↵
Sign in
Reseting focus
You signed in with another tab or window.
Reload
to refresh your session.
You signed out in another tab or window.
Reload
to refresh your session.
You switched accounts on another tab or window.
Reload
to refresh your session.
Dismiss alert
{{ message }}
git-mirror
/
git
Public
Notifications
You must be signed in to change notification settings
Fork
0
Star
0
Code
Issues
0
Pull requests
0
Actions
Projects
0
Security
Insights
Additional navigation options
Code
Issues
Pull requests
Actions
Projects
Security
Insights
Files
5d00592
Documentation
block-sha1
compat
contrib
git-gui
git_remote_helpers
gitk-git
gitweb
perl
ppc
t
templates
xdiff
.gitattributes
.gitignore
.mailmap
COPYING
GIT-VERSION-GEN
INSTALL
Makefile
README
RelNotes
abspath.c
advice.c
advice.h
alias.c
alloc.c
archive-tar.c
archive-zip.c
archive.c
archive.h
attr.c
attr.h
base85.c
bisect.c
bisect.h
blob.c
blob.h
branch.c
branch.h
builtin-add.c
builtin-annotate.c
builtin-apply.c
builtin-archive.c
builtin-bisect--helper.c
builtin-blame.c
builtin-branch.c
builtin-bundle.c
builtin-cat-file.c
builtin-check-attr.c
builtin-check-ref-format.c
builtin-checkout-index.c
builtin-checkout.c
builtin-clean.c
builtin-clone.c
builtin-commit-tree.c
builtin-commit.c
builtin-config.c
builtin-count-objects.c
builtin-describe.c
builtin-diff-files.c
builtin-diff-index.c
builtin-diff-tree.c
builtin-diff.c
builtin-fast-export.c
builtin-fetch-pack.c
builtin-fetch.c
builtin-fmt-merge-msg.c
builtin-for-each-ref.c
builtin-fsck.c
builtin-gc.c
builtin-grep.c
builtin-hash-object.c
builtin-help.c
builtin-index-pack.c
builtin-init-db.c
builtin-log.c
builtin-ls-files.c
builtin-ls-remote.c
builtin-ls-tree.c
builtin-mailinfo.c
builtin-mailsplit.c
builtin-merge-base.c
builtin-merge-file.c
builtin-merge-index.c
builtin-merge-ours.c
builtin-merge-recursive.c
builtin-merge-tree.c
builtin-merge.c
builtin-mktag.c
builtin-mktree.c
builtin-mv.c
builtin-name-rev.c
builtin-pack-objects.c
builtin-pack-redundant.c
builtin-pack-refs.c
builtin-patch-id.c
builtin-prune-packed.c
builtin-prune.c
builtin-push.c
builtin-read-tree.c
builtin-receive-pack.c
builtin-reflog.c
builtin-remote.c
builtin-replace.c
builtin-rerere.c
builtin-reset.c
builtin-rev-list.c
builtin-rev-parse.c
builtin-revert.c
builtin-rm.c
builtin-send-pack.c
builtin-shortlog.c
builtin-show-branch.c
builtin-show-ref.c
builtin-stripspace.c
builtin-symbolic-ref.c
builtin-tag.c
builtin-tar-tree.c
builtin-unpack-file.c
builtin-unpack-objects.c
builtin-update-index.c
builtin-update-ref.c
builtin-update-server-info.c
builtin-upload-archive.c
builtin-var.c
builtin-verify-pack.c
builtin-verify-tag.c
builtin-write-tree.c
builtin.h
bundle.c
bundle.h
cache-tree.c
cache-tree.h
cache.h
check-builtins.sh
check-racy.c
check_bindir
color.c
color.h
combine-diff.c
command-list.txt
commit.c
commit.h
config.c
config.mak.in
configure.ac
connect.c
convert.c
copy.c
csum-file.c
csum-file.h
ctype.c
daemon.c
date.c
decorate.c
decorate.h
delta.h
diff-delta.c
diff-lib.c
diff-no-index.c
diff.c
diff.h
diffcore-break.c
diffcore-delta.c
diffcore-order.c
diffcore-pickaxe.c
diffcore-rename.c
diffcore.h
dir.c
dir.h
editor.c
entry.c
environment.c
exec_cmd.c
exec_cmd.h
fast-import.c
fetch-pack.h
fixup-builtins
fsck.c
fsck.h
generate-cmdlist.sh
git-add--interactive.perl
git-am.sh
git-archimport.perl
git-bisect.sh
git-compat-util.h
git-cvsexportcommit.perl
git-cvsimport.perl
git-cvsserver.perl
git-difftool--helper.sh
git-difftool.perl
git-filter-branch.sh
git-instaweb.sh
git-lost-found.sh
git-merge-octopus.sh
git-merge-one-file.sh
git-merge-resolve.sh
git-mergetool--lib.sh
git-mergetool.sh
git-notes.sh
git-parse-remote.sh
git-pull.sh
git-quiltimport.sh
git-rebase--interactive.sh
git-rebase.sh
git-relink.perl
git-repack.sh
git-request-pull.sh
git-send-email.perl
git-sh-setup.sh
git-stash.sh
git-submodule.sh
git-svn.perl
git-web--browse.sh
git.c
git.spec.in
graph.c
graph.h
grep.c
grep.h
hash.c
hash.h
help.c
help.h
hex.c
http-backend.c
http-fetch.c
http-push.c
http-walker.c
http.c
http.h
ident.c
imap-send.c
levenshtein.c
levenshtein.h
list-objects.c
list-objects.h
ll-merge.c
ll-merge.h
lockfile.c
log-tree.c
log-tree.h
mailmap.c
mailmap.h
match-trees.c
merge-file.c
merge-recursive.c
merge-recursive.h
name-hash.c
notes.c
notes.h
object.c
object.h
pack-check.c
pack-refs.c
pack-refs.h
pack-revindex.c
pack-revindex.h
pack-write.c
pack.h
pager.c
parse-options.c
parse-options.h
patch-delta.c
patch-ids.c
patch-ids.h
path.c
pkt-line.c
pkt-line.h
preload-index.c
pretty.c
progress.c
progress.h
quote.c
quote.h
reachable.c
reachable.h
read-cache.c
reflog-walk.c
reflog-walk.h
refs.c
refs.h
remote-curl.c
remote.c
remote.h
replace_object.c
rerere.c
rerere.h
resolve-undo.c
resolve-undo.h
revision.c
revision.h
run-command.c
run-command.h
send-pack.h
server-info.c
setup.c
sha1-lookup.c
sha1-lookup.h
sha1_file.c
sha1_name.c
shallow.c
shell.c
shortlog.h
show-index.c
sideband.c
sideband.h
sigchain.c
sigchain.h
strbuf.c
strbuf.h
string-list.c
string-list.h
submodule.c
submodule.h
symlinks.c
tag.c
tag.h
tar.h
test-chmtime.c
test-ctype.c
test-date.c
test-delta.c
test-dump-cache-tree.c
test-genrandom.c
test-index-version.c
test-match-trees.c
test-parse-options.c
test-path-utils.c
test-run-command.c
test-sha1.c
test-sha1.sh
test-sigchain.c
thread-utils.c
thread-utils.h
trace.c
transport-helper.c
transport.c
transport.h
tree-diff.c
tree-walk.c
tree-walk.h
tree.c
tree.h
unimplemented.sh
unpack-trees.c
unpack-trees.h
upload-pack.c
usage.c
userdiff.c
userdiff.h
utf8.c
utf8.h
walker.c
walker.h
wrap-for-bin.sh
wrapper.c
write_or_die.c
ws.c
wt-status.c
wt-status.h
xdiff-interface.c
xdiff-interface.h
Breadcrumbs
git
/
git-stash.sh
Blame
Blame
Latest commit
History
History
executable file
·
440 lines (384 loc) · 8.55 KB
Breadcrumbs
git
/
git-stash.sh
Top
File metadata and controls
Code
Blame
executable file
·
440 lines (384 loc) · 8.55 KB
Raw
#!/bin/sh # Copyright (c) 2007, Nanako Shiraishi dashless=$(basename "$0" | sed -e 's/-/ /') USAGE="list [<options>] or: $dashless show [<stash>] or: $dashless drop [-q|--quiet] [<stash>] or: $dashless ( pop | apply ) [--index] [-q|--quiet] [<stash>] or: $dashless branch <branchname> [<stash>] or: $dashless [save [--patch] [-k|--[no-]keep-index] [-q|--quiet] [<message>]] or: $dashless clear" SUBDIRECTORY_OK=Yes OPTIONS_SPEC= . git-sh-setup require_work_tree cd_to_toplevel TMP="$GIT_DIR/.git-stash.$$" trap 'rm -f "$TMP-*"' 0 ref_stash=refs/stash if git config --get-colorbool color.interactive; then help_color="$(git config --get-color color.interactive.help 'red bold')" reset_color="$(git config --get-color '' reset)" else help_color= reset_color= fi no_changes () { git diff-index --quiet --cached HEAD --ignore-submodules -- && git diff-files --quiet --ignore-submodules } clear_stash () { if test $# != 0 then die "git stash clear with parameters is unimplemented" fi if current=$(git rev-parse --verify $ref_stash 2>/dev/null) then git update-ref -d $ref_stash $current fi } create_stash () { stash_msg="$1" git update-index -q --refresh if no_changes then exit 0 fi # state of the base commit if b_commit=$(git rev-parse --verify HEAD) then head=$(git log --no-color --abbrev-commit --pretty=oneline -n 1 HEAD --) else die "You do not have the initial commit yet" fi if branch=$(git symbolic-ref -q HEAD) then branch=${branch#refs/heads/} else branch='(no branch)' fi msg=$(printf '%s: %s' "$branch" "$head") # state of the index i_tree=$(git write-tree) && i_commit=$(printf 'index on %s\n' "$msg" | git commit-tree $i_tree -p $b_commit) || die "Cannot save the current index state" if test -z "$patch_mode" then # state of the working tree w_tree=$( ( rm -f "$TMP-index" && cp -p ${GIT_INDEX_FILE-"$GIT_DIR/index"} "$TMP-index" && GIT_INDEX_FILE="$TMP-index" && export GIT_INDEX_FILE && git read-tree -m $i_tree && git add -u && git write-tree && rm -f "$TMP-index" ) ) || die "Cannot save the current worktree state" else rm -f "$TMP-index" && GIT_INDEX_FILE="$TMP-index" git read-tree HEAD && # find out what the user wants GIT_INDEX_FILE="$TMP-index" \ git add--interactive --patch=stash -- && # state of the working tree w_tree=$(GIT_INDEX_FILE="$TMP-index" git write-tree) || die "Cannot save the current worktree state" git diff-tree -p HEAD $w_tree > "$TMP-patch" && test -s "$TMP-patch" || die "No changes selected" rm -f "$TMP-index" || die "Cannot remove temporary index (can't happen)" fi # create the stash if test -z "$stash_msg" then stash_msg=$(printf 'WIP on %s' "$msg") else stash_msg=$(printf 'On %s: %s' "$branch" "$stash_msg") fi w_commit=$(printf '%s\n' "$stash_msg" | git commit-tree $w_tree -p $b_commit -p $i_commit) || die "Cannot record working tree state" } save_stash () { keep_index= patch_mode= while test $# != 0 do case "$1" in -k|--keep-index) keep_index=t ;; --no-keep-index) keep_index= ;; -p|--patch) patch_mode=t keep_index=t ;; -q|--quiet) GIT_QUIET=t ;; --) shift break ;; -*) echo "error: unknown option for 'stash save': $1" echo " To provide a message, use git stash save -- '$1'" usage ;; *) break ;; esac shift done stash_msg="$*" git update-index -q --refresh if no_changes then say 'No local changes to save' exit 0 fi test -f "$GIT_DIR/logs/$ref_stash" || clear_stash || die "Cannot initialize stash" create_stash "$stash_msg" # Make sure the reflog for stash is kept. : >>"$GIT_DIR/logs/$ref_stash" git update-ref -m "$stash_msg" $ref_stash $w_commit || die "Cannot save the current status" say Saved working directory and index state "$stash_msg" if test -z "$patch_mode" then git reset --hard ${GIT_QUIET:+-q} if test -n "$keep_index" && test -n $i_tree then git read-tree --reset -u $i_tree fi else git apply -R < "$TMP-patch" || die "Cannot remove worktree changes" if test -z "$keep_index" then git reset fi fi } have_stash () { git rev-parse --verify $ref_stash >/dev/null 2>&1 } list_stash () { have_stash || return 0 git log --format="%gd: %gs" -g "$@" $ref_stash -- } show_stash () { flags=$(git rev-parse --no-revs --flags "$@") if test -z "$flags" then flags=--stat fi w_commit=$(git rev-parse --verify --default $ref_stash "$@") && b_commit=$(git rev-parse --verify "$w_commit^") && git diff $flags $b_commit $w_commit } apply_stash () { applied_stash= unstash_index= while test $# != 0 do case "$1" in --index) unstash_index=t ;; -q|--quiet) GIT_QUIET=t ;; *) break ;; esac shift done if test $# = 0 then have_stash || die 'Nothing to apply' applied_stash="$ref_stash@{0}" else applied_stash="$*" fi # stash records the work tree, and is a merge between the # base commit (first parent) and the index tree (second parent). s=$(git rev-parse --quiet --verify --default $ref_stash "$@") && w_tree=$(git rev-parse --quiet --verify "$s:") && b_tree=$(git rev-parse --quiet --verify "$s^1:") && i_tree=$(git rev-parse --quiet --verify "$s^2:") || die "$*: no valid stashed state found" git update-index -q --refresh && git diff-files --quiet --ignore-submodules || die 'Cannot apply to a dirty working tree, please stage your changes' # current index state c_tree=$(git write-tree) || die 'Cannot apply a stash in the middle of a merge' unstashed_index_tree= if test -n "$unstash_index" && test "$b_tree" != "$i_tree" && test "$c_tree" != "$i_tree" then git diff-tree --binary $s^2^..$s^2 | git apply --cached test $? -ne 0 && die 'Conflicts in index. Try without --index.' unstashed_index_tree=$(git write-tree) || die 'Could not save index tree' git reset fi eval " GITHEAD_$w_tree='Stashed changes' && GITHEAD_$c_tree='Updated upstream' && GITHEAD_$b_tree='Version stash was based on' && export GITHEAD_$w_tree GITHEAD_$c_tree GITHEAD_$b_tree " if test -n "$GIT_QUIET" then export GIT_MERGE_VERBOSITY=0 fi if git merge-recursive $b_tree -- $c_tree $w_tree then # No conflict if test -n "$unstashed_index_tree" then git read-tree "$unstashed_index_tree" else a="$TMP-added" && git diff-index --cached --name-only --diff-filter=A $c_tree >"$a" && git read-tree --reset $c_tree && git update-index --add --stdin <"$a" || die "Cannot unstage modified files" rm -f "$a" fi squelch= if test -n "$GIT_QUIET" then squelch='>/dev/null 2>&1' fi eval "git status $squelch" || : else # Merge conflict; keep the exit status from merge-recursive status=$? if test -n "$unstash_index" then echo >&2 'Index was not unstashed.' fi exit $status fi } drop_stash () { have_stash || die 'No stash entries to drop' while test $# != 0 do case "$1" in -q|--quiet) GIT_QUIET=t ;; *) break ;; esac shift done if test $# = 0 then set x "$ref_stash@{0}" shift fi # Verify supplied argument looks like a stash entry s=$(git rev-parse --verify "$@") && git rev-parse --verify "$s:" > /dev/null 2>&1 && git rev-parse --verify "$s^1:" > /dev/null 2>&1 && git rev-parse --verify "$s^2:" > /dev/null 2>&1 || die "$*: not a valid stashed state" git reflog delete --updateref --rewrite "$@" && say "Dropped $* ($s)" || die "$*: Could not drop stash entry" # clear_stash if we just dropped the last stash entry git rev-parse --verify "$ref_stash@{0}" > /dev/null 2>&1 || clear_stash } apply_to_branch () { have_stash || die 'Nothing to apply' test -n "$1" || die 'No branch name specified' branch=$1 if test -z "$2" then set x "$ref_stash@{0}" fi stash=$2 git checkout -b $branch $stash^ && apply_stash --index $stash && drop_stash $stash } # The default command is "save" if nothing but options are given seen_non_option= for opt do case "$opt" in -*) ;; *) seen_non_option=t; break ;; esac done test -n "$seen_non_option" || set "save" "$@" # Main command set case "$1" in list) shift list_stash "$@" ;; show) shift show_stash "$@" ;; save) shift save_stash "$@" ;; apply) shift apply_stash "$@" ;; clear) shift clear_stash "$@" ;; create) if test $# -gt 0 && test "$1" = create then shift fi create_stash "$*" && echo "$w_commit" ;; drop) shift drop_stash "$@" ;; pop) shift if apply_stash "$@" then drop_stash "$applied_stash" fi ;; branch) shift apply_to_branch "$@" ;; *) case $# in 0) save_stash && say '(To restore them type "git stash apply")' ;; *) usage esac ;; esac
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
You can’t perform that action at this time.