{"thread":{"id":"3958","subject":"[PATCH] Add git-stash to stash the working tree to a new tagged name","startedAt":"2006-04-24T19:37:25Z","lastAt":"2006-04-24T20:58:59Z","messageCount":3,"participants":["Carl Worth","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"19055","messageId":"8764kyzrwq.wl%cworth@cworth.org","threadId":"3958","inReplyTo":null,"subject":"[PATCH] Add git-stash to stash the working tree to a new tagged name","fromName":"Carl Worth","fromEmail":"cworth@cworth.org","sentAt":"2006-04-24T19:37:25Z","receivedAt":"2006-04-24T19:37:25Z","isPatch":true,"sender":{"key":"cworth@cworth.org","avatar":"https://gravatar.com/avatar/3746dc28cde609bdbd7f939058356e7e2bbd16d21e32274df0725eb3d998bc5b?d=mp&s=160"},"body":"This is a really simple script which is convenient for stashing\nchanges in the current working tree:\n\n\tgit stash <tagname>\n\nand recovering them later with something like:\n\n\tgit cherry-pick -n <tagname>\n\tgit tag -d <tagname>\t# optional cleanup\n\n---\n\nThis could also be implemented with a branch rather than a tag, (which\nwould require simply removing the \"git-tag\" and \"git-branch -D\" lines\nfrom the implementation. But I preferred to emphasize that a stashed\ncommit is not a natural basis for more development.\n\nLess than seriously proposing this for inclusion as is, I'm trying to\nstart some discussion around a workflow issue I keep running into. The\ngit-reset documentation describes an \"interrupted workflow\" case and\nsuggests something like the stash and recover operations I describe\nabove but with the following usage:\n\nStashing (on branch 'feature'):\n\n\tgit commit -a -m 'snapshot WIP'\n\nRecovering:\n\n\tgit checkout feature\n\tgit reset --soft HEAD^\n\tgit reset\n\nMy git-stash approach isn't really a lot less work, (in fact, it\nrequires coming up with a new temporary name which makes it less\ndesirable), but it's at least easier for me to remember how to do\nit. For me at least, it seems I'm often having to re-consult the\ngit-reset documentation to decide which variant I need to use in any\ngiven situation---and I still find myself making frustrating mistakes\nwith git-reset every once in a while.\n\nI think an improved interface for interrupted workflow would look more\nlike this:\n\nStashing (on branch 'feature'):\n\n\tgit stash\n\nRecovering:\n\n\tgit checkout feature\n\nThat would be quite pleasant. And I may write my own git-checkout\nwrapper to do this based on some convention for tag naming (such as\n<branchname>-stash). A cleaner implementation might involve some\nper-branch metadata (as has been recently proposed) for storing the\nstashed information rather than a naming convention. [At that point,\nI'm suggesting ideas beyond my intent to code things up.]\n\nAnd if all that were in place, maybe it would even make sense to do\nautomatic stashing by default whenever switching away from a branch\nwith a \"dirty\" working tree, (and without the -m option asking to\nmerge those changes into the destination). Currently, git-checkout\nsimply errors out in this situation, so there's room to add new\nfunctionality there. That would give the most ideal interface of all,\nwhich is simply:\n\nStashing (on branch 'somewhere'):\n\n\tgit checkout elsewhere\n\nRecovering:\n\n\tgit checkout somewhere\n\nOne thing that is missing from all the schemes discussed so far is\nthat they are lossy with respect to differences that originally exist\nbetween the working tree and the index. If an automatically stashing\nscheme were implemented via per-branch metadata, then it seems it\nwould be feasible to stash the working tree and the index separately\ninto the branch's metadata.\n\nThat would be quite convenient for me, since conceptually, the\nworking tree and the index are just as much a part of my \"current\nbranch state\" as the parent commit is.\n\nI'd be interested in any feedback or other ideas.\n\n-Carl\n\n .gitignore   |    1 +\n Makefile     |    2 +-\n git-stash.sh |   24 ++++++++++++++++++++++++\n 3 files changed, 26 insertions(+), 1 deletions(-)\n create mode 100755 git-stash.sh\n\n686ceaf3444d70914c251ad857fc424c9334141c\ndiff --git a/.gitignore b/.gitignore\nindex b5959d6..16c3149 100644\n--- a/.gitignore\n+++ b/.gitignore\n@@ -103,6 +103,7 @@ git-ssh-fetch\n git-ssh-pull\n git-ssh-push\n git-ssh-upload\n+git-stash\n git-status\n git-stripspace\n git-svnimport\ndiff --git a/Makefile b/Makefile\nindex 8aed3af..2a9906e 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -125,7 +125,7 @@ SCRIPT_SH = \\\n \tgit-applymbox.sh git-applypatch.sh git-am.sh \\\n \tgit-merge.sh git-merge-stupid.sh git-merge-octopus.sh \\\n \tgit-merge-resolve.sh git-merge-ours.sh git-grep.sh \\\n-\tgit-lost-found.sh\n+\tgit-lost-found.sh git-stash.sh\n \n SCRIPT_PERL = \\\n \tgit-archimport.perl git-cvsimport.perl git-relink.perl \\\ndiff --git a/git-stash.sh b/git-stash.sh\nnew file mode 100755\nindex 0000000..988ca51\n--- /dev/null\n+++ b/git-stash.sh\n@@ -0,0 +1,24 @@\n+#!/bin/sh\n+#\n+# Copyright (C) 2006 Carl D. Worth\n+\n+USAGE='<tagname>'\n+SUBDIRECTORY_OK=Yes\n+. git-sh-setup\n+\n+if test \"$#\" -ne 1\n+then\n+\tusage\n+fi\n+\n+tagname=\"$1\"\n+\n+headref=$(git-symbolic-ref HEAD | sed -e 's|^refs/heads/||')\n+\n+# We use tagname for the temporary branch name as well.\n+git-checkout -b \"$tagname\" || exit\n+git commit -a -m \"Stash commit of $headref to $tagname\"\n+git tag \"$tagname\"\n+git-checkout \"$headref\"\n+git-branch -D \"$tagname\"\n+\n-- \n1.3.0.g85e6-dirty\n\n"},{"id":"19058","messageId":"7vfyk27kz4.fsf@assigned-by-dhcp.cox.net","threadId":"3958","inReplyTo":"8764kyzrwq.wl%cworth@cworth.org","subject":"Re: [PATCH] Add git-stash to stash the working tree to a new tagged name","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-04-24T20:54:39Z","receivedAt":"2006-04-24T20:54:39Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Carl Worth <cworth@cworth.org> writes:\n\n> Stashing (on branch 'feature'):\n>\n> \tgit commit -a -m 'snapshot WIP'\n>\n> Recovering:\n>\n> \tgit checkout feature\n> \tgit reset --soft HEAD^\n> \tgit reset\n\nIf I were doing this today, I would probably do this:\n\n\tgit commit -a -m 'WIP'\n\n        git checkout elsewhere ;# interrupted\n        ... hack hack hack ...\n\n        git checkout feature ;# come back\n        ... hack hack hack ...\n        git commit --amend\n\nBut I wonder why the originally suggested sequence is reset soft\nto the state we want and then another reset.  Without\nexperimenting myself or thinking hard about it, I would expect\n\"git reset HEAD^\" should do what we want, in which case:\n\nStashing (on branch 'feature'):\n\n\tgit commit -a -m 'snapshot WIP'\n\nRecovering:\n\n\tgit checkout feature\n\tgit reset HEAD^\n"},{"id":"19059","messageId":"874q0izo4s.wl%cworth@cworth.org","threadId":"3958","inReplyTo":"7vfyk27kz4.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] Add git-stash to stash the working tree to a new tagged name","fromName":"Carl Worth","fromEmail":"cworth@cworth.org","sentAt":"2006-04-24T20:58:59Z","receivedAt":"2006-04-24T20:58:59Z","isPatch":true,"sender":{"key":"cworth@cworth.org","avatar":"https://gravatar.com/avatar/3746dc28cde609bdbd7f939058356e7e2bbd16d21e32274df0725eb3d998bc5b?d=mp&s=160"},"body":"On Mon, 24 Apr 2006 13:54:39 -0700, Junio C Hamano wrote:\n> If I were doing this today, I would probably do this:\n...\n>         git commit --amend\n\nOh, that's fantastic.\n\nI hadn't picked up on this feature before, and it looks quite\nuseful. Thanks for pointing that out.\n\n-Carl\n"}]}