git stash save 和 git stash push 有什么区别?

What's the difference between git stash save and git stash push?

我什么时候应该使用 git stash save 而不是 git stash push,反之亦然?

git stash save 接受一个非选项参数——隐藏消息。

git stash push 接受带有选项 -m 的消息,并接受要存储的文件列表作为参数。

明确一点,从 Git 2.15/2.16(2018 年第一季度)开始,git stash save 已被弃用,取而代之的是 git stash push(尽管 git stash save 仍然可用暂时)。

参见 commit c0c0c82, commit fd2ebf1, commit db37745 (22 Oct 2017) by Thomas Gummerer (tgummerer)
(由 Junio C Hamano -- gitster -- in commit 40f1293 合并,2017 年 11 月 6 日)

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'.


在 Git 2.18(2018 年第 2 季度)中,命令行补全(在 contrib/ 中)被告知“git stash save”已被弃用(git stash push " 是新世界中的首选拼写)并且不提供它作为可能 完成候选时“git stash push”即可。

参见 commit df70b19, commit 0eb5a4f (19 Apr 2018) by Thomas Gummerer (tgummerer)
(由 Junio C Hamano -- gitster -- in commit 79d92b1 合并,2018 年 5 月 8 日)

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.


命令行完成脚本(在 contrib/ 中)试图像完成“git stash push -p", but it was too aggressive and also affected "git stash show -p”一样完成“git stash -p”,已用 Git 更正2.28(2020 年第三季度)。

参见 commit fffd0cf (21 May 2020) by Ville Skyttä (scop)
(由 Junio C Hamano -- gitster -- in commit a8ecd01 合并,2020 年 6 月 9 日)

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 stash push -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.

push 命令旨在始终在 stash 命令之上使用,因为它更灵活并且使用更常规的命令行参数。由于这些原因,save 命令已被弃用。

替换

2.13.0 中引入了 push 选项,以便以比 save 更传统的方式提供命令行参数。

此更改的基本原理已记录在将命令添加到 Git 的提交消息中:

f5727e2:

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).

c0c0c82:

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.

fd2ebf1:

'git stash push' has all functionality of 'git stash save', with a nicer, more consistent user interface

弃用

save 命令在 Git 的 2.16.0 release 中被正式弃用:

"git stash save" has been deprecated in favour of "git stash push".

save 的弃用在其 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.

缩写形式

除了命令的标准形式外,push 有一个缩写形式,其中从 stash 命令中省略了“push”。 save 命令没有这样的等价物。根据 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

命令比较

通过阅读文档,我认为这应该是两个命令的相当完整的比较:

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)

如此比较所示,savepush 之间的显着变化是:

  • 可以使用 push 的路径规范创建部分存储,但不能 save。 pathspec 可以作为内联参数或使用 --.
  • 提供
  • 消息可以作为 save 的内联参数提供,但必须由 -mpush
  • 中提供