1

If you have a number of files that are newly added to a repository, but not committed, and you then execute git stash, git pull and git stash apply stash@{0}, what reasons exist for the newly added files to not be included in the apply?

This happened to me yesterday when a coworker modified the htaccess and htpasswd files and created a backup on a staging environment. These backup files were not added to the repository and caused a fatal error and abort of a git pull. So I added the files via git add <filename>, and then executed a stash, pull and apply, only to find the new htaccess and htpasswd files were not included in the apply.

However, git stash show -p stash@{0} | grep "diff" showed that the filenames were in the stash and I was able to see the contents by omitting the grep pipe. This solution was resolved via git checkout stash@{0} -- <filename>, but the question remains as to why a stash apply did not include these files.

Jason
  • 11,263
  • 21
  • 87
  • 181
  • Why must git stash (in this case) have other flags to do what you obviously want it to do in the first place - a 'feature'? As a bonus, you get to go through the git command plus user-pass routine again (the ones you just entered before having to search SO to find out why it didn't work), rather than a "do you want to ...." prompt, to save you that trouble. – JosephK Jun 22 '16 at 10:32

2 Answers2

1

The fact is that untracked files are not taken into account when making some git commands. This is safer because ignoring them is the safest choice that we can make by default (an automatic add would be really not something you want, believe me).

So, if you want to include the newly added files into your stash, just git add them and track them.

EDIT

Sorry, I got confused between newly added files and tracked new files.

According to the manpage of git stash:

If the --keep-index option is used, all changes already added to the index are left intact.

If the --include-untracked option is used, all untracked files are also stashed and then cleaned up with git clean, leaving the working directory in a very clean state. If the --all option is used instead then the ignored files are stashed and cleaned in addition to the untracked files.

With --patch, you can interactively select hunks from the diff between HEAD and the working tree to be stashed. The stash entry is constructed such that its index state is the same as the index state of your repository, and its worktree contains only the changes you selected interactively. The selected changes are then rolled back from your worktree. See the “Interactive Mode” section of git-add(1) to learn how to operate the --patch mode.

The --patch option implies --keep-index. You can use --no-keep-index to override this.

Then, later on, you are given an example:

Testing partial commits

You can use git stash save --keep-index when you want to make two or more commits out of the changes in the work tree, and you want to test each change before committing:

   # ... 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 -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
   $ git commit foo -m 'Remaining parts'

So, in order to include all the changes you have inside the current branch to be present in the stash, you should either use the --keep-index option, or select carefully what file you want to include by marking them with --patch option when adding it.

perror
  • 7,071
  • 16
  • 58
  • 85
  • I think you misread my question. I specifically stated that I executed a `git add` prior to the stash. If the files were not part of the repository, then they would not have shown up via `git stash show -p stash@{0}` – Jason Jul 31 '14 at 13:17
1

The stash stores the index and work-tree states separately (as a two-or-three-commit "stash-bag" hanging off the commit to which HEAD points at the time you make the commit).

The git stash show command compares the HEAD commit (stash^) to the work-tree commit (stash), ignoring the index commit (stash^2) and any untracked/ignored/all-files commit if present (stash^3).

If your git stash show shows them, they must be in the work-tree commit. They should therefore be restored, in general, or the merge might fail if the files now exist. See this answer for a list of the steps that git stash apply takes.

I cannot reproduce your particular issue but it may matter which flags you used when creating the stash (-a or -u) and/or the apply (--index or not), and any git rerere resolutions you might have. You could also use git ls-tree and git show to examine files still in the up-to-three special stash commits (stash, stash^2, and stash^3 in this case, since it's all stash@{0}), and compare them to your current work-tree (especially the one right before the apply, if you can reconstruct it).

Community
  • 1
  • 1
torek
  • 448,244
  • 59
  • 642
  • 775