32

I want to apply some of the changes in a git stash to one commit, and the rest of the changes to another.

Rose Perrone
  • 55,475
  • 49
  • 196
  • 231

4 Answers4

47
git checkout stash@{0} -- <filename>

You can also do this with a list or a glob of filenames.

Will Da Silva
  • 1,428
  • 1
  • 13
  • 28
Leo
  • 713
  • 1
  • 6
  • 9
15

Looks like you can use git checkout -p with a stash reference, like stash@{0}. This will let you choose piece by piece what you want to apply to your work tree from the stash.

After you're done using git checkout -p, the changes you accepted will have been applied to your work tree and added to the cache/index, ready to commit. You can use git checkout -p stash@{0} multiple times, choosing the patches you want and committing however many times you want along the way.

Dmitry Minkovsky
  • 30,036
  • 20
  • 97
  • 138
10

Apply the patch for only the files you want to change.

git show --first-parent stash@{0} -- <file(s) in question> | git apply
Mort
  • 2,888
  • 1
  • 19
  • 33
  • 3
    I think the default output has changed as you now need to specify the `-m` option (`git show -m stash...`) to output a diff that `git apply` understands. Without that I got `error: unrecognised input` from `git apply`. – Andrew France Feb 21 '19 at 18:10
  • @AndrewFrance I can't find much reference to `-m`. Can you point me to some documentation and I'll update my answer. – Mort Feb 24 '19 at 03:51
  • The documentation does seem lacking, `-m` is not in the options list on the man page for `git-show` but it is briefly mentioned in the [combined diff format](https://git-scm.com/docs/git-show#_combined_diff_format) section. It's not clear to me why it works sorry! – Andrew France Mar 19 '19 at 08:52
  • I think `-m` is for `git stash show` (having the same options as `git diff`), not for `git show stash` – user2543253 Oct 08 '19 at 10:57
  • This doesn't seem to work anymore for me either. `git stash show -p stash@{0} | git apply` works if you do not need to select files. But `git stash show` doesn't accept filters on files and `git show` produces some "kind of patch of patch" that `git apply` doesn't understand. – Cilyan Aug 31 '20 at 13:59
  • @Cilyan I don't think you're copying my answer correctly. Try cut and paste rather than typing what you think it is. It's using the `git show` command, and showing `stash@{0}`. And if it truly isn't working, please supply the git version so that I can verify that it is no longer working. – Mort Aug 31 '20 at 14:16
  • `[cilyan@whatever repo]$ git show stash@{0} -- lib/drivers/****.c lib/include/drivers/*****.h | git apply` gives `error: entrée non reconnue`. `git version 2.26.2` – Cilyan Aug 31 '20 at 14:24
  • 1
    @Cilyan I've reproduced the bug. Stashes are now saved as merge commits, it seems and produce a "combined diff". If I add `--first-parent` to the show command, it works again. Answer updated. – Mort Sep 01 '20 at 13:09
7

Unstash the stash...

git stash pop

...use git add in patch mode...

git add -p

...and then commit that...

git commit -m "Partial stashed commit"

This is what quickly came to my head without reading the docs. Leo's answer has much better way to achieve this.

alex
  • 438,662
  • 188
  • 837
  • 957
  • 3
    You could also restash unstaged changes but keep the index. – R0MANARMY Mar 04 '13 at 23:18
  • ^ Yes. @R0MANARMY suggests a good approach. Use `git stash --keep-index` to do this. – acjay Sep 21 '18 at 15:02
  • After doing this, I realized I wanted to follow [Dmitry's answer](https://stackoverflow.com/a/50884446/1048186) because I wanted to have my undesired changes still stashed, but my to-be-commited changes both in the working directory and index/cache/stage so that I could test them before committing them. – Josiah Yoder Jul 24 '19 at 20:35