{"thread":{"id":"47719","subject":"git stash ; git stash pop unstages all staged changes","startedAt":"2018-01-30T10:38:56Z","lastAt":"2018-01-30T19:57:19Z","messageCount":2,"participants":["Martin Häcker","Igor Djordjevic"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"337780","messageId":"454AAA27-B8D3-47F9-8E49-EC5415A26FCE@schwarz-online.org","threadId":"47719","inReplyTo":null,"subject":"git stash ; git stash pop unstages all staged changes","fromName":"Martin Häcker","fromEmail":"mhaecker@schwarz-online.org","sentAt":"2018-01-30T10:05:00Z","receivedAt":"2018-01-30T10:38:56Z","isPatch":false,"sender":{"key":"mhaecker@schwarz-online.org","avatar":null},"body":"Hi there,\n\nI just lost quite some work, because `git stash; git stash pop` doesn’t seem to understand the concept of the index correctly.\n\nTo reproduce:\n\n— snip —\ndwt@crest ~/Desktop % mkdir test\ndwt@crest ~/Desktop % cd test\ndwt@crest ~/Desktop/test % git init\nInitialized empty Git repository in /Users/dwt/Desktop/test/.git/\ndwt@crest ~/Desktop/test (git)-[master] % touch foo\ndwt@crest ~/Desktop/test (git)-[master] % git add foo\ndwt@crest ~/Desktop/test (git)-[master] % git commit -m \"initial commit\"\n[master (root-commit) 893b428] initial commit\n 1 file changed, 0 insertions(+), 0 deletions(-)\n create mode 100644 foo\ndwt@crest ~/Desktop/test (git)-[master] % echo \"bar\" >> foo\ndwt@crest ~/Desktop/test (git)-[master] % git status\nOn branch master\nChanges not staged for commit:\n  (use \"git add <file>...\" to update what will be committed)\n  (use \"git checkout -- <file>...\" to discard changes in working directory)\n\n\tmodified:   foo\n\nno changes added to commit (use \"git add\" and/or \"git commit -a\")\ndwt@crest ~/Desktop/test (git)-[master] % git add foo\ndwt@crest ~/Desktop/test (git)-[master] % git status\nOn branch master\nChanges to be committed:\n  (use \"git reset HEAD <file>...\" to unstage)\n\n\tmodified:   foo\n\ndwt@crest ~/Desktop/test (git)-[master] % echo \"baz\" >> foo\ndwt@crest ~/Desktop/test (git)-[master] % git diff\ndiff --git a/foo b/foo\nindex 5716ca5..e2994c5 100644\n--- a/foo\n+++ b/foo\n@@ -1 +1,2 @@\n bar\n+baz\ndwt@crest ~/Desktop/test (git)-[master] % git status\nOn branch master\nChanges to be committed:\n  (use \"git reset HEAD <file>...\" to unstage)\n\n\tmodified:   foo\n\nChanges not staged for commit:\n  (use \"git add <file>...\" to update what will be committed)\n  (use \"git checkout -- <file>...\" to discard changes in working directory)\n\n\tmodified:   foo\n\ndwt@crest ~/Desktop/test (git)-[master] % git stash\nSaved working directory and index state WIP on master: 893b428 initial commit\ndwt@crest ~/Desktop/test (git)-[master] % git status\nOn branch master\nnothing to commit, working tree clean\ndwt@crest ~/Desktop/test (git)-[master] % git stash pop\nOn branch master\nChanges not staged for commit:\n  (use \"git add <file>...\" to update what will be committed)\n  (use \"git checkout -- <file>...\" to discard changes in working directory)\n\n\tmodified:   foo\n\nno changes added to commit (use \"git add\" and/or \"git commit -a\")\nDropped refs/stash@{0} (7a8d892120c0a231a529222dabeec1fd3594f514)\ndwt@crest ~/Desktop/test (git)-[master] % git diff\ndiff --git a/foo b/foo\nindex e69de29..e2994c5 100644\n--- a/foo\n+++ b/foo\n@@ -0,0 +1,2 @@\n+bar\n+baz\n\n— snap —\n\nWhat git stash does get right is that it does remove everything that is stashed from the current state of the repo, but what it doesn’t get right is restoring that state fatefully in `git stash pop`.\n\nAs a user, I would expect that `git stash pop` undoes the change that `git stash` inflicted.\n\nBest Regards,\nMartin Häcker\n"},{"id":"337800","messageId":"c5a811ac-8cd3-c389-ac6d-29020a648c87@gmail.com","threadId":"47719","inReplyTo":"454AAA27-B8D3-47F9-8E49-EC5415A26FCE@schwarz-online.org","subject":"Re: git stash ; git stash pop unstages all staged changes","fromName":"Igor Djordjevic","fromEmail":"igor.d.djordjevic@gmail.com","sentAt":"2018-01-30T19:57:07Z","receivedAt":"2018-01-30T19:57:19Z","isPatch":false,"sender":{"key":"igor.d.djordjevic@gmail.com","avatar":null},"body":"Hi Marten,\n\nOn 30/01/2018 11:05, Martin Häcker wrote:\n> \n> I just lost quite some work, because `git stash; git stash pop` \n> doesn’t seem to understand the concept of the index correctly.\n\nI`m afraid it actually seems you`re not fully understanding how `git \nstash pop` works - but the good news is none of your work is lost, as \nlong as you have the stash sha1 (or you can find/restore it through \n`git fsck`).\n\n> What git stash does get right is that it does remove everything that \n> is stashed from the current state of the repo, but what it doesn’t \n> get right is restoring that state fatefully in `git stash pop`.\n\nAccording `git stash pop`[1] documentation, this is as expected, but \nI see the confusing part:\n\n  Remove a single stashed state from the stash list and apply it on top \n  of the current working tree state, i.e., do the inverse operation of \n  `git stash push`. The working directory must match the index.\n\nIt clearly says that stash is applied \"on top of the current _working \ntree_ state\" (so _not_ index), but then it says \"i.e., do the inverse \noperation of `git stash push`\", which is not exactly true (in regards \nto index handling, no options provided explicitly).\n\nLater below, it notes what to do to restore index as well:\n\n  If the `--index` option is used, then tries to reinstate not only the \n  working tree’s changes, but also the index’s ones. However, this can \n  fail, when you have conflicts (which are stored in the index, where \n  you therefore can no longer apply the changes as they were originally).\n\n> As a user, I would expect that `git stash pop` undoes the change that \n> `git stash` inflicted.\n\nThis seems as a fair expectation, especially when documentation \nitself states that `git stash pop` is reverse operation of `git stash \npush`...\n\nAs to why `git stash pop` behaves like this, I would leave to someone \nmore informed to answer, what I myself managed to dig out so far is that \nit seems `--index` was originally discussed to be a default indeed, \nwith `--skip-index` to turn it off if needed, see \"[PATCH] Teach \ngit-stash to \"apply --index\"\"[2] (2007-07-02, Johannes Schindelin) \n(note that `git stash pop` is essentially `git stash apply && git \nstash drop`).\n\nFor the reference, here are some similar topics:\n - \"[BUG] git stash doesn't use --index as default\"[3] (2013-10-11, James)\n - \"Asymmetric default behavior of git stash\"[4] (2013-08-27, Uwe Storbeck)\n - \"Newbie question: Is it possible to undo a stash?\"[5] (2008-05-14, Iván V.)\n\nFinally, here`s your demo script, just modified to use `git stash \npop --index` instead, yielding desired results:\n\n  mkdir test\n  cd test\n  git init\n  touch foo\n  git add foo\n  git commit -m \"initial commit\"\n  echo \"bar\" >> foo\n  git status\n  git add foo\n  git status\n  echo \"baz\" >> foo\n  git diff\n  git status\n  git stash\n  git status\n  git stash pop --index\n  git diff\n\n\nRegards, Buga\n\n[1] https://git-scm.com/docs/git-stash#git-stash-pop--index-q--quietltstashgt\n[2] https://public-inbox.org/git/Pine.LNX.4.64.0707021213350.4438@racer.site/T/#u\n[3] https://public-inbox.org/git/1381467430.4130.38.camel@freed.purpleidea.com/T/#u\n[4] https://public-inbox.org/git/20130827132210.GA14266@ibr.ch/T/#u\n[5] https://public-inbox.org/git/509f40850805141256gce6ac1brf5ced6436f81dae8@mail.gmail.com/T/#u\n"}]}