threads / discuss / 15325

Unexpected behaviour with git stash save --keep-index?

Subject: Unexpected behaviour with git stash save --keep-index?

## tl;dr

6 messages between Sep 1, 2008 and Sep 2, 2008.

replies: 5people: 3as markdown or json

Jonas Flodén· Sep 1, 2008, 23:14 UTC · lore
Hello all,

while I was using StGit for the first time and used git stash to split the changes into different patches I noticed that git stash save -- keep-index will stash also the changes that are already in the index. This was unexpected atleast to me but maybe someone can explain why it's correct.

The following sequence should illustrate the problem. Notice how both the b and c are popped from the stash.

git init echo a > test.txt git add test.txt git commit -m "a" echo b >> test.txt git add test.txt echo c >> test.txt git stash save --keep-index git commit -m "b" git checkout -b new_branch HEAD^ git stash pop git diff

Also maybe someone could someone recommend a way to split an unclean working dir into several patches/commits?

With regards
Jonas
SZEDER Gábor· Sep 2, 2008, 01:28 UTC · re: Jonas Flodén · lore

Re: Unexpected behaviour with git stash save --keep-index?

Hi,
On Tue, Sep 02, 2008 at 01:14:10AM +0200, Jonas Flodén wrote:
Show 6 quoted lines
> while I was using StGit for the first time and used git stash to split
> the changes into different patches I noticed that git stash save -- 
> keep-index
> will stash also the changes that are already in the index. This was  
> unexpected
> atleast to me but maybe someone can explain why it's correct.

A plain 'git stash [save]' means "save all local modifications and clear both the index and the working tree".

'git stash save --keep-index' means "save all local modifications and remove all modifications from the working tree that are not in the index". This differs substantially from "save only those modifications that are not in the index, and then remove them from the working tree".

> Also maybe someone could someone recommend a way to split an unclean  
> working dir
> into several patches/commits?

The workflow described at the end of stash's man page (under 'Testing partial commits') works well for me.

(Heh, I have just looked that section up, and noticed that the formatting is broken and some comments are missing from the man page. I will send out a patch in a minute.)

Regards, Gábor

SZEDER Gábor· Sep 2, 2008, 01:35 UTC · re: SZEDER Gábor · lore

[PATCH] Documentation: fix disappeared lines in 'git stash' manpage

Asciidoc removes lines starting with a dot when creating manpages. Since those lines were comments in use case examples showing shell commands, preceed those lines with a hash sign.

Signed-off-by: SZEDER Gábor <szeder@ira.uka.de>
---
 Documentation/git-stash.txt |   14 +++++++-------
 1 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/Documentation/git-stash.txt b/Documentation/git-stash.txt
index 49e2296..cdf3cf1 100644
--- a/Documentation/git-stash.txt
+++ b/Documentation/git-stash.txt
@@ -159,7 +159,7 @@ perform a pull, and then unstash, like this:
 +
 ----------------------------------------------------------------
 $ git pull
-...
+# ...
 file foobar not up to date, cannot merge.
 $ git stash
 $ git pull
@@ -174,7 +174,7 @@ make a commit to a temporary branch to store your changes away, and
 return to your original branch to make the emergency fix, like this:
 +
 ----------------------------------------------------------------
-... hack hack hack ...
+# ... hack hack hack ...
 $ git checkout -b my_wip
 $ git commit -a -m "WIP"
 $ git checkout master
@@ -182,18 +182,18 @@ $ edit emergency fix
 $ git commit -a -m "Fix in a hurry"
 $ git checkout my_wip
 $ git reset --soft HEAD^
-... continue hacking ...
+# ... continue hacking ...
 ----------------------------------------------------------------
 +
 You can use 'git-stash' to simplify the above, like this:
 +
 ----------------------------------------------------------------
-... hack hack hack ...
+# ... hack hack hack ...
 $ git stash
 $ edit emergency fix
 $ git commit -a -m "Fix in a hurry"
 $ git stash apply
-... continue hacking ...
+# ... continue hacking ...
 ----------------------------------------------------------------
 
 Testing partial commits::
