As Mohana Rao said, git add --patch
doesn't just add the file. It's actually a moderately large Perl script:
$ file $(git --exec-path)/git-add--interactive
/usr/local/libexec/git-core/git-add--interactive: Perl script text executable
and it works by running git diff
on the copy of your file that is in the index now, vs the copy of that same file that is in your work-tree now. It presents the diff to you, one diff-hunk at a time. There are a bunch of things you can do, but the simplest is say "insert this one" or "skip this one", and if you pick "add", the Perl script eitr applies the patch, then runs the code underneath git add
that copies the actual data, from the patched temporary file. So now the index copy of the file has that one diff-hunk added to it, and if you quit the interactive-add operation, and start again, you won't see the option to add that diff-hunk as it's no longer different.
Once you have the file the way you like it in the index, it's ready—at least in theory—to be committed. Running git commit
now would commit what's in the index, not what's in the work-tree. That's fine as far as it goes, but what's in the index has never been tested: it got into the index via the Perl script; it has not been built and run. So now, how will you build and run it?
One way to do that is to git commit
it now, extract the commit somewhere else, and run it. That's kind of painful though. But git stash
already does that—commits it, that is. In fact, git stash
makes two commits, one to hold what's in the index right now, just like a regular git commit
would, and another to hold what's in the work-tree right now, just like git commit -a
would. Be aware that there's a moderately annoying bug in many version of git stash
here. Specifically, they make the right index commit but, depending on what's in the work-tree vs what's in HEAD
, can sometimes make the wrong work-tree commit.
Since git stash
commits the index, though, and saves the work-tree, it's pretty obvious that Git could then replace the work-tree contents with the committed index contents. Having done that, you can now run your tests. If they pass, you can commit and use git stash pop
to put things back.
See also How do I properly git stash/pop in pre-commit hooks to get a clean working tree for tests?