{"thread":{"id":"17796","subject":"[DRAFT] Create stash from index state","startedAt":"2009-02-14T22:39:29Z","lastAt":"2009-02-14T22:59:53Z","messageCount":2,"participants":["Adeodato Simó","Johannes Schindelin"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"104713","messageId":"20090214223929.GA29472@chistera.yi.org","threadId":"17796","inReplyTo":null,"subject":"[DRAFT] Create stash from index state","fromName":"Adeodato Simó","fromEmail":"dato@net.com.org.es","sentAt":"2009-02-14T22:39:29Z","receivedAt":"2009-02-14T22:39:29Z","isPatch":false,"sender":{"key":"dato@net.com.org.es","avatar":"https://gravatar.com/avatar/952ec7d5d5663eb8baf631b5c37f9c58480a881920dd5f8a2d3a71f969b72b53?d=mp&s=160"},"body":"Hello,\n\nI've always missed a way to do what `bzr shelve` does: interactive\nstash, where you just select hunks à-la `add -p`, and then those gets\nstashed away.\n\nI've recently realized that git-stash doesn't need to know how to prompt\nfor changes, and that just a --from-index flag that would stash the\nstate of the index would be simpler and (at least in my eyes) very git-ish.\n\nDo you think such a flag would be appropriate? I've prepared a\npreliminary, but I need help with the part that removes the index\nchanges from the working tree (a partial git-reset --hard). I know\n\"checkout stash && checkout -\" would do it, but I really don't know how\nto do that with low-level plumbing (unless git-checkout is actually okay\nfor this.) Any suggestions?\n\nAdditionally, I have two behaviors I'd like in stash: the ability to\napply/pop on top of a dirty state, perhaps with a -f flag (at the moment\nI'm just doing `commit -a -m foo && pop && reset HEAD^`), and the\nability to --amend the last stash state, as in \"oh, add this to the last\nstash please\". Thoughts?\n\nMany thanks in advance,\n\n-- \nAdeodato Simó                                     dato at net.com.org.es\nDebian Developer                                  adeodato at debian.org\n \nWhen all is summed up, a man never speaks of himself without loss; his\naccusations of himself are always believed; his praises never.\n                -- Michel de Montaigne\n\n\ndiff --git a/git-stash.sh b/git-stash.sh\nindex b9ace99..0b6f5bd 100755\n--- a/git-stash.sh\n+++ b/git-stash.sh\n@@ -67,26 +67,32 @@ create_stash () {\n \t\tgit commit-tree $i_tree -p $b_commit) ||\n \t\tdie \"Cannot save the current index state\"\n \n-\t# state of the working tree\n-\tw_tree=$( (\n-\t\trm -f \"$TMP-index\" &&\n-\t\tcp -p ${GIT_INDEX_FILE-\"$GIT_DIR/index\"} \"$TMP-index\" &&\n-\t\tGIT_INDEX_FILE=\"$TMP-index\" &&\n-\t\texport GIT_INDEX_FILE &&\n-\t\tgit read-tree -m $i_tree &&\n-\t\tgit add -u &&\n-\t\tgit write-tree &&\n-\t\trm -f \"$TMP-index\"\n-\t) ) ||\n-\t\tdie \"Cannot save the current worktree state\"\n-\n-\t# create the stash\n \tif test -z \"$stash_msg\"\n \tthen\n \t\tstash_msg=$(printf 'WIP on %s' \"$msg\")\n \telse\n \t\tstash_msg=$(printf 'On %s: %s' \"$branch\" \"$stash_msg\")\n \tfi\n+\n+\tif test -z \"$from_index\"\n+\tthen\n+\t\t# state of the working tree\n+\t\tw_tree=$( (\n+\t\t\trm -f \"$TMP-index\" &&\n+\t\t\tcp -p ${GIT_INDEX_FILE-\"$GIT_DIR/index\"} \"$TMP-index\" &&\n+\t\t\tGIT_INDEX_FILE=\"$TMP-index\" &&\n+\t\t\texport GIT_INDEX_FILE &&\n+\t\t\tgit read-tree -m $i_tree &&\n+\t\t\tgit add -u &&\n+\t\t\tgit write-tree &&\n+\t\t\trm -f \"$TMP-index\"\n+\t\t) ) ||\n+\t\t\tdie \"Cannot save the current worktree state\"\n+\telse\n+\t\tw_tree=\"$i_tree\"\n+\tfi\n+\n+\t# create the stash\n \tw_commit=$(printf '%s\\n' \"$stash_msg\" |\n \t\tgit commit-tree $w_tree -p $b_commit -p $i_commit) ||\n \t\tdie \"Cannot record working tree state\"\n@@ -94,10 +100,22 @@ create_stash () {\n \n save_stash () {\n \tkeep_index=\n+\tfrom_index=\n \tcase \"$1\" in\n \t--keep-index)\n \t\tkeep_index=t\n \t\tshift\n+\t\tif [ \"$1\" = \"--from-index\" ]; then\n+\t\t\tdie \"--keep-index and --from-index are incompatible\"\n+\t\tfi\n+\t\t;;\n+\t--from-index)\n+\t\tfrom_index=t\n+\t\tshift\n+\t\tif [ \"$1\" = \"--keep-index\" ]; then\n+\t\t\tdie \"--from-index and --keep-index are incompatible\"\n+\t\tfi\n+\t\t;;\n \tesac\n \n \tstash_msg=\"$*\"\n@@ -120,7 +138,14 @@ save_stash () {\n \t\tdie \"Cannot save the current status\"\n \tprintf 'Saved working directory and index state \"%s\"\\n' \"$stash_msg\"\n \n-\tgit reset --hard\n+\tif test -z \"$from_index\"\n+\tthen\n+\t\tgit reset --hard\n+\telse\n+\t\t# XXX Use plumbing. How?\n+\t\tgit checkout stash\n+\t\tgit checkout -\n+\tfi\n \n \tif test -n \"$keep_index\" && test -n $i_tree\n \tthen\n"},{"id":"104716","messageId":"alpine.DEB.1.00.0902142356200.10279@pacific.mpi-cbg.de","threadId":"17796","inReplyTo":"20090214223929.GA29472@chistera.yi.org","subject":"Re: [DRAFT] Create stash from index state","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2009-02-14T22:59:53Z","receivedAt":"2009-02-14T22:59:53Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Sat, 14 Feb 2009, Adeodato Simó wrote:\n\n> I've always missed a way to do what `bzr shelve` does: interactive\n> stash, where you just select hunks à-la `add -p`, and then those gets\n> stashed away.\n\nI recently wrote this in my blog:\n\n-- snip --\nI think something like an interactive stash is needed. A method to \nspecify what you want to keep in the working directory, the rest should \nbe stashed. The idea would be something like this:\n\n   1. Add the desired changes into a temporary index.\n   2. Put the rest of the changes in another temporary index.\n   3. Stash the latter index.\n   4. Synchronize the working directory with the first index.\n   5. Clean up temporary indices. \n\nOr in code:\n\n$ cp .git/index .git/interactive-stash-1\n$ GIT_INDEX_FILE=.git/interactive-stash-1 git add -i\n$ cp .git/index .git/interactive-stash-2\n$ GIT_INDEX_FILE=.git/interactive-stash-1 git diff -R |\n        (GIT_INDEX_FILE=.git/interactive-stash-2 git apply--index)\n$ tree=$(GIT_INDEX_FILE=.git/index git write-tree)\n$ commit=$(echo Current index | git commit-tree $tree -p HEAD)\n$ tree=$(GIT_INDEX_FILE=.git/interactive-stash-2 git write-tree)\n$ commit=$(echo Edited out | git commit-tree $tree -p HEAD -p $commit)\n$ git update-ref refs/stash $commit\n$ GIT_INDEX_FILE=.git/interactive-stash-1 git checkout-index -a -f\n$ rm .git/interactive-stash-1 .git/interactive-stash-2\n\nThis should probably go into git-stash.sh, maybe even with a switch to \nstart git-gui to do the interactive adding instead of git-add.\n-- snap --\n\nNow, the main reason I did not implement this already is that I am not \nquite sure if you should select the changes you _want_ to keep (which \nwould seem the more natural way to say what needs stashing), or if it \nwould be better to select the changes you do _not_ want to keep (this \nwould seem more consistent, as \"git add -i\" is about selecting what goes \ninto the index, so \"git stash -i\" should be about selecting what goes into \nthe stash).\n\nMaybe you want to give it a try?\n\nCiao,\nDscho\n"}]}