Git:stash 命令

Oct 23, 2021

目录


ref: https://git-scm.com/docs/git-stash


命令


 1git stash list [<log-options>]
 2git stash show [-u|--include-untracked|--only-untracked] [<diff-options>] [<stash>]
 3git stash drop [-q|--quiet] [<stash>]
 4git stash ( pop | apply ) [--index] [-q|--quiet] [<stash>]
 5git stash branch <branchname> [<stash>]
 6git stash [push [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]
 7	     [-u|--include-untracked] [-a|--all] [-m|--message <message>]
 8	     [--pathspec-from-file=<file> [--pathspec-file-nul]]
 9	     [--] [<pathspec>…​]]
10git stash clear
11git stash create [<message>]
12git stash store [-m|--message <message>] [-q|--quiet] <commit>

git-stash - Stash the changes in a dirty working directory away


描述


当您想记录当前工作目录和索引的状态,但又想返回到一个干净的工作目录的状态时,请使用 git stash。 该命令会保存您的本地修改,并将工作目录恢复到和 HEAD 相同的状态。

git stash list 用于列举你当前所有存放起来的修改

git stash show 用于查看特定信息

git stash apply 用户恢复之前存放起来的修改

直接使用 git stash 不带是任何参数,等同于使用 git stash push

创建的最新的 stash 存储在 refs/stash 中。 旧的 stash 可以在 reflog 中通过 reflog 语法查找(stash@{0} 表示最新创建的 stash,stash@{1} 代表第二个 stash)。 也可以通过仅仅指定 stash index 的方式查找 (n 代表 stash@{n})


命令


push

1push [-p|--patch] [-k|--[no-]keep-index] [-u|--include-untracked] [-a|--all] 
2    [-q|--quiet] [-m|--message <message>] [--pathspec-from-file=<file> 
3    [--pathspec-file-nul]] [--] [<pathspec>...]

将您的本地修改保存到一个新的 stash entry,并将它们(工作目录和索引)回滚到 HEAD 相同的状态。

<message> 选项是可选的,指定一个描述信息。

为了快速创建快照,可以省略 “push”。

save

1save [-p|--patch] [-k|--[no-]keep-index] [-u|--include-untracked] [-a|--all] 
2    [-q|--quiet] [<message>]

已废弃

list

1list [<log-options>]

列举当前存在的 stash entry。 输出信息中包含名称, 分支名称,和一个简短的描述信息

stash@{0}: WIP on submit: 6ebd0e2... Update git-stash documentation
stash@{1}: On master: 9cc0589... Add git-stash

show

1show [-u|--include-untracked|--only-untracked] [<diff-options>] [<stash>]

显示当前 stash entry 中保存的版本与创建当前 stash entry 时的 commit 版本的不同(diff)。 默认情况下此命令只显示 diffstat,但是可以使用 git diff 所接受的任何合法的格式来显示不同。

如果没有指定<diff-option>,默认使用 state.showStatstash.showPatch配置。

pop

1pop [--index] [-q|--quiet] [<stash>]

从 stash list 中移除单个 stash, 然后将该 stash 应用到当前工作目录。 是 git stash push 的逆运算。 要求此时的工作目录必须和索引匹配。

如果发生了冲突,这个命令会失败。 此时,你需要手动解决冲突,然后使用 git stash drop 手动将当前 stash 移除。

apply

1apply [--index] [-q|--quiet] [<stash>]

pop 类似,区别是此命令不会从 stash list 中移除当前 stash。

branch

1branch <branchname> [<stash>]

Creates and checks out a new branch named <branchname> starting from the commit at which the <stash> was originally created, applies the changes recorded in <stash> to the new working tree and index. If that succeeds, and <stash> is a reference of the form stash@{<revision>}, it then drops the <stash>.

This is useful if the branch on which you ran git stash push has changed enough that git stash apply fails due to conflicts. Since the stash entry is applied on top of the commit that was HEAD at the time git stash was run, it restores the originally stashed state with no conflicts.

clear

1clear

移除所有 stash entry。

drop

1drop [-q|--quiet] [<stash>]

从 stash list 中移除指定 stash entry。

store

1store

将你通过 git stash create 创建的 stash 保存到 stash ref 中,并更新 stash reflog。

这对脚本是有用的。它可能不是您想要使用的命令;参见上面的 “push”。


选项


  • -a, --all

仅适用于 pushsave 命令

所有被忽略(ignored)和未被跟踪(untracked)的文件也被保存,然后用 git clean 清理。

  • -u, --include-untrached, --no-include-untracked

