git stash的预期用途是什么?

239

如果我正在分支A上工作,突然需要在准备好提交分支A之前在分支B上工作,我会将我的更改存储在A上,切换到B,在那里完成我的工作,然后切换回A并应用这个存储。

如果我在A上工作,并且想要停止一天的工作,我应该将我的工作存储起来,然后在第二天继续工作时应用它,还是只是留下未提交的修改文件在工作目录中?除非存在某些安全性的好处,否则我不明白为什么需要在这种情况下使用stash。

此外,另一个情况:我既在工作地又在家里工作。如果我还没有准备好提交,并且想要回家了,我可以将我的工作藏起来,将其推送到GitHub,然后在家里拉取这个stash吗?


3
您的选择很大程度上取决于您公司的政策,如果有的话。您将如何选择“被接受”的答案? (翻译:Your choice largely depends on your company policies, if any. How will you choose the "accepted" answer?) - Daemon Painter
1
这个问题的措辞只是在征求意见(我应该用git 种方式还是种方式?),因此应该被关闭或编辑。 - TylerH
10个回答

282

Stash只是一种方便的方法。由于在git中分支非常廉价且易于管理,我个人几乎总是更喜欢创建一个新的临时分支而不是使用stash,但这主要是个人口味的问题。

我喜欢使用stash的一个场景是,如果我发现我在上一个提交中忘记了某些东西,并且已经在同一个分支上开始处理下一个提交:

# Assume the latest commit was already done
# start working on the next patch, and discovered I was missing something

# stash away the current mess I made
git stash save

# some changes in the working dir

# and now add them to the last commit:
git add -u
git commit --amend

# back to work!
git stash pop

3
当你取消暂存后,你添加的缺失部分是否会合并到暂存中?(我对Git的时间线如何工作仍然不太确定 - 我假设你正在覆盖历史记录?) - Kiki Jewell
@KikiJewell 弹出的更改应用于索引 - 它们没有提交。因此,如果您两次执行 git stash pop,则会丢失这两个更改集之间的区别。 - Mureinik
2
截至2017年10月底,Git邮件列表上进行了广泛讨论,其中命令git stash save正在被弃用,而现有的替代方案git stash push则备受推崇。主要原因是git stash push引入了选择性存储路径规范(pathspecs)的选项,而git stash save不支持此功能。 - Krishna Gupta
1
@Mureinik,你认为新分支和git stash branch哪个更好? - Pacerier
2
@Pacerier 正如我在第一段所说的,我几乎总是更喜欢创建一个新的分支,但这可能更多是一种习惯性的行为,而非任何合理的技术原因。 - Mureinik
显示剩余4条评论

101

我会把回答分成三个段落。

第一部分:

git stash(将未提交的更改保存在“stash”中。 注意:这会从工作树中删除更改!)

