如何在Git中储藏(stash)特定的文件?

2359

我如何将特定文件暂存,而其他当前修改的文件不包含在即将保存的暂存中?

例如,如果git状态给出以下结果:

younker % gst      
# On branch master
# Your branch is ahead of 'origin/master' by 1 commit.
#
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   modified:   app/controllers/cart_controller.php
#   modified:   app/views/cart/welcome.thtml
#
no changes added to commit (use "git add" and/or "git commit -a")

我只想将 app/views/cart/welcome.thtml 存储,应该怎么做?类似以下方式(但这当然不起作用):

git stash save welcome_cart app/views/cart/welcome.thtml

72
“可能是重复问题”的答案目前有一个错误的被标记为已采纳。 - Penguin Brian
11
你可以使用 git checkout -- 文件名 命令将其还原为原始状态。 - visualex
11
@visualex 确实会还原它,但不会藏起来。 - Jesper
2
企鹅 Brian 的评论:是的,“可能重复”的问题的被接受答案链接到了最近版本的 git 的这个问题。 - Mars
3
$ git stash -- filename.ext - Lini
14个回答

3301

编辑:自git 2.13以来,新增了一条命令可以将特定路径保存到stash中:git stash push <path>。例如:

git stash push -m welcome_cart app/views/cart/welcome.thtml

旧回答:

你可以使用 git stash --patch(或者 git stash -p)来实现这一点 —— 会进入交互模式,其中会呈现出每个修改的补丁。使用 n 来跳过不想储存的文件,y 当遇到想要储存的时候,使用 q 来退出并离开未储存的剩余补丁。 a 将会储存当前展示的补丁和该文件中的其余补丁。

虽然不是最友好的方法,但如果确实需要,它可以完成工作。


41
有些繁琐,但有效。我希望有一种快速的方法只储存已暂存的更改,然后在稍后弹出时将更改应用到未暂存的工作树中。 - James Johnston
74
git stash --keep-index命令会将所有未暂存的更改都储藏起来(与你想要的相反)。https://dev59.com/m3A75IYBdhLWcg3w6Nhj#8333163 - nimser
130
如果你使用a代替y,它将隐藏这个代码块以及文件的其余部分,这样会更快。 - i_am_jorf
53
@jeffamaphone 太棒了!此外,d 将执行相反的操作,即不在当前文件中隐藏任何进一步的补丁块。而 ? 则会显示所有可能的选项。 - omnikron
16
它代表“消息”,用于指定对贮藏的可选描述。如果不需要,可以省略“-m welcome_cart”部分。 - svick
显示剩余21条评论

386

我通常将不想要存储的索引更改添加到索引中,然后使用--keep-index选项进行存储。

git add app/controllers/cart_controller.php
git stash --keep-index
git reset

最后一步是可选的,但通常你都需要它。它将更改从索引中移除。


警告 如注释中所述,git stash --keep-index 将所有内容推送到stash中,包括已暂存和未暂存的更改。 --keep-index 在完成stash后仅使索引保持不变。这可能会在稍后弹出stash时导致合并冲突。


5
如果你有很多的修改但不想通过--patch选项来查看它们,那么这个答案比已接受的答案要好得多。 - quux00
211
不,这会将所有东西都放入stash中,包括已暂存和未暂存的更改。--keep-index选项只是在完成stash后让索引保持不变。所以就我所知,这不是对问题的有效回答。 - Raman
3
请看我在@Rachel的问题上的回答,了解如何进行相反的操作(将已暂存的更改藏起来而不是未暂存的更改)-https://dev59.com/m3A75IYBdhLWcg3w6Nhj#17137669 - JesusFreke
3
如果你想要取回你暂存但未提交的文件,可以运行 git stash; git stash pop stash@{1}。这样做会使得这些文件重新出现在你的工作目录中。 - yndolok
8
警告:请注意@Raman的观点。这个操作不会实现它应该做的事情。这将把相同的更改放入储藏区,并保留它们在工作树中。当您稍后尝试弹出储藏时,很可能会遇到合并冲突,它们通常非常混乱和难以修复。 - rjmunro
2
@DanBerindei 阶段文件留在索引中并进入了存储区。如果您编辑其中一个文件并尝试取消存储,通常会出现编辑冲突。如果您放弃对这些文件的更改并取消存储,则更改将返回 - 至少上次我尝试时是这样的。 - rjmunro

254
只需将一个文件存储起来:
git stash -- filename.txt

