From bc9e7399af3790918140c30a5b2c85bf9a8f1ad3 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 8 Jul 2007 01:38:32 -0700 Subject: stash: implement "stash create" This subcommand creates a stash from the current state and writes out the resulting commit object ID to the standard output, without updating the stash ref nor resetting the tree. It is intended to be used by scripts to temporarily rewind the working tree to a clean state. Signed-off-by: Junio C Hamano --- git-stash.sh | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/git-stash.sh b/git-stash.sh index 7ba61625ba..04af892531 100755 --- a/git-stash.sh +++ b/git-stash.sh @@ -25,19 +25,13 @@ clear_stash () { fi } -save_stash () { +create_stash () { stash_msg="$1" if no_changes then - echo >&2 'No local changes to save' exit 0 fi - test -f "$GIT_DIR/logs/$ref_stash" || - clear_stash || die "Cannot initialize stash" - - # Make sure the reflog for stash is kept. - : >>"$GIT_DIR/logs/$ref_stash" # state of the base commit if b_commit=$(git rev-parse --verify HEAD) @@ -84,7 +78,20 @@ save_stash () { 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 () { + stash_msg="$1" + + if no_changes + then + echo >&2 '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" git update-ref -m "$stash_msg" $ref_stash $w_commit || die "Cannot save the current status" printf >&2 'Saved "%s"\n' "$stash_msg" @@ -202,6 +209,13 @@ apply) clear) clear_stash ;; +create) + if test $# -gt 0 && test "$1" = create + then + shift + fi + create_stash "$*" && echo "$w_commit" + ;; help | usage) usage ;; -- cgit v1.2.3 From 6c9ad166dbbf9e5a0c09450b892151dbec49b8dc Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 9 Jul 2007 00:51:23 -0700 Subject: rebase: allow starting from a dirty tree. This uses the new "git stash create" interface to stash away the dirty state you have in your working tree before starting a rebase, and then replaying it when you are done with stashing. Signed-off-by: Junio C Hamano --- git-rebase.sh | 72 +++++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 58 insertions(+), 14 deletions(-) diff --git a/git-rebase.sh b/git-rebase.sh index c9942f2400..e342974dc0 100755 --- a/git-rebase.sh +++ b/git-rebase.sh @@ -116,10 +116,30 @@ call_merge () { } finish_rb_merge () { + if test -f "$dotest/stash" + then + stash=$(cat "$dotest/stash") + git stash apply --index "$stash" + fi rm -r "$dotest" echo "All done." } +read_stash () { + if test -f "$1" + then + cat "$1" + fi +} +unstash_and_exit () { + err=$? + if test -f "$1" && test $err = 0 + then + git stash apply --index "$1" + fi + exit $err +} + is_interactive () { test -f "$dotest"/interactive || while case $#,"$1" in 0,|*,-i|*,--interactive) break ;; esac @@ -154,8 +174,9 @@ do finish_rb_merge exit fi + stash=$(read_stash ".dotest/stash") git am --resolved --3way --resolvemsg="$RESOLVEMSG" - exit + unstash_and_exit "$stash" ;; --skip) if test -d "$dotest" @@ -174,21 +195,31 @@ do finish_rb_merge exit fi + stash=$(read_stash ".dotest/stash") git am -3 --skip --resolvemsg="$RESOLVEMSG" - exit + unstash_and_exit "$stash" ;; --abort) git rerere clear if test -d "$dotest" then + if test -f "$dotest/stash" + then + stash=$(cat "$dotest/stash") + fi rm -r "$dotest" elif test -d .dotest then + if test -f ".dotest/stash" + then + stash=$(cat ".dotest/stash") + fi rm -r .dotest else die "No rebase in progress?" fi git reset --hard ORIG_HEAD + test -z "$stash" || git stash apply --index "$stash" exit ;; --onto) @@ -254,16 +285,6 @@ else fi fi -# The tree must be really really clean. -git update-index --refresh || exit -diff=$(git diff-index --cached --name-status -r HEAD) -case "$diff" in -?*) echo "cannot rebase: your index is not up-to-date" - echo "$diff" - exit 1 - ;; -esac - # The upstream head must be given. Make sure it is valid. upstream_name="$1" upstream=`git rev-parse --verify "${upstream_name}^0"` || @@ -273,11 +294,19 @@ upstream=`git rev-parse --verify "${upstream_name}^0"` || onto_name=${newbase-"$upstream_name"} onto=$(git rev-parse --verify "${onto_name}^0") || exit +# The tree must be clean enough for us to create a stash +stash=$(git stash create) || exit +if test -n "$stash" +then + echo >&2 "Stashed away your working tree changes" +fi + # If a hook exists, give it a chance to interrupt if test -x "$GIT_DIR/hooks/pre-rebase" then "$GIT_DIR/hooks/pre-rebase" ${1+"$@"} || { echo >&2 "The pre-rebase hook refused to rebase." + test -z "$stash" || git stash apply --index "$stash" exit 1 } fi @@ -286,7 +315,10 @@ fi case "$#" in 2) branch_name="$2" - git-checkout "$2" || usage + git-checkout "$2" || { + test -z "$stash" || git stash apply --index "$stash" + usage + } ;; *) if branch_name=`git symbolic-ref -q HEAD` @@ -309,6 +341,7 @@ if test "$upstream" = "$onto" && test "$mb" = "$onto" && ! git rev-list --parents "$onto".."$branch" | grep " .* " > /dev/null then echo >&2 "Current branch $branch_name is up to date." + test -z "$stash" || git stash apply --index "$stash" exit 0 fi @@ -328,6 +361,7 @@ git-reset --hard "$onto" if test "$mb" = "$branch" then echo >&2 "Fast-forwarded $branch_name to $onto_name." + test -z "$stash" || git stash apply --index "$stash" exit 0 fi @@ -335,7 +369,16 @@ if test -z "$do_merge" then git format-patch -k --stdout --full-index --ignore-if-in-upstream "$upstream"..ORIG_HEAD | git am $git_am_opt --binary -3 -k --resolvemsg="$RESOLVEMSG" - exit $? + err=$? + + if test $err = 0 + then + test -z "$stash" || git stash apply --index "$stash" + exit + else + test -z "$stash" || echo "$stash" >.dotest/stash + exit $err + fi fi # start doing a rebase with git-merge @@ -346,6 +389,7 @@ echo "$onto" > "$dotest/onto" echo "$onto_name" > "$dotest/onto_name" prev_head=`git rev-parse HEAD^0` echo "$prev_head" > "$dotest/prev_head" +test -z "$stash" || echo "$stash" >"$dotest/stash" msgnum=0 for cmt in `git rev-list --reverse --no-merges "$upstream"..ORIG_HEAD` -- cgit v1.2.3 From 0f49327c9755b6575b447f79b540749d231cb26d Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 1 Nov 2007 13:46:20 -0700 Subject: Revert "rebase: allow starting from a dirty tree." This reverts commit 6c9ad166dbbf9e5a0c09450b892151dbec49b8dc. Allowing rebase to start in a dirty tree might have been a worthy goal, but it is not necessarily always wanted (some people prefer to be reminded that the state is dirty, and think about the next action that may not be to stash and proceed). Furthermore, depending on the nature of local changes, unstashing the dirty state on top of the rebased result is not always desirable. Signed-off-by: Junio C Hamano --- git-rebase.sh | 72 ++++++++++++----------------------------------------------- 1 file changed, 14 insertions(+), 58 deletions(-) diff --git a/git-rebase.sh b/git-rebase.sh index e342974dc0..c9942f2400 100755 --- a/git-rebase.sh +++ b/git-rebase.sh @@ -116,30 +116,10 @@ call_merge () { } finish_rb_merge () { - if test -f "$dotest/stash" - then - stash=$(cat "$dotest/stash") - git stash apply --index "$stash" - fi rm -r "$dotest" echo "All done." } -read_stash () { - if test -f "$1" - then - cat "$1" - fi -} -unstash_and_exit () { - err=$? - if test -f "$1" && test $err = 0 - then - git stash apply --index "$1" - fi - exit $err -} - is_interactive () { test -f "$dotest"/interactive || while case $#,"$1" in 0,|*,-i|*,--interactive) break ;; esac @@ -174,9 +154,8 @@ do finish_rb_merge exit fi - stash=$(read_stash ".dotest/stash") git am --resolved --3way --resolvemsg="$RESOLVEMSG" - unstash_and_exit "$stash" + exit ;; --skip) if test -d "$dotest" @@ -195,31 +174,21 @@ do finish_rb_merge exit fi - stash=$(read_stash ".dotest/stash") git am -3 --skip --resolvemsg="$RESOLVEMSG" - unstash_and_exit "$stash" + exit ;; --abort) git rerere clear if test -d "$dotest" then - if test -f "$dotest/stash" - then - stash=$(cat "$dotest/stash") - fi rm -r "$dotest" elif test -d .dotest then - if test -f ".dotest/stash" - then - stash=$(cat ".dotest/stash") - fi rm -r .dotest else die "No rebase in progress?" fi git reset --hard ORIG_HEAD - test -z "$stash" || git stash apply --index "$stash" exit ;; --onto) @@ -285,6 +254,16 @@ else fi fi +# The tree must be really really clean. +git update-index --refresh || exit +diff=$(git diff-index --cached --name-status -r HEAD) +case "$diff" in +?*) echo "cannot rebase: your index is not up-to-date" + echo "$diff" + exit 1 + ;; +esac + # The upstream head must be given. Make sure it is valid. upstream_name="$1" upstream=`git rev-parse --verify "${upstream_name}^0"` || @@ -294,19 +273,11 @@ upstream=`git rev-parse --verify "${upstream_name}^0"` || onto_name=${newbase-"$upstream_name"} onto=$(git rev-parse --verify "${onto_name}^0") || exit -# The tree must be clean enough for us to create a stash -stash=$(git stash create) || exit -if test -n "$stash" -then - echo >&2 "Stashed away your working tree changes" -fi - # If a hook exists, give it a chance to interrupt if test -x "$GIT_DIR/hooks/pre-rebase" then "$GIT_DIR/hooks/pre-rebase" ${1+"$@"} || { echo >&2 "The pre-rebase hook refused to rebase." - test -z "$stash" || git stash apply --index "$stash" exit 1 } fi @@ -315,10 +286,7 @@ fi case "$#" in 2) branch_name="$2" - git-checkout "$2" || { - test -z "$stash" || git stash apply --index "$stash" - usage - } + git-checkout "$2" || usage ;; *) if branch_name=`git symbolic-ref -q HEAD` @@ -341,7 +309,6 @@ if test "$upstream" = "$onto" && test "$mb" = "$onto" && ! git rev-list --parents "$onto".."$branch" | grep " .* " > /dev/null then echo >&2 "Current branch $branch_name is up to date." - test -z "$stash" || git stash apply --index "$stash" exit 0 fi @@ -361,7 +328,6 @@ git-reset --hard "$onto" if test "$mb" = "$branch" then echo >&2 "Fast-forwarded $branch_name to $onto_name." - test -z "$stash" || git stash apply --index "$stash" exit 0 fi @@ -369,16 +335,7 @@ if test -z "$do_merge" then git format-patch -k --stdout --full-index --ignore-if-in-upstream "$upstream"..ORIG_HEAD | git am $git_am_opt --binary -3 -k --resolvemsg="$RESOLVEMSG" - err=$? - - if test $err = 0 - then - test -z "$stash" || git stash apply --index "$stash" - exit - else - test -z "$stash" || echo "$stash" >.dotest/stash - exit $err - fi + exit $? fi # start doing a rebase with git-merge @@ -389,7 +346,6 @@ echo "$onto" > "$dotest/onto" echo "$onto_name" > "$dotest/onto_name" prev_head=`git rev-parse HEAD^0` echo "$prev_head" > "$dotest/prev_head" -test -z "$stash" || echo "$stash" >"$dotest/stash" msgnum=0 for cmt in `git rev-list --reverse --no-merges "$upstream"..ORIG_HEAD` -- cgit v1.2.3 From a64d7784e830b3140e7d0f2b45cb3d8fafb84cca Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 1 Nov 2007 14:30:30 -0700 Subject: git-merge: no reason to use cpio anymore Now we have "git stash create", we can use it to safely stash away the dirty state in the tree. Signed-off-by: Junio C Hamano --- git-merge.sh | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/git-merge.sh b/git-merge.sh index 3a01db0d75..976117ac90 100755 --- a/git-merge.sh +++ b/git-merge.sh @@ -28,20 +28,19 @@ allow_trivial_merge=t dropsave() { rm -f -- "$GIT_DIR/MERGE_HEAD" "$GIT_DIR/MERGE_MSG" \ - "$GIT_DIR/MERGE_SAVE" || exit 1 + "$GIT_DIR/MERGE_STASH" || exit 1 } savestate() { # Stash away any local modifications. - git diff-index -z --name-only $head | - cpio -0 -o >"$GIT_DIR/MERGE_SAVE" + git stash create >"$GIT_DIR/MERGE_STASH" } restorestate() { - if test -f "$GIT_DIR/MERGE_SAVE" + if test -f "$GIT_DIR/MERGE_STASH" then git reset --hard $head >/dev/null - cpio -iuv <"$GIT_DIR/MERGE_SAVE" + git stash apply $(cat "$GIT_DIR/MERGE_STASH") git update-index --refresh >/dev/null fi } @@ -386,7 +385,7 @@ case "$use_strategies" in single_strategy=no ;; *) - rm -f "$GIT_DIR/MERGE_SAVE" + rm -f "$GIT_DIR/MERGE_STASH" single_strategy=yes ;; esac -- cgit v1.2.3 From a9ee9bf9f9840498f2369ebafe6c220deb4327fd Mon Sep 17 00:00:00 2001 From: Emil Medve Date: Wed, 7 Nov 2007 15:10:27 -0600 Subject: git-stash: Fix listing stashes Commit bc9e7399af3790918140c30a5b2c85bf9a8f1ad3 "reverted" commit f12e925ac23ad6169e046cfe05b8438a1611ad58 Signed-off-by: Emil Medve Signed-off-by: Junio C Hamano --- git-stash.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/git-stash.sh b/git-stash.sh index 04af892531..696b465b7c 100755 --- a/git-stash.sh +++ b/git-stash.sh @@ -21,7 +21,7 @@ no_changes () { clear_stash () { if current=$(git rev-parse --verify $ref_stash 2>/dev/null) then - git update-ref -d refs/stash $current + git update-ref -d $ref_stash $current fi } @@ -92,6 +92,10 @@ save_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" printf >&2 'Saved "%s"\n' "$stash_msg" -- cgit v1.2.3