This is a really simple script which is convenient for stashing changes in the current working tree: git stash <tagname> and recovering them later with something like: git cherry-pick -n <tagname> git tag -d <tagname> # optional cleanup --- This could also be implemented with a branch rather than a tag, (which would require simply removing the "git-tag" and "git-branch -D" lines from the implementation. But I preferred to emphasize that a stashed commit is not a natural basis for more development. Less than seriously proposing this for inclusion as is, I'm trying to start some discussion around a workflow issue I keep running into. The git-reset documentation describes an "interrupted workflow" case and suggests something like the stash and recover operations I describe above but with the following usage: Stashing (on branch 'feature'): git commit -a -m 'snapshot WIP' Recovering: git checkout feature git reset --soft HEAD^ git reset My git-stash approach isn't really a lot less work, (in fact, it requires coming up with a new temporary name which makes it less desirable), but it's at least easier for me to remember how to do it. For me at least, it seems I'm often having to re-consult the git-reset documentation to decide which variant I need to use in any given situation---and I still find myself making frustrating mistakes with git-reset every once in a while. I think an improved interface for interrupted workflow would look more like this: Stashing (on branch 'feature'): git stash Recovering: git checkout feature That would be quite pleasant. And I may write my own git-checkout wrapper to do this based on some convention for tag naming (such as <branchname>-stash). A cleaner implementation might involve some per-branch metadata (as has been recently proposed) for storing the stashed information rather than a naming convention. [At that point, I'm suggesting ideas beyond my intent to code things up.] And if all that were in place, maybe it would even make sense to do automatic stashing by default whenever switching away from a branch with a "dirty" working tree, (and without the -m option asking to merge those changes into the destination). Currently, git-checkout simply errors out in this situation, so there's room to add new functionality there. That would give the most ideal interface of all, which is simply: Stashing (on branch 'somewhere'): git checkout elsewhere Recovering: git checkout somewhere One thing that is missing from all the schemes discussed so far is that they are lossy with respect to differences that originally exist between the working tree and the index. If an automatically stashing scheme were implemented via per-branch metadata, then it seems it would be feasible to stash the working tree and the index separately into the branch's metadata. That would be quite convenient for me, since conceptually, the working tree and the index are just as much a part of my "current branch state" as the parent commit is. I'd be interested in any feedback or other ideas. -Carl .gitignore | 1 + Makefile | 2 +- git-stash.sh | 24 ++++++++++++++++++++++++ 3 files changed, 26 insertions(+), 1 deletions(-) create mode 100755 git-stash.sh 686ceaf3444d70914c251ad857fc424c9334141c diff --git a/.gitignore b/.gitignore index b5959d6..16c3149 100644 --- a/.gitignore +++ b/.gitignore @@ -103,6 +103,7 @@ git-ssh-fetch git-ssh-pull git-ssh-push git-ssh-upload +git-stash git-status git-stripspace git-svnimport diff --git a/Makefile b/Makefile index 8aed3af..2a9906e 100644 --- a/Makefile +++ b/Makefile @@ -125,7 +125,7 @@ SCRIPT_SH = \ git-applymbox.sh git-applypatch.sh git-am.sh \ git-merge.sh git-merge-stupid.sh git-merge-octopus.sh \ git-merge-resolve.sh git-merge-ours.sh git-grep.sh \ - git-lost-found.sh + git-lost-found.sh git-stash.sh SCRIPT_PERL = \ git-archimport.perl git-cvsimport.perl git-relink.perl \ diff --git a/git-stash.sh b/git-stash.sh new file mode 100755 index 0000000..988ca51 --- /dev/null +++ b/git-stash.sh @@ -0,0 +1,24 @@ +#!/bin/sh +# +# Copyright (C) 2006 Carl D. Worth + +USAGE='<tagname>' +SUBDIRECTORY_OK=Yes +. git-sh-setup + +if test "$#" -ne 1 +then + usage +fi + +tagname="$1" + +headref=$(git-symbolic-ref HEAD | sed -e 's|^refs/heads/||') + +# We use tagname for the temporary branch name as well. +git-checkout -b "$tagname" || exit +git commit -a -m "Stash commit of $headref to $tagname" +git tag "$tagname" +git-checkout "$headref" +git-branch -D "$tagname" + -- 1.3.0.g85e6-dirty
Attachment:
pgpykARSi5uXa.pgp
Description: PGP signature