git checkout some_branch(切换到预期的分支--在这种情况下是some_branch

git stash list(列出暂存区列表)

你可以看到:
stash@{0}:WIP on {branch_name}:{SHA-1 of last commit} {last commit of you branch}
stash@{1}: WIP on master: 085b095c6 modification for test

git stash apply(将暂存区应用于当前分支的工作树中)

git stash apply stash@{12}(如果你有许多暂存区,你可以选择应用哪个暂存区--在这种情况下,我们应用了暂存区12

git stash drop stash@{0}(从暂存区列表中删除--在这种情况下,暂存区为0

git stash pop stash@{1}(应用所选的暂存区并从暂存区列表中删除它)

第二部分:
你可以使用这个命令隐藏你的更改,但不是必须的。
你可以在没有暂存区的情况下继续工作。

这些命令可以隐藏你的更改并在不同分支上工作,或者实现你的一些代码实现并将其保存在stashes中而不需要分支和提交你的自定义案例!之后,您可以使用其中一些暂存区,并检查哪个更好。

第三部分:
Stash命令用于本地隐藏更改。
如果您想远程工作,必须提交和推送。


20

主要思想是:

将不需要的更改暂存到一个脏工作目录中

基本上,Stash命令会保留那些你当前不需要或不想要的更改,但以后可能会需要。

当你想记录当前状态的工作目录和索引,但又想返回到一个干净的工作目录时,请使用git stash命令。该命令会保存你的本地修改,并将工作目录还原为与HEAD提交匹配的状态。


19
您可以使用以下命令:
  • 保存尚未提交的更改

    git stash

  • 列出已保存的暂存区

    git stash list

  • 应用/取回未提交的更改,其中 x 为 0、1、2......

    git stash apply stash@{x}

注意:

  • 应用一个 stash 并从 stash 列表中删除它

    git stash pop stash@{x}

  • 应用一个 stash 并将其保留在 stash 列表中

    git stash apply stash@{x}


11

我知道StackOverflow不适合提供基于个人看法的答案,但是我确实对何时使用stash有自己的看法。

不想提交试验性改动

当你在你的工作区/工作目录中进行更改时,如果需要执行任何基于分支的操作,如合并、推送、获取或拉取,你必须处于一个干净的提交点。所以如果你有工作区更改,你需要将它们提交。但是如果你不想提交它们呢?如果它们是试验性的?你不想让它们成为你提交历史的一部分?你不想在将代码推到GitHub时让别人看到吗?

不想在硬重置时丢失本地更改

在这种情况下,你可以做一个硬重置。但是如果你做一个硬重置,你会失去所有本地工作目录的更改,因为每样东西都被覆盖到了上次提交的时候,你会失去所有的更改。

那么,关于“什么时候应该存储”,答案是当你需要返回到一个干净的提交点,并且需要保持同步的工作树/索引/提交时,但又不想在此过程中丢失你的本地更改时。只需将更改存储在stash中,你就完成了。

一旦你完成了存储,然后合并或拉取或推送,你只需stash pop或apply,你就可以回到起点了。

Git存储和GitHub

GitHub不断添加新功能,但目前为止,还没有方法可以在那里保存stash。再次强调,stash是本地和私有的。没有人能窥视你的stash,除非物理访问你的工作站。这种方式与git reflog是私有的,而git log是公开的方式类似。如果它被推到GitHub上,它可能不再私有。

一个技巧可能是对你的工作区执行差异,将差异检入你的git仓库,提交并推送。然后你可以从家里进行拉取,获取差异,然后解开它。但这是一个相当混乱的方法来实现这些结果。

git diff > git-dif-file.diff

pop the stash


5

如果你在工作副本中有更改(而不是在暂存区),并且运行了git stash命令,Git 将创建一个储藏对象并将其推入储藏栈的顶部(就像运行git checkout -- . 命令一样,但你不会丢失更改)。稍后,你可以从栈顶弹出。


我认为这也是来自索引。这是来自Git文档的内容: 当您想记录工作目录和索引的当前状态时,请使用git stash。 - Manuel Rivera

4

Stash命令会储藏您上次提交后所做的任何更改。在您的情况下,如果您打算第二天继续工作,没有理由储藏。我只会使用stash去撤销您不想提交的更改。


2
不,git stash 不会改变你的分支。它尤其不会“还原”任何已提交的更改。它只会(临时)丢弃文件中未提交的更改。- 这可能看起来很挑剔,但这些词在 git 的上下文中有着非常特殊的含义。你真的不应该混淆它们。 - michas
谢谢指出。我已经相应地修改了我的答案。 - Severin
在git中,“分支”被定义为一系列提交。git stash不会触及任何提交,因此不会修改任何分支。它不会从分支中“移除”任何内容,也不会以任何方式“重置”它。分支保持不变,只有工作树中的文件发生变化。这是两件完全不同的事情。 - michas
它不会丢弃你的更改,而是“存储”它们!Git为存储保持了一个LIFO结构,因此存储实际上是一个推送操作,您可以从其顶部弹出。单词“丢弃”意味着您将失去任何东西,但实际上并非如此。 - gyorgyabraham

1
也许你可以将stash视为临时的“私有”提交。当你执行stash操作时,不会将其添加到其他人可以看到的提交历史中。这种情况通常是你需要快速隐藏一些东西。
例如:你需要快速回到主分支(无论出于什么原因),没有时间添加到暂存区或做出适当的提交(也许你没有时间审核你所做的工作,不能快速提供清晰的提交信息和描述)。
糟糕的提交会被所有人看到。Stash类似于一个提交,你可以为自己添加消息,重置工作目录,然后稍后回来,只有你可以看到它。至少我不认为推送stash是默认行为。
这里提到了许多其他用途。
可以将stash视为git存储库“机器”之外的存储区域,与所有分支分开,因此可以从任何地方访问它。

1

以上答案已经提供了主要用例。

Stash 的一个用例是,如果您的分支上的更改与您的 stash 中的更改不同,那么在弹出或应用 stash 时可能会遇到冲突。

您可以使用 git stash branch 创建一个新分支,将您的存储更改应用于该分支。例如,

git stash branch master_stash_newBranch stash@{1}

这将基于你创建存储的提交检查出一个新分支,然后将你存储的更改推入该分支。

0

您可以使用两种方式,无论是存储并开始还是从上游创建新分支。存储是更方便的保存撤消重做更改的方式。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接