Stash only one file out of multiple files that have changed with Git? Stash only one file out of multiple files that have changed with Git? git git

Stash only one file out of multiple files that have changed with Git?


git stash push -p -m "my commit message"

-p let's you select the hunks that should be stashed; whole files can be selected as well.

You'll be prompted with a few actions for each hunk:

   y - stash this hunk   n - do not stash this hunk   q - quit; do not stash this hunk or any of the remaining ones   a - stash this hunk and all later hunks in the file   d - do not stash this hunk or any of the later hunks in the file   g - select a hunk to go to   / - search for a hunk matching the given regex   j - leave this hunk undecided, see next undecided hunk   J - leave this hunk undecided, see next hunk   k - leave this hunk undecided, see previous undecided hunk   K - leave this hunk undecided, see previous hunk   s - split the current hunk into smaller hunks   e - manually edit the current hunk   ? - print help


Disclaimer: the following answer is for git before git 2.13. For git 2.13 and over, check out another answer further down.


Warning

As noted in the comments, this puts everything into the stash, both staged and unstaged. The --keep-index just leaves the index alone after the stash is done. This can cause merge conflicts when you later pop the stash.


This will stash everything that you haven't previously added. Just git add the things you want to keep, then run it.

git stash --keep-index

For example, if you want to split an old commit into more than one changeset, you can use this procedure:

  1. git rebase -i <last good commit>
  2. Mark some changes as edit.
  3. git reset HEAD^
  4. git add <files you want to keep in this change>
  5. git stash --keep-index
  6. Fix things up as necessary. Don't forget to git add any changes.
  7. git commit
  8. git stash pop
  9. Repeat, from #5, as necessary.
  10. git rebase --continue


Since Git 2.13 (Q2 2017), you can stash individual files, with git stash push:

git stash push [-m <message>] [--] [<pathspec>...]

When pathspec is given to 'git stash push', the new stash records the modified states only for the files that match the pathspecSee "Stash changes to specific files" for more.

Simplified example:

 git stash push path/to/file

The test case for this feature shows a few more options off:

test_expect_success 'stash with multiple pathspec arguments' '    >foo &&    >bar &&    >extra &&    git add foo bar extra &&    git stash push -- foo bar &&       test_path_is_missing bar &&    test_path_is_missing foo &&    test_path_is_file extra &&    git stash pop &&    test_path_is_file foo &&    test_path_is_file bar &&    test_path_is_file extra

The original answer (below, June 2010) was about manually selecting what you want to stash.

Casebash comments:

This (the stash --patch original solution) is nice, but often I've modified a lot of files so using patch is annoying

bukzor's answer (upvoted, November 2011) suggests a more practical solution, based on
git add + git stash --keep-index.
Go see and upvote his answer, which should be the official one (instead of mine).

About that option, chhh points out an alternative workflow in the comments:

you should "git reset --soft" after such a stash to get your clear staging back:
In order to get to the original state - which is a clear staging area and with only some select un-staged modifications, one could softly reset the index to get (without committing anything like you - bukzor - did).


(Original answer June 2010: manual stash)

Yet, git stash save --patch could allows you to achieve the partial stashing you are after:

With --patch, you can interactively select hunks from in 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.

However that will save the full index (which may not be what you want since it might include other files already indexed), and a partial worktree (which could look like the one you want to stash).

git stash --patch --no-keep-index

might be a better fit.


If --patch doesn't work, a manual process might:

For one or several files, an intermediate solution would be to:

  • copy them outside the Git repo
    (Actually, eleotlecram proposes an interesting alternative)
  • git stash
  • copy them back
  • git stash # this time, only the files you want are stashed
  • git stash pop stash@{1} # re-apply all your files modifications
  • git checkout -- afile # reset the file to the HEAD content, before any local modifications

At the end of that rather cumbersome process, you will have only one or several files stashed.