@@ -203,13 +203,13 @@ more commits out of the changes in the work tree, and you want to test
 each change before committing:
 +
 ----------------------------------------------------------------
-... hack hack hack ...
+# ... hack hack hack ...
 $ git add --patch foo            # add just first part to the index
 $ git stash save --keep-index    # save all other changes to the stash
 $ edit/build/test first part
 $ git commit foo -m 'First part' # commit fully tested change
 $ git stash pop                  # prepare to work on all other changes
-... repeat above five steps until one commit remains ...
+# ... repeat above five steps until one commit remains ...
 $ edit/build/test remaining parts
 $ git commit foo -m 'Remaining parts'
 ----------------------------------------------------------------
-- 
1.6.0.1.171.gaaac
SZEDER Gábor· Sep 2, 2008, 01:45 UTC · re: SZEDER Gábor · lore

[PATCH] Documentation: minor cleanup in a use case in 'git stash' manual

There is no need to explicitly pass the file to be committed to 'git commit', because it's contents is already in the index.

Signed-off-by: SZEDER Gábor <szeder@ira.uka.de>
---
  Ah, and one more small change in stash docs.
 Documentation/git-stash.txt |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/Documentation/git-stash.txt b/Documentation/git-stash.txt
index cdf3cf1..f91368c 100644
--- a/Documentation/git-stash.txt
+++ b/Documentation/git-stash.txt
@@ -207,7 +207,7 @@ each change before committing:
 $ git add --patch foo            # add just first part to the index
 $ git stash save --keep-index    # save all other changes to the stash
 $ edit/build/test first part
-$ git commit foo -m 'First part' # commit fully tested change
+$ git commit -m 'First part'     # commit fully tested change
 $ git stash pop                  # prepare to work on all other changes
 # ... repeat above five steps until one commit remains ...
 $ edit/build/test remaining parts
-- 
1.6.0.1.171.gaaac
Jonas Flodén· Sep 2, 2008, 06:20 UTC · re: SZEDER Gábor · lore

Re: Unexpected behaviour with git stash save --keep-index?

SZEDER Gábor wrote:
 > 'git stash save --keep-index' means "save all local modifications and
 >  remove all modifications from the working tree that are not in the
 > index".  This differs substantially from "save only those
 > modifications that are not in the index, and then remove them from
 > the working tree".
 >

Thanks for the explanation. It seemed strange first but now I know why it does that.

 >> Also maybe someone could someone recommend a way to split an
 >> unclean working dir into several patches/commits?
 > The workflow described at the end of stash's man page (under 'Testing
 >  partial commits') works well for me.
 >

Thanks. What about the case when I already have a number of existing patches/commits and want to split the working dir into them.

Regards, Jonas

Karl Hasselström· Sep 2, 2008, 07:45 UTC · re: Jonas Flodén · lore

Re: Unexpected behaviour with git stash save --keep-index?

On 2008-09-02 01:14:10 +0200, Jonas Flodén wrote:
> while I was using StGit for the first time
[...]
> Also maybe someone could someone recommend a way to split an unclean
> working dir into several patches/commits?
This is what I usually do:
  1. Create a new StGit patch with all the changes.
  2. Pop that patch.
  3. View the patch in an emacs diff-mode buffer, and repeatedly
       a. apply one or more hunks, and
       b. create a new patch with just those changes
     until no more changes remain.
Another way to do it would be to
  1. Use e.g. git-gui to stage the changes you want in your first
     patch.
  2. Make an StGit patch out of just that (with e.g. stg new and stg
     refresh --index).
  3. If the worktree is still dirty, go to step 1.

A third method I usually make use of is to commit very often while developing, and periodically clump these microcommits together into larger commits. This sidesteps the whole problem of splitting up a commit into pieces, which can be quite a chore if splitting on hunk boundaries isn't enough. (stg coalesce will turn two or more smaller patches into one large patch for you. And I'm pretty sure git-rebase --interactive has some equivalent functions.)

-- 
Karl Hasselström, kha@treskal.com
      www.treskal.com/kalle

← back to recent threads