-1

Working on some code and want to save a portion of it for later. Assuming not much will happen between the two changesets I decide to git stash -p. An hour or so later realize that it'll get hairy, and don't want to loose my stash. So I want to create a branch out of it.

Unfortunately doing a simple

git branch stash-branch stash@{0}

doesn't yield the results I want. Looking at the tree I see

*   99b0d0c (refs/stash, stash-branch) WIP on my-dev-branch: 2af1f8b PARTIAL but it builds again!
|\
| * d45ddae index on my-dev-branch: 2af1f8b PARTIAL but it builds again!
|/
* 2af1f8b (HEAD -> my-dev-branch) PARTIAL but it builds again!
| * d8bb99f (origin/my-dev-branch) PARTIAL but it builds again!
|/
* fe1296d PARTIAL (doesn't compile)

What I expected is for stash-branch to be on d45ddae, but didn't work out that way. Oh well, I'll go looking around for another way to do this automatically.

After a bit of searching, can't find anything. So my question: Is there an automatic way to refer to the commit just before the tip of stash@{N}? All my efforts result in the newly made branch pointing at my-dev-branch.

EDIT: The git branch command above was incorrect. Has been corrected.

Also, as far as I can tell git stash branch always automatically checks out the branch. In this case I'd only like to create a new branch at an existing sha.

Basically, I'm want to create a new branch, without checking it out, at d45ddae.

Trevor Norris
  • 20,499
  • 4
  • 26
  • 28

2 Answers2

1

You describe "creating a branch out of the stash", which is done with:

git stash branch <branchname> [<stash>]

but you show as a command:

git branch stash@{0}

(which is lacking a branch name, and runs the git branch command instead of the git stash command).

It seems like what you want is git stash branch, e.g.:

git stash branch newbr

(the default is to use the main stash, stash@{0}). This creates a new branch pointing to the commit that was current at the time you saved the stash, then applies the stash (with git stash apply), then on success—which should be "always"—drops the stash.

torek
  • 448,244
  • 59
  • 642
  • 775
  • The `git branch` command was a typo. It's been corrected. As it was it simply returned "is not a valid branch name". The correction results in the tree shown below. Problem w/ `git stash branch` is that it automatically checks out the branch as well. Which isn't what I want. – Trevor Norris Nov 15 '16 at 18:28
  • Yes, `git stash branch` creates-and-checks-out the new branch so as to apply-and-drop the stash. Creating a branch name pointing to the stash's parent commit *without* switching to it is kind of pointless, since that commit will remain referenced (via the stash) until the stash is dropped, and you can refer to that commit at any time via `^2`. You don't need the branch *name* until you are reading to start making commits using the un-stashed stash, and want branch-name behavior for them. (Not that it *hurts* either, and giving these things names is nice.) – torek Nov 16 '16 at 02:59
  • You are more diligent than I am. My stash list becomes polluted frequently. Which I often solve with a quick `git stash clear`. Using a branch I can at least give it a sensible name, and make deleting it more intentional. – Trevor Norris Nov 16 '16 at 21:48
  • 1
    @TrevorNorris: I've *almost* stopped using stash at all, I just create branches and commit. Which means I wind up with a profusion of poorly named branches, alas. :-) – torek Nov 16 '16 at 21:50
0

I completely brain farted the solution until just now. Which is very simple. Basically I wanted to address the second parent of the stash.

*   99b0d0c (refs/stash, stash-branch) WIP on my-dev-branch: 2af1f8b PARTIAL but it builds again!
|\
| * d45ddae index on my-dev-branch: 2af1f8b PARTIAL but it builds again!
|/
* 2af1f8b (HEAD -> my-dev-branch) PARTIAL but it builds again!

So in order to create a new branch with the correct changeset all that needs to be done is follow the second parent. i.e.

git branch stash-branch stash@{0}^2

Which results in the following:

*   99b0d0c (refs/stash) WIP on my-dev-branch: 2af1f8b PARTIAL but it builds again!
|\
| * d45ddae (stash-branch) index on my-dev-branch: 2af1f8b PARTIAL but it builds again!
|/
* 2af1f8b (HEAD -> my-dev-branch) PARTIAL but it builds again!

Now, why would you want to do this? Say multiple files have been edited and only some of them have been added. Take the following:

$ git status
On branch my-dev-branch
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        modified:   Makefile

Changes not staged for commit:

        modified:   README.md

Now run the following commands to see, what I first saw as, unexpected output:

$ git show stash@{0}
commit 2cbcfa95123ab775107311286418f95180a0ca55
Merge: 9e620e0 26f500a
Author: Trevor Norris <xxxxxxxx@gmail.com>
Date:   Tue Nov 15 11:51:09 2016 -0700

    WIP on my-dev-branch: 9e620e0 working on stuff

diff --cc README.md
index d15916e,d15916e..1cf2d60
--- a/README.md
+++ b/README.md
@@@ -2,6 -2,6 +2,8 @@@



++FOO BAR
++

Where'd the cached changes go? They're sitting on branched commit to the stash (can verify this by doing git show stash@{0}^2). This means a new branch can be created, without needing to check it out, pointing to only the cached changes with:

git branch cached-changes stash@{N}^2
Trevor Norris
  • 20,499
  • 4
  • 26
  • 28
  • I think a better answer to "where did the cached changes go" is: they didn't *go* anywhere. They're right where they have been all along, in the stash. What you have done here is to create a name pointing to the *index* commit. (There's nothing wrong with that either, but you might want to consider the work-tree commit, and the third commit if present. See http://stackoverflow.com/a/20412685/1256452 and http://stackoverflow.com/a/20589663/1256452.) – torek Nov 16 '16 at 03:07
  • Excellent references. Will revise my answer after reading through those. – Trevor Norris Nov 16 '16 at 21:51