Just to be clear, starting Git 2.15/2.16 (Q1 2018), git stash save has been deprecated in favour of git stash push (though git stash save is still available for the time being).
stash: mark "git stash save" deprecated in the man page
'git stash push' fixes a historical wart in the interface of 'git stash save'.
As 'git stash push' has all functionality of 'git stash save', with a nicer, more consistent user interface deprecate 'git stash save'.
stash: remove now superfluos help for "stash push"
With the 'git stash save' interface, it was easily possible for users to
try to add a message which would start with "-", which 'git stash save'
would interpret as a command line argument, and fail.
For this case we added some extra help on how to create a stash with a message starting with "-".
For 'stash push', messages are passed with the -m flag, avoiding this potential pitfall.
Now only pathspecs starting with "-" would have to be distinguished from command line parameters by using "-- --<pathspec>".
This is fairly common in the git command line interface, and we don't try to guess what the users wanted in the other cases.
Because this way of passing pathspecs is quite common in other git commands, and we don't provide any extra help there, do the same in the error message for 'git stash push'.
With Git 2.18 (Q2 2018), the command line completion (in contrib/) has been taught that "git stash save" has been deprecated ("git stash push" is the preferred spelling in the new world) and does not offer it as a possible
completion candidate when "git stash push" can be.
completion: make stash -p and alias for stash push -p
We define 'git stash -p' as an alias for 'git stash push -p' in the
manpage. Do the same in the completion script, so all options that
can be given to 'git stash push' are being completed when the user is
using 'git stash -p --<tab>'.
Currently the only additional option the user will get is '--message', but there may be more in the future.
The command line completion script (in contrib/) tried to complete "git stash -p" as if it were "git stash push -p", but it was too aggressive and also affected "git stash show -p", which has been corrected With Git 2.28 (Q3 2020).
completion: don't override given stash subcommand with -p
Signed-off-by: Ville Skyttä
df70b190 ("completion: make stash -p and alias for stash push -p", 2018-04-20, Git v2.18.0-rc0 -- merge listed in batch #5) wanted to make sure "git stash -p <TAB>" offers the same completion as "git stashpush -p <TAB>", but it did so by forcing the $subcommand to be "push" whenever then "-p" option is found on the command line.
This harms any subcommand that can take the "-p" option --- even when the subcommand is explicitly given, e.g. "git stash show -p", the code added by the change would overwrite the $subcommand the user gave us.
Fix it by making sure that the defaulting to "push" happens only when there is no $subcommand given yet.
The push command is intended to always be used over the stash command, as it is more flexible and uses more conventional command line arguments. The save command is deprecated for these reasons.
Replacement
The push option was introduced in 2.13.0 in order to provide the command line arguments in a more conventional way than save does.
The rationale for this change was documented in the commit messages which added the command to Git:
Introduce a new git stash push verb in addition to git stash save. The
push verb is used to transition from the current command line arguments
to a more conventional way, in which the message is given as an argument
to the -m option.
This allows us to have pathspecs at the end of the command line
arguments like other Git commands do, so that the user can say which
subset of paths to stash (and leave others behind).
With the 'git stash save' interface, it was easily possible for users to
try to add a message which would start with "-", which 'git stash save'
would interpret as a command line argument, and fail. […]
For 'stash push', messages are passed with the -m flag, avoiding this
potential pitfall. Now only pathspecs starting with "-" would have to
be distinguished from command line parameters by using
"-- --<pathspec>". This is fairly common in the git command line
interface, and we don't try to guess what the users wanted in the other
cases.
'git stash push' has all functionality of 'git stash save',
with a nicer, more consistent user interface
Deprecation
The save command was officially deprecated in the 2.16.0 release of Git:
"git stash save" has been deprecated in favour of "git stash push".
The deprecation of save is explained in its documentation:
save [-p|--patch] [-S|--staged] [-k|--[no-]keep-index] [-u|--include-untracked] [-a|--all] [-q|--quiet] [<message>]
This option is deprecated in favour of git stash push. It differs from "stash push" in that it cannot take pathspec. Instead, all non-option arguments are concatenated to form the stash message.
Short form
In addition to the standard form of the command, push has a short form whereby "push" is omitted from the stash command. The save command has no such equivalent. Per the documentation:
For quickly making a snapshot, you can omit "push". In this mode, non-option arguments are not allowed to prevent a misspelled subcommand from making an unwanted stash entry. The two exceptions to this are stash -p which acts as alias for stash push -p and pathspec elements, which are allowed after a double hyphen -- for disambiguation.
git stash
git stash -p
Command comparison
From reading through the documentation, I think this should be a fairly complete comparison of the two commands:
push
save
git stash push
git stash save
git stash push -m <message>
git stash save <message> or git stash save -m <message>
git stash push -m <message> (message starting with "-")
git stash save -m <message>
git stash push [--] <pathspec>…
N/A (not possible)
git stash push --pathspec-from-file=<file>
N/A (not possible)
git stash
git stash save
git stash -p
git stash save -p
git stash -- <pathspec>…
N/A (not possible)
As shown in this comparison, the notable changes between save and push are:
A partial stash can be created using pathspecs using push, but not save. The pathspec can be provided either as inline arguments or by using --.
The message can be provided as an inline argument with save, but must be provided by -m in push