Git Stash 提高开发效率
我要先来吐嘈下 Boss 的产品的用户体验问题,大家看下下图的红圈圈。
Boss 吐槽看完没之后,是不是感觉挺好的,不想看这个职位可以直接通过这个叉叉关掉,功能是没问题,但是当你用的时候你就会发现问题了,无论你用你的大猪蹄子还是小鸡爪子去点这个叉叉,很容易就直接点进职位详情去了。
对于我这种强迫症的人来讲,点几次就头皮发麻了。
这里我想说一下产品经理的职位素养问题,我认为除了稳定输出功能完善的原型图,还有一个不能忽视的就是产品自己做的产品,一定要自己去用自己去体验,去思考,体验一百遍一千遍的那种,这样就不会在产品中出现奇怪的设计,然后还觉得自己这个功能做的很好。
毕竟,好不好,用过 N 次才知道。
目录
- git stash 的作用
- stash 在 暂存区和工作区的表现
- stash 已暂存和未暂存的更改
- Git 中未被追踪和已被追踪的文件
- stash 跟踪和未跟踪的文件
- stash 被 Git 忽略的文件
- 使用暂存的更改
- 查看暂存列表
- 如何添加暂存的描述信息
- 查看 stash 暂存的内容
- Stash 暂存单个文件
- 从 stash 取出单个文件来使用
- 从 Stash 创建一个分支
- 删除暂存
- 高级用法自动暂存
- 命令汇总
- 总结
前言
作为一名技术人员,我们知道,我们的工作经常会被要求实现更重要的功能或修复一些紧急的 bug,然后工作节奏就被无情的打断。
这种情况下我们面临着一个难题,当前开发任务还没完成只进行了部分,而我并没有准备好提交更改。
如果你对分支比较熟悉,马上能反应过来说,我可以通过分支对当前修改进行备份,OK,这没问题。
但是,Git 提供了一个命令来轻松处理这种情况。
认识 git stash 命令
运行 git stash 命令,就像是使用我们的文本编辑器的剪切功能,stash 会暂时保存已被 Git 追踪你最新的更改,把当前工作目录撤销到更改之前的状态,这样你就可以从头开始编写新功能。
如果需要,你可以决定随时把暂存的更改取出来并重新应用它们,当我们需要快速切换上下文去处理其他事情,而不丢失未完成的工作时,这会非常的方便。
但是请记住,stash 位于您的存储库的本地,当你在推送更改的时候,它是不会一起传输到远程服务器的。
问题:现在假如我们正在开发一个新功能,但是此时遇到一个紧急的 bug 需要修复或者开发任务的优先级发生了改变。
接下来就是我工作遇见这种情况,我的应对步骤。
- 首先使用
git status
命令检查已进行了多少更改:
- 接下里使用
git stash
命令存储更改:
-
新功能或者是修复 bug 的过程
-
当步骤三完成之后,我们就可以回到我们刚刚 stash 的 master 分支,然后通过
git stash pop
把暂存剪切出来。
Stash 在暂存区和工作区的表现
- 更改了文件,还没有通过 add 把更改的文件由工作区添加到暂存区:
当我们查看本地状态的时候 git 告诉我们:Changes not staged for commit
- 接下来我们查看已经通过 add 把本地最新的修改添加到暂存区的情况
通过对比我们发现,没有添加到暂存给的提示信息是红色的,已经添加到暂存给的提示信息就是绿色的。
- 同一个文件暂存了一部分,然后又更改了一部分
stash 暂存工作区和暂存区的更改
通过上面的学习,现在我们已经了解了暂存区和非暂存区(工作区)更改是什么,接下来就是通过 stash 来暂存他们了。
先说结论:通过 git stash 命令可以暂时保存暂存区和非暂存区(工作区)的更改,当通过 git stash pop / git stash apply
重新取出它们后,所有更改都变为未暂存:
Git 中未被追踪和已被追踪的文件
现在我们知道 git stash
能够处理暂存区和非暂存区(工作区)的更改,我们需要知道它如何处理未跟踪和已跟踪的文件。
但在回答这个问题之前,让我们先了解一下 Git 中的未跟踪文件和已跟踪文件是什么。
未跟踪的文件
默认情况下,当您在工作目录中创建新文件时,它将显示为未跟踪,因为它不在 Git 版本系统中。
例如我创建了一个新的 App.vue 组件并执行了 git status 命令:
Git 未跟踪文件Git 通过以下消息告诉我们该文件未被跟踪:Untracked files。
跟踪文件
跟踪文件是下次执行 git commit 命令时应该提交的文件。
要将文件从未跟踪状态移动到已跟踪状态,运行 git add 命令即可。
跟踪的文件通常用绿色标记:
Git 跟踪文件stash 暂存跟踪和未跟踪的文件
默认情况下 git stash
并不能暂存未跟踪文件:
当我们试图存储一个未跟踪的文件时,Git 提示我们:(No local changes to save)本地没有更改需要保存。
Git 无法跟踪未存储在 Git 中的文件,那我们可以怎么来解决呢?
- 通过
git add
添加到 git 的暂存区 - git stash -u,-u 是
--include-untracked
的缩写。
因为我们要暂存未被追踪的文件,可见 git stash -u
更加好用。
stash 被 Git 忽略的文件
git stash
是否适用于被忽略的文件(被忽略的文件是在 .gitignore 这个特殊文件中跟踪的文件)。
很显然默认情况下 git stash 不能暂存被忽略的文件,但我们可以通过使用(-a或 -all)来完成达到目的。
让我们把 App.vue
添加到 .gitignore
中:
// ..
App.vue
并验证它确实被忽略了,git status
命令显示我们只更改了.gitignore
文件,但它没有将 App.vue
显示为未跟踪的文件):
尝试使用 git stash -a
命令存储被忽略的文件,并在运行 git stash pop
后看到它已被重新应用,即使这个文件被 Git 忽略。
使用暂存的更改
可任选下面两个命令来使用暂存的的更改:
-
git stash apply
应用最新的 stash 更改,如果想使用指定的 stash ,可以使用命令git stash apply stash@{<index>}
。
要么
-
git stash pop
应用最新的 stash 更改 -
git stash pop stash@{<index>}
应用指定的 stash 更改
pop 和 apply 都做同样的事情,但它们之间有一个重要的区别,执行 pop 命令,暂存被使用,然后列表里面的暂存会被删除,执行 apply 命令,暂存被使用,然后列表里面的暂存依然保留。
PS:我一般都是使用 pop ,基本不使用 apply,因为暂存本来就是用完即可删除的,不删的话,暂存列表过多并不清晰。
查看暂存列表
在项目中我们是可以使用多次 stash 来暂存不同时间的不同更改的,这时会有一个暂存列表,那么如何查看这个暂存列表呢?
git stash list
需要注意的是每个暂存都会被标记为 WIP(Work In Progress) 和创建一个 commit 信息。
通过 git stash list
我们只能查看我们暂存的个数,并不能查看具体暂存的信息,这样我们很难弄懂我们到底做了哪些更改。所以必要的描述信息是很重要的,这是接下里的内容。
如何添加暂存的描述信息
我们可以通过如下命令来添加暂存的描述信息:
git stash save "<message>"
现在我来对文件做一个小改动,然后自定义描述让它隐藏起来,让我来演示下:
git stash message现在我们看到它是有自定义描述的,这样我们就能更准确的看到此次 stash 具体是干啥的了。
查看 stash 暂存的内容
有时需要查看暂存的详细信息,以确这个暂存是我目前需要的。
这可以通过以下命令完成:
-
git stash show
查看最近一次的 stash 信息 -
git stash show stash@{<index>}
查看特定暂存的更改。
接下来让我们快速检查列表中的每个 stash 都做了哪些更改,先通过 git stash list 查看暂存列表:
通过 git stash list 查看暂存列表查看最新的暂存更改 git stash show
:
查看指定的暂存更改 git stash show stash@{2}
通过 save message 的信息,我们找到 stash 的 index 然后通过 git show 来查看哪些改变这时没问题的,但是有时候能查看到具体的文件内容会更加的直观。
于是如果我们想知道哪一行代码做了变动怎么查看呢?这时我们可以添加 -p
或 --patch
标志:
演示 一下:
查看最新暂存更改 git stash show -p
:
查看指定暂存更改 git stash show stash@{2} -p
:
Stash 暂存单个文件
现在我们看到 Stash 暂存的是当前所有更改,但有时,您可能不想隐藏所有更改,而只想存储最重要的几个或单个的更改。
这时我们可以强制 Git 遍历所有更改的文件,通过 git stash
命令加 -p(或--patch)
标志来暂存特定的文件:
git stash -p
接下来我来演示下,我更改了两个文件,但只想暂存一个被更改的文件:
我暂存了 reducer.ts
文件,可以通过 git stash show -p
看下暂存状态:
在通过 git status
查看更改文件的情况:
看到这你是不是发现 -p
标志好厉害,其实,工作中还有一个地方用到了它,就是 git add 的时候,一般我们 git add 是添加整个文件,如果想提交文件对应更改行的内容怎么办呢?
没错通过 git add -p
来实现,这里按下不表,感兴趣的自己去学习下使用。
从 stash 取出单个文件来使用
一种很不常见的情况下,就是我们 stash 暂存中可能有部分文件是旧的,我们只想应用暂存中的一个或几个特定文件。
这时,可以使用以下命令:
-
git checkout stash <file>
最新暂存的特定文件 -
git checkout stash@{<index>} <file>
指定暂存中的特定文件
让我们看看它的实际效果:
取出最新暂存的特定文件从 Stash 创建一个分支
可以从 stash 创建一个分支,如果在创建暂存期间修改了相同的文件,并尝试取出暂存应用更改时,会发生冲突,而创建一个分支这将非常有用,其实很鸡肋,我不应用暂存不就行了。
执行此操作的命令如下:
-
git stash branch <name>
从最新的暂存创建一个分支 -
git stash branch <name> stash@{<index>}
从特定的暂存创建一个分支
演示,根据最新的更改创建一个 stash-change 分支:
根据最新的更改创建一个 stash-change 分支删除暂存
有些暂存实在是用不到了,我们可以通过删除不必要的暂存,来保持项目暂存清单的清晰。
删除特定存储的命令:
-
git stash drop
删除最新的暂存 -
git stash drop stash@{<index>}
删除特定的暂存
一般是通过 git stash list
查看暂存目录,然后通过 git stash drop
或 git stash drop stash@{<index>}
删除那些不必要的暂存。
演示:
通过 git stash list
查看暂存列表:
通过 git stash drop stash@{0}
删除一个暂存:
最后,通过 git stash list
查看暂存列表,发现只有两个暂存了:
如果要从列表中删除所有的暂存,即清空暂存列表可以通过执行下面命令:
git stash clear
演示,清空暂存和无暂存情况下都没有提示,Git 这点不友好,
清空暂存高级用法自动暂存
当我们使用 rebase 时,必须保证有一个干净的工作目录,否则 Git 会抛出错误:
变基有几种方法可以解决这个问题:
- 做一次 commit,多了一次 commit 信息
- 放弃更改,改动的文件可能有用
- 手动暂存然后重新应用更改,多敲了两次命令。
- 最新更改备份到临时分支,多敲了好几个命令。
- 自动暂存然后应用更改,推荐 👍。
通过对比解决方案,最终我们选择自动方案,即 --autostash
命令实现。
使用此命令,更改将在 rebase 之前自动暂存并在动作完成之后重新应用:
autostash注意我们最后敲了 git stash list
查看暂存列表,列表为空,你会发现 autostash 的应用更改的策略是 pop,而不是 apply。
命令汇总
命令 | 作用 |
---|---|
git stash | 临时暂存工作目录的当前状态 |
git stash -u | 暂存未跟踪的文件更改 |
git stash -a | 暂存被 git 忽略的文件 |
git stash apply / git stash apply stash@{1} | 应用上次/给定暂存的更改 |
git stash pop / git stash pop stash@{1} | 从最后一个/给定的 stash 应用并这个暂存从 stash 列表中删除 |
git stash list | 列出暂存列表 |
git stash save "message" | 使用自定义描述本次暂存更改信息摘要 |
git stash show / git stash show stash@{1} | 查看上次/给定暂存中更改的文件 |
git stash show -p / git stash show stash@{1} -p | 查看最后/给定暂存中更改的代码行 |
git checkout stash path/to/file / git checkout stash@{1} path/to/file | 应用最后一次/给定的暂存中的单个文件 |
git stash -p | 强制 Git 遍历所有更改的文件并询问您是否要存储给定文件 |
git stash branch / git stash branch stash@{1} | 从最后一个/给定的暂存处创建一个分支 |
git stash drop / git stash drop stash@{1} | 删除最后/给定的暂存 |
git stash clear | 清空暂存列表 |
git rebase -i HEAD~2 --autostash | 在 rebase 之前自动暂存更改并在之后通过 pop 策略重新应用它们 |
总结
文章好长,终于结束了,恭喜,你完成了这个关于 git stash
命令及其使用方法的长篇故事。
此命令的工作方式就像剪贴板工具一样,它可以临时保存工作目录的当前状态,并撤消它,因此您可以随时的从新编写新功能,而且你还可以随时取出暂存中的更改。
当您需要快速切换上下文并处理其他事情而不丢失未完成的工作时,它非常有用。
希望你在日常的工作中常使用 git stash
命令来提高开发效率。