当在 pushsave 命令中使用,所以未被跟踪的文件也会被保存,然后用 git clean 清理。

当在 show 命令中使用,未被跟踪的文件也会被显示出来

  • --only-untracked

仅适用于 show 命令

仅仅显示未被跟踪的文件。

  • --index

仅适用于 popapply 命令

不仅要恢复工作目录的变化,还要恢复索引的变化。 然而,这个命令可能会失败,如果产生了冲突。

  • -k, --keep-index, --no-keep-index

仅适用于 pushsave 命令

已经添加到索引中的所有更改都保持不变。

  • -p, --patch

仅适用于 pushsave 命令

交互式地从 HEAD 和要存储的工作目录之间的差异中选择想要保存的内容。

此选项隐含的使用 --keep-index, 你可以使用 --no-keep-index 覆盖这个默认行为。

  • --pathspec-from-file=<file>

仅适用于 push 命令

Pathspec is passed in <file> instead of commandline args. If <file> is exactly - then standard input is used. Pathspec elements are separated by LF or CR/LF. Pathspec elements can be quoted as explained for the configuration variable core.quotePath (see git-config[1]). See also –pathspec-file-nul and global –literal-pathspecs.

  • --pathspec-file-nul

仅适用于 push 命令

仅仅在和 pathspec-from-file 搭配使用才有意义。 Pathspec 元素通过 NUL 字符分隔,其他字符被当做正常字符处理(包括 newline 和 quotes)

  • -q, --quiet

适用于 apply, drop, pop, push, save, store 命令

不输出回显消息

  • --

仅适用于 push 命令

为了消除歧义,将 pathspec 与选项分离

  • <stash>

适用于 apply, branch, drop, pop, show 命令

指定一个 stash 的引用 (stash@{<version>})。 如果不指定,默认使用最新的 stash (stash@{0})


讨论


stash 被表示为一个 commit。 它记录了工作目录的状态,以创建时 HEAD 所指向的 commit 为他的第一个父,他的第二个父记录了创建 stashh 时 索引的状态,并且第二个父是 HEAD 的子。

1       .----W
2      /    /
3-----H----I

其中 H 表示 HEADI 记录了索引的状态,W记录了工作目录的状态。


例子


  • Pulling into a dirty tree

当你正在做本地修改期间,你得知远程有新的修改,这些修改可能和你的修改相关。 如果你本地修改和远程修改没有冲突的时候,你可以通过 git pull 直接获取远程修改。

然而,有可能你的修改和远程修改冲突,此时 git pull 将不适用于这种情况。 此时,你需要先备份你的修改,然后执行 pull 操作,然后将备份的修改恢复到更新后的内容上。 就像这样:

1git pull
2    ...
3file foobar not up to date, cannot merge.
4
5git stash
6git pull
7git stash pop
  • Interrupted workflow

当你正在做本地修改期间,你的 boss 跑来要你立即去修另外一个问题。 通常情况下,你应该将你的修改提交到一个临时分支中,然后到原始分支中去修复紧急的问题,就像这样:

1# ... hack hack hack ...
2git switch -c my_wip
3git commit -a -m "WIP"
4git switch master
5edit emergency fix
6git commit -a -m "Fix in a hurry"
7git switch my_wip
8git reset --soft HEAD^
9# ... continue hacking ...

你可以通过 git stash 来让事情更简单,就像这样:

1# ... hack hack hack ...
2git stash
3edit emergency fix
4git commit -a -m "Fix in a hurry"
5git stash pop
6# ... continue hacking ...
  • Testing partial commits

你可以使用 git stash push --keep-index 将两个或更多的提交排除在工作目录之外,然后分别测试测试,然后提交:

1# ... hack hack hack ...
2git add --patch foo            # add just first part to the index
3git stash push --keep-index    # save all other changes to the stash
4edit/build/test first part
5git commit -m 'First part'     # commit fully tested change
6git stash pop                  # prepare to work on all other changes
7# ... repeat above five steps until one commit remains ...
8edit/build/test remaining parts
9git commit foo -m 'Remaining parts'
  • Recovering stash entries that were cleared/dropped erroneously

如果你不小心删除了一些 stash entry, 这通常是无法通过正常方法恢复的。 然后,你可以通过以下方法来尝试找回你误删的stash entry:

1git fsck --unreachable |
2grep commit | cut -d\  -f3 |
3xargs git log --merges --no-walk --grep=WIP

END!!!


Tags