我总是认为你可以通过git stash save stashname
来保存一个名字,以后可以通过git stash apply stashname
申请。但似乎在这种情况下,所有发生的事情都是stashname
将被用作藏匿描述。
有没有办法真正命名藏匿?如果没有,你会建议什么实现相同的功能?基本上我有一个小的藏匿,我会定期申请,但不想总是在git stash list
中寻找它的实际藏匿号码。
答案 0 :(得分:504)
您就是这样做的:
git stash save "my_stash"
其中"my_stash"
是藏匿名称。
要了解更多有用的信息:所有存储都存储在堆栈中。 类型:
git stash list
这将列出你的所有藏匿处。
要应用存储并将其从存储堆栈中删除,请键入:
git stash pop stash@{n}
要应用存储并将其保存在存储堆栈中,请键入:
git stash apply stash@{n}
n
是隐藏更改的索引。
答案 1 :(得分:171)
git stash save
已弃用,您可以使用git stash push -m "message"
你可以像这样使用它:
git stash push -m "message"
其中"消息"是你对那个藏匿处的记录。
为了检索藏匿,您可以使用:git stash list
。这将输出这样的列表,例如:
stash@{0}: On develop: perf-spike
stash@{1}: On develop: node v10
然后,您只需使用apply
为其提供stash@{index}
:
git stash apply stash@{1}
答案 2 :(得分:81)
如果你认为它足够重要,你可以把藏匿处变成一个分支:
git stash branch <branchname> [<stash>]
来自手册页:
这将创建并检出一个名为<branchname>
的新分支,从最初创建<stash>
的提交开始,将<stash>
中记录的更改应用于新的工作树和索引,如果成功完成,则删除<stash>
。如果没有给出<stash>
,则应用最新的。{/ p>
如果运行git stash save
的分支已经发生了足够的变化,git stash apply因冲突而失败,这将非常有用。由于存储是在运行git stash时的HEAD提交之上应用的,因此它会恢复原始存储状态而不会发生冲突。
你可以稍后将这个新分支重新绑定到其他地方,这个地方是你藏匿时所处的位置。
答案 3 :(得分:38)
如果您只是想要一种轻量级的方法来保存当前的部分或全部工作副本更改,然后随意重新应用它们,请考虑一个补丁文件:
# save your working copy changes
git diff > some.patch
# re-apply it later
git apply some.patch
我时不时地想知道我是否应该使用藏匿处,然后我会看到上面的疯狂之类的内容,而且我对我正在做的事情感到满意:)
答案 4 :(得分:38)
Stashes并不是你想要的永久性东西。在提交时使用标签可能会更好。构建你想藏匿的东西。做出承诺。为该提交创建标记。然后将您的分支回滚到HEAD^
。现在,当您想重新申请该存储时,可以使用git cherry-pick -n tagname
(-n
为--no-commit
)。
答案 5 :(得分:23)
所以,我不确定为什么在这个话题上有这么多的疑惑。我可以同时使用push
和已弃用的save
name a git stash
,也可以使用正则表达式将其apply
撤回:
$ git stash push -m "john-hancock"
$ git stash apply stash^{/john-hancock}
如前所述,save
命令已被弃用,但仍然可以使用,因此您可以在无法通过push
调用进行更新的旧系统上使用此命令。与push
命令不同,-m
不需要save
开关。
// save is deprecated but still functional
$ git stash save john-hancock
这是Git 2.2和Windows 10。
这是演示过程的精美GIF动画。
GIF运行很快,但是如果您看,过程是这样的:
ls
命令在目录中显示4个文件touch example.html
添加第5个文件git stash push -m "john-hancock" -a
(-a
包含未跟踪的文件)ls
命令在隐藏之后显示4个文件,这意味着隐藏和隐式硬重置均有效git stash apply stash^{/john-hancock}
运行ls
命令列出了5个文件,表明 example.html 文件已恢复,这意味着git stash apply
命令有效。坦率地说,我不确定这种方法的好处是什么。给存储区起一个名字是有价值的,但取回却没有。也许编写shelve and unshelve脚本的脚本可能会有所帮助,但是仅按名称弹出隐藏项仍然很容易。
$ git stash pop 3
$ git stash apply 3
在我看来,这比正则表达式更容易。
答案 6 :(得分:22)
使用git stash push -m aNameForYourStash
保存它。然后使用git stash list
了解要应用的存储的索引。然后使用git stash pop --index 0
弹出存储并应用它。
注意:我正在使用 git版本2.21.0.windows.1
答案 7 :(得分:18)
我在.zshrc
文件中有这两个函数:
function gitstash() {
git stash push -m "zsh_stash_name_$1"
}
function gitstashapply() {
git stash apply $(git stash list | grep "zsh_stash_name_$1" | cut -d: -f1)
}
以这种方式使用它们:
gitstash nice
gitstashapply nice
答案 8 :(得分:8)
sapply = "!f() { git stash apply \"$(git stash list | awk -F: --posix -vpat=\"$*\" \"$ 0 ~ pat {print $ 1; exit}\")\"; }; f"
git sapply "<regex>"
编辑:我坚持原来的解决方案,但我明白为什么大多数人更喜欢Etan Reisner的版本(上图)。所以只是为了记录:
sapply = "!f() { git stash apply \"$(git stash list | grep -E \"$*\" | awk \"{ print $ 1; }\" | sed -n \"s/://;1p\")\"; }; f"
答案 9 :(得分:7)
不幸的是,git stash apply stash^{/<regex>}
不起作用(它实际上没有搜索存储列表,请参见accepted answer下的注释)。
这里是直接替换项,它们通过正则表达式搜索git stash list
以找到第一个(最新的)stash@{<n>}
,然后将其传递给git stash <command>
:
# standalone (replace <stash_name> with your regex)
(n=$(git stash list --max-count=1 --grep=<stash_name> | cut -f1 -d":") ; if [[ -n "$n" ]] ; then git stash show "$n" ; else echo "Error: No stash matches" ; return 1 ; fi)
(n=$(git stash list --max-count=1 --grep=<stash_name> | cut -f1 -d":") ; if [[ -n "$n" ]] ; then git stash apply "$n" ; else echo "Error: No stash matches" ; return 1 ; fi)
# ~/.gitconfig
[alias]
sshow = "!f() { n=$(git stash list --max-count=1 --grep=$1 | cut -f1 -d":") ; if [[ -n "$n" ]] ; then git stash show "$n" ; else echo "Error: No stash matches $1" ; return 1 ; fi }; f"
sapply = "!f() { n=$(git stash list --max-count=1 --grep=$1 | cut -f1 -d":") ; if [[ -n "$n" ]] ; then git stash apply "$n" ; else echo "Error: No stash matches $1" ; return 1 ; fi }; f"
# usage:
$ git sshow my_stash
myfile.txt | 1 +
1 file changed, 1 insertion(+)
$ git sapply my_stash
On branch master
Your branch is up to date with 'origin/master'.
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: myfile.txt
no changes added to commit (use "git add" and/or "git commit -a")
请注意,将返回正确的结果代码,因此您可以在其他脚本中使用这些命令。可以在使用以下命令运行命令后对此进行验证:
echo $?
请注意variable expansion exploits,因为我不确定--grep=$1
部分。应该是--grep="$1"
,但我不确定是否会干扰正则表达式分隔符(我愿意接受建议)。
答案 10 :(得分:6)
这个答案很大程度上归功于KlemenSlavič。我会对已接受的答案发表评论,但我还没有足够的代表:(
您还可以添加一个git别名来查找存储引用,并将其用于show,apply,drop等其他别名。
[alias]
sgrep = "!f() { ref=$(git --no-pager stash list | grep "$1" | cut -d: -f1 | head -n1); echo ${ref:-<no_match>}; }; f"
sshow = "!f() { git stash show $(git sgrep "$1") -p; }; f"
sapply = "!f() { git stash apply $(git sgrep "$1"); }; f"
sdrop = "!f() { git stash drop $(git sgrep "$1"); }; f"
请注意,ref=$( ... ); echo ${ref:-<no_match>};
模式的原因是没有返回空白字符串,这会导致sshow,sapply和sdrop定位最新的存储而不是像预期的那样失败。
答案 11 :(得分:4)
<强>别名强> 对于类Unix系统而言,这可能是一种更直接的语法,无需封装在函数中。 将以下内容添加到[alias]
下的〜/ .gitconfig中sshow = !sh -c 'git stash show stash^{/$*} -p' -
sapply = !sh -c 'git stash apply stash^{/$*}' -
ssave = !sh -c 'git stash save "${1}"' -
使用方法: sapply regex
实施例: git sshow MySecretStash
最后的连字符表示从标准输入中输入。
答案 12 :(得分:4)
使用小型bash脚本查找存储的编号。称之为&#34; gitapply&#34;:
NAME="$1"
if [[ -z "$NAME" ]]; then echo "usage: gitapply [name]"; exit; fi
git stash apply $(git stash list | grep "$NAME" | cut -d: -f1)
用法:
gitapply foo
...其中foo是您想要的藏匿名称的子字符串。
答案 13 :(得分:2)
这是使用PowerShell实现此目的的一种方法:
<#
.SYNOPSIS
Restores (applies) a previously saved stash based on full or partial stash name.
.DESCRIPTION
Restores (applies) a previously saved stash based on full or partial stash name and then optionally drops the stash. Can be used regardless of whether "git stash save" was done or just "git stash". If no stash matches a message is given. If multiple stashes match a message is given along with matching stash info.
.PARAMETER message
A full or partial stash message name (see right side output of "git stash list"). Can also be "@stash{N}" where N is 0 based stash index.
.PARAMETER drop
If -drop is specified, the matching stash is dropped after being applied.
.EXAMPLE
Restore-Stash "Readme change"
Apply-Stash MyStashName
Apply-Stash MyStashName -drop
Apply-Stash "stash@{0}"
#>
function Restore-Stash {
[CmdletBinding()]
[Alias("Apply-Stash")]
PARAM (
[Parameter(Mandatory=$true)] $message,
[switch]$drop
)
$stashId = $null
if ($message -match "stash@{") {
$stashId = $message
}
if (!$stashId) {
$matches = git stash list | Where-Object { $_ -match $message }
if (!$matches) {
Write-Warning "No stashes found with message matching '$message' - check git stash list"
return
}
if ($matches.Count -gt 1) {
Write-Warning "Found $($matches.Count) matches for '$message'. Refine message or pass 'stash{@N}' to this function or git stash apply"
return $matches
}
$parts = $matches -split ':'
$stashId = $parts[0]
}
git stash apply ''$stashId''
if ($drop) {
git stash drop ''$stashId''
}
}
答案 14 :(得分:2)
使用git stash save NAME
保存。
然后......您可以使用此脚本选择要应用(或弹出)的内容:
#!/usr/bin/env ruby
#git-stash-pick by Dan Rosenstark
# can take a command, default is apply
command = ARGV[0]
command = "apply" if !command
ARGV.clear
stashes = []
stashNames = []
`git stash list`.split("\n").each_with_index { |line, index|
lineSplit = line.split(": ");
puts "#{index+1}. #{lineSplit[2]}"
stashes[index] = lineSplit[0]
stashNames[index] = lineSplit[2]
}
print "Choose Stash or ENTER to exit: "
input = gets.chomp
if input.to_i.to_s == input
realIndex = input.to_i - 1
puts "\n\nDoing #{command} to #{stashNames[realIndex]}\n\n"
puts `git stash #{command} #{stashes[realIndex]}`
end
我喜欢能够看到藏匿处的名字并选择。我也使用Zshell,坦率地说不知道如何使用上面的一些Bash别名;)
答案 15 :(得分:2)
对于除了藏匿创建之外的所有内容,我通过引入fzf作为依赖关系来提出另一种解决方案。建议花5分钟的时间来介绍它,因为它总体上提高了生产力。
无论如何,他们examples page提供藏匿搜索的相关摘录。更改sciptlet以添加其他功能(如存储应用程序或删除)非常容易:
fstash() {
local out q k sha
while out=$(
git stash list --pretty="%C(yellow)%h %>(14)%Cgreen%cr %C(blue)%gs" |
fzf --ansi --no-sort --query="$q" --print-query \
--expect=ctrl-d,ctrl-b); do
mapfile -t out <<< "$out"
q="${out[0]}"
k="${out[1]}"
sha="${out[-1]}"
sha="${sha%% *}"
[[ -z "$sha" ]] && continue
if [[ "$k" == 'ctrl-d' ]]; then
git diff $sha
elif [[ "$k" == 'ctrl-b' ]]; then
git stash branch "stash-$sha" $sha
break;
else
git stash show -p $sha
fi
done
}
答案 16 :(得分:1)
在这里晚了聚会,但是如果使用VSCode,一种快速的方法是打开命令面板(CTRL / CMD + SHIFT + P)并键入“ Pop Stash”,您将可以检索到按名称隐藏,无需使用git CLI
答案 17 :(得分:1)
在我的鱼壳中
function gsap
git stash list | grep ": $argv" | tr -dc '0-9' | xargs git stash apply
end
使用
gsap name_of_stash
答案 18 :(得分:1)
git stash apply
还可以与stash@{0}
以外的其他引用一起使用。因此,您可以使用普通的标签来获得一个永久名称。这还有一个优点,就是您不会偶然git stash drop
或git stash pop
。
因此,您可以像这样定义别名pstash
(又称“持久存储”):
git config --global alias.pstash '!f(){ git stash && git tag "$1" stash && git stash drop; }; f'
现在您可以创建带标签的存储区:
git pstash x-important-stuff
,show
和apply
再次照常进行:
git stash show x-important-stuff
git stash apply x-important-stuff
答案 19 :(得分:0)
那呢?
=> true
答案 20 :(得分:0)
我认为没有办法用它的名字git pop stash。
我已经创建了一个执行此操作的bash函数。
#!/bin/bash
function gstashpop {
IFS="
"
[ -z "$1" ] && { echo "provide a stash name"; return; }
index=$(git stash list | grep -e ': '"$1"'$' | cut -f1 -d:)
[ "" == "$index" ] && { echo "stash name $1 not found"; return; }
git stash apply "$index"
}
用法示例:
[~/code/site] on master*
$ git stash push -m"here the stash name"
Saved working directory and index state On master: here the stash name
[~/code/site] on master
$ git stash list
stash@{0}: On master: here the stash name
[~/code/site] on master
$ gstashpop "here the stash name"
希望对您有帮助!
答案 21 :(得分:-2)
这是我做的一个快速设置,对我有用,希望它也适合你:
假设我的 package.json 项目文件中有一个自定义/本地脚本,我不想推送到远程仓库
{
// ... package.json stuff
"scripts": {
"custom": "ts-node a_ts_test_file.ts"
}
}
所以当我想推送我的分支或类似的东西时,我决定隐藏这个更改,并在我的下一个“git push”之前弹出存储。
所以……
# dev is the "stash tag"
# To stash current working directory
git config --global alias.sh "stash -m 'dev'"
~.bashrz
或 ~.zshrc
,添加以下别名:# Apply stash "tagged" $(X) where X is substring of "git stash list" output filtered by output that contains "dev".
# I didn't use git stash apply because "dev" tag isn't unique, so it's a need to pop the stash and ensure to create a new one alias set on first step
alias gitsh="git stash pop $(git stash list | grep 'dev' | cut -d ':' -f 1) || echo 'nope'"
使用标签“dev”推送您的工作目录:git sh
要从标记为“dev”的 stash 中提取您的 stash 更改:sitsh
(这是我在五分钟内制作的一个小脚本,对我有用,如果失败......修复它!?)