要在命令中提供消息而不是在提示时输入,请在文件部分之前添加 -m,例如 git stash -m "stash-message" -- filename1.txt

对于多个文件的隐藏:

git stash -m "stash-message" -- filename1.txt filename2.txt…

4
这仅适用于已被 Git 跟踪的文件,否则会出现错误,如:error: pathspec 'filename1' did not match any file(s) known to git - Nico Brenner
2
这对我来说是最快、最简单的解决方案,可以解决OP的问题,+1 - noxter
8
对于带有消息的存储,请在文件部分之前添加“-m”,例如:git stash -m“您的消息”--filename1.txt filename2.txt - Fenix
2
您还可以通过将未跟踪的文件添加到暂存区来隐藏它们,例如 git add my.file 然后 git stash -- my.file。每当您应用存储更改时,如果需要,可以取消暂存,使其再次保持未跟踪状态。 - DonLarry
1
@Bower -- 的意思是将我之后的所有内容视为文件名。 - undefined
显示剩余4条评论

175

补充 svick 的回答,-m 选项只是向您的存储添加一条消息,完全是可选的。因此,该命令为:

git stash push [paths you wish to stash]

这是完全有效的。因此,例如,如果我只想将更改存储在src/目录中,我只需运行

git stash push src/

4
注意:执行 git stash pop 时不需要路径,只需执行命令即可。 - Olle Härstedt
这个命令比上面的--keep-index建议要高效得多,后者需要多条命令,并且有点违反直觉(需要添加你不想暂存的文件)。 - stwr667

50

如果你使用Visual Studio Code,有一个更简单的方法来暂存选定的文件。

  1. 确保在VSCode中安装了GitLens扩展。
  2. 进入源代码控制选项卡。
  3. 选择要暂存的文件。
  4. 右键点击文件,你将看到许多选项。点击Stash Changes

输入图像描述

  1. 现在它将要求您添加一些stash消息。添加易于理解的消息并按回车键。

输入图像描述


我的显示:放弃更改,暂存更改,添加到Git忽略列表。不要藏匿。 - Someone Somewhere
5
请尝试使用GitLens扩展。 - Akshay
3
适用于许多 VSCode 用户的绝佳解决方案,无需烦恼处理命令。 - kitkatsim

17
简短而简单的解决方案:
git stash -- filename.ext

在你的情况下,使用git stash -- app/views/cart/welcome.thtml命令。

2
哪个版本的git支持这个?我正在使用2.1.4,但它不被支持。 - JellicleCat
1
嗨@JellicleCat,我正在使用2.31.1版本。 - Vicky P
如果想要添加注释:git stash push -m 【comment】 -- 【file path】 - YiPing Chiu

13
  • git status (确保您的更改可以存储)

src/config/bl.go

src/config/dl.go

如果你只想存储dl.go文件:

  • git stash push -m "<键入您的消息例如:dl文件还原>" src/config/dl.go

显示您的存储列表:

  • git stash list

然后检出您的分支并应用存储:

  • git stash apply stash{0}

6
如果您使用GIT GUI客户端没有问题,Fork在2020年5月以后可以非常顺利地完成这个功能。下面的GIF图展示了部分储藏功能,比任何文字都更好理解:GIF of partial stash functionality in git-fork 请注意,Fork(难以在Google中搜索到的名称!)不是免费软件,在评估期之后需要花费50美元购买,但是您可以像处理WinRAR或WinZip弹窗一样无视它们。

5

@svick 发布了一个很棒的答案。我想把所有的 .java 文件都存储起来,而不改动 build.gradle 文件,所以我运行了以下命令:

git stash push *.java

4
  1. 将您不想隐藏的更改进行暂存。
  2. 使用以下命令将其余未暂存的文件进行隐藏:
$ git stash save <give_it_a_name> --keep-index

未暂存的文件现在已经被贮藏。 使用你命名的贮藏可以查看贮藏列表:
$ git stash list

stash@{0}: On mybranch: WIP220412-1119am
stash@{1}: On mybranch: WIP220312-749am

恢复存储的文件:

$ git stash apply stash@{<index_of_saved_stash>}
$ git stash apply stash@{0}

存储在WIP220412-1119am中的更改现已恢复。 而且存储列表也保留了,(您可以通过这种方式保留列表,而不是使用“git stash pop”。)

这只适用于已更改的文件,我猜是吗?如果您想将新文件添加到存储中,您需要先将其暂存,但这无法使用“--keep-index”标志。 - Koen

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