Is it possible to extract a single file or diff of a file from a git stash without popping the stash changeset off?
Is it possible to extract a single file or diff of a file from a git stash without popping the stash changeset off?
On the git stash manpage you can read (in the "Discussion" section, just after "Options" description) that:
A stash is represented as a commit whose tree records the state of the working directory, and its first parent is the commit at HEAD when the stash was created.
So you can treat stash (e.g. stash@{0} is first / topmost stash) as a merge commit, and use:
$ git diff stash@{0}^1 stash@{0} -- <filename>
Explanation: stash@{0}^1 means the first parent of the given stash, which as stated in the explanation above is the commit at which changes were stashed away. We use this form of "git diff" (with two commits) because stash@{0} / refs/stash is a merge commit, and we have to tell git which parent we want to diff against. More cryptic:
$ git diff stash@{0}^! -- <filename>
should also work (see git rev-parse manpage for explanation of rev^! syntax, in "Specifying ranges" section).
Likewise, you can use git checkout to check a single file out of the stash:
$ git checkout stash@{0} -- <filename>
or to save it under another filename:
$ git show stash@{0}:<full filename> > <newfile>
or
$ git show stash@{0}:./<relative filename> > <newfile>
(note that here <full filename> is full pathname of a file relative to top directory of a project (think: relative to stash@{0})).
You might need to protect stash@{0} from shell expansion, i.e. use "stash@{0}" or 'stash@{0}'.
If you use git stash apply rather than git stash pop, it will apply the stash to your working tree but still keep the stash.
With this done, you can add/commit the file that you want and then reset the remaining changes.
Use the following to apply the changes to a file in a stash to your working tree.
git diff stash^! -- <filename> | git apply
This is generally better than using git checkout because you won't lose any changes you made to file since you created the stash.
You can get the diff for a stash with "git show stash@{0}" (or whatever the number of the stash is; see "git stash list"). It's easy to extract the section of the diff for a single file.
If the stashed files need to merge with the current version so use the previous ways using diff. Otherwise you might use git pop for unstashing them, git add fileWantToKeep for staging your file, and do a git stash save --keep-index, for stashing everything except what is on stage.
Remember that the difference of this way with the previous ones is that it "pops" the file from stash. The previous answers keep it git checkout stash@{0} -- <filename> so it goes according to your needs.