Git stash with staged files. Does stash convert staged files to unstaged?

I was working on a large set of changes to a code base. Some of the changes had been staged, and some had not. I needed to switch to a different branch, but was not ready to make a commit, so I stashed my current state using git stash.

Later, I went to apply my stash with, git stash apply. Then I ran git status. I noticed that my staged changes no longer appeared as ‘staged’, and instead appear to be included as ‘Changes not staged for commit’. Am I correct in my understanding that no data was actually lost, but instead ‘staged’ data is now simply converted to ‘unstaged’ data?

EDIT: I should add that some of the files in question had staged versions, and unstaged versions at the time of the stash. For example, file A had some changes made, which were staged. Then, some more changes were made to file A, which had not yet been staged. Then, a stash was made.

The answer to the question as asked (“does stash convert staged files to unstaged”) is both yes and no.

If you’ve applied with git stash apply (vs git stash pop), you’re in great shape because the stash is still present. But let’s back up a bit and look at the underlying mechanism, since it matters here.

When you run git stash push (the new verb) or git stash save (the old verb) (or plain git stash which does a push/save), git makes two1 commits that are not on any branch. One commit holds the state of the index, i.e., whatever you’ve staged. The second commit holds state of the work tree, i.e., everything else.

Later, when you use git stash apply, git smushes the changes together so that nothing is staged, unless you add --index2 to the apply operation, in which case it restores (if it can) your previous arrangement of staged vs unstaged.

When you use apply, the stash script keeps the stash commits around as well, so if the apply does not go the way you wanted—including if you forgot --index or misspelled it (see footnote 2)—you can git reset --hard (assuming you had everything in a clean state when you started, anyway) and re-do the apply.

If you’ve used pop, though, and git thinks the apply worked, it then drops the stash. I generally recommend using separate apply and drop just for this reason.

(Side note: I actually recommend avoiding git stash as much as possible. It has too many traps for the unwary, plus it historically has had a number of bugs. But if you’ve used it and now regret it, consider git stash branch, which turns a saved stash into a branch. See ADTC’s comment below. You can do this with the raw hash ID of an already-popped stash, though you will generally need a “clean” state. The new branch branches-out from the commit you were on at the time you made the stash.)


1With -u or -a, which save not just staged and unstaged files abut also ignored and/or all files, the stash script makes three commits. Without these flags, such files don’t go in to either part of the stash, though.

2Confusingly, the stash script also has a --keep-index flag, which it allows you to specify for apply operations but has no meaning there. Instead, --keep-index affects what stash does after making its special stash commits. Occasionally I’ve accidentally done git stash apply --keep-index instead of git stash apply --index, having mixed up the two options.

7

Yes, your thinking is correct. It’s described in the following sections of man git-stash:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>Use git stash when you want to record the current state of the working
directory and the index, but want to go back to a clean working
directory. The command saves your local modifications away and reverts
the working directory to match the HEAD commit.
(...)
pop [--index] [-q|--quiet] [<stash>] Remove a single stashed
state from the stash list and apply it on top of the
current working tree state, i.e., do the inverse operation
of git stash save. The working directory must match the
index.
(...)
If the --index option is used, then tries to reinstate not
only the working tree’s changes, but also the index’s
ones.
(...)
apply [--index] [-q|--quiet] [<stash>]
Like pop, but do not remove the state from the stash list.
</code>
<code>Use git stash when you want to record the current state of the working directory and the index, but want to go back to a clean working directory. The command saves your local modifications away and reverts the working directory to match the HEAD commit. (...) pop [--index] [-q|--quiet] [<stash>] Remove a single stashed state from the stash list and apply it on top of the current working tree state, i.e., do the inverse operation of git stash save. The working directory must match the index. (...) If the --index option is used, then tries to reinstate not only the working tree’s changes, but also the index’s ones. (...) apply [--index] [-q|--quiet] [<stash>] Like pop, but do not remove the state from the stash list. </code>
Use git stash when you want to record the current state of the working
directory and the index, but want to go back to a clean working
directory. The command saves your local modifications away and reverts
the working directory to match the HEAD commit.

(...)

pop [--index] [-q|--quiet] [<stash>] Remove a single stashed
           state from the stash list and apply it on top of the
           current working tree state, i.e., do the inverse operation
           of git stash save. The working directory must match the
           index.

           (...)

           If the --index option is used, then tries to reinstate not
           only the working tree’s changes, but also the index’s
           ones.

(...)

apply [--index] [-q|--quiet] [<stash>]
           Like pop, but do not remove the state from the stash list.

NO, no changes have been lost.

Acc. to the documentation:

Git re-modifies the files you uncommitted when you saved the stash. In this case, you had a clean working directory when you tried to apply the stash, and you tried to apply it on the same branch you saved it from; but having a clean working directory and applying it on the same branch aren’t necessary to successfully apply a stash. You can save a stash on one branch, switch to another branch later, and try to reapply the changes. You can also have modified and uncommitted files in your working directory when you apply a stash — Git gives you merge conflicts if anything no longer applies cleanly.

The changes to your files were reapplied, but the file you staged
before wasn’t restaged. To do that, you must run the git stash apply
command with a –index option to tell the command to try to reapply
the staged changes. If you had run that instead, you’d have gotten
back to your original position:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>$ git stash apply --index
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: index.html
#
# Changes not staged for commit:
# (use "git add <file>..." to update what will be committed)
#
# modified: lib/simplegit.rb
#
</code>
<code>$ git stash apply --index # On branch master # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # modified: index.html # # Changes not staged for commit: # (use "git add <file>..." to update what will be committed) # # modified: lib/simplegit.rb # </code>
$ git stash apply --index
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#      modified:   index.html
#
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#
#      modified:   lib/simplegit.rb
#

1

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật