前言
git
是用来管理代码和工作流的强大工具,它以commit
为单位,低成本开辟分支等优势备受青睐.
在实际开发中,我们常常遇到一些复杂的应用场景,不单单是pull
,commit
,push
就能解决.下面我们通过引入git stash
的使用,来讨论在复杂情况下git
发挥的强大功能.
git stash 的作用
git stash
用于想要保存当前的修改,但是想回到之前最后一次提交的干净的工作仓库时进行的操作.git stash
将本地的修改保存起来,并且将当前代码切换到HEAD
提交上.
通过git stash
存储的修改列表,可以通过git stash list
查看.git stash show
用于校验,git stash apply
用于重新存储.直接执行git stash
等同于git stash save
.
最新的存储保存在refs/stash
中.老的存储可以通过相关的参数获得,例如stash@{0}
获取最新的存储,stash@{1}
获取次新.stash@{2.hour.ago}
获取两小时之前的.存储可以直接通过索引的位置来获得stash@{n}
.
git stash的概念理解
git stash
的每个存储单元在工作仓库中是通过commit
的形式由树结构展示的.它的根节点是HEAD
所在的提交.以下图标来表示stash
和branch
的关系.
H
是HEAD
提交.I
是存储单元的提交.W
是工作树中的提交.
应用举例
通过几个实际的示例来了解一下git stash
的强大.
开发到一半,同步远端代码
当你的开发进行到一半,但是代码还不想进行提交 ,然后需要同步去关联远端代码时.如果你本地的代码和远端代码没有冲突时,可以直接通过git pull
解决.但是如果可能发生冲突怎么办.直接git pull
会拒绝覆盖当前的修改.
遇到这种情况,需要先保存本地的代码,进行git pull
,然后再pop出本地代码:
git stash
git pull
git stash pop
工作流被打断,需要先做别的需求
当开发进行到一半,老板过来跟你说"线上有个bug,你现在给我改好,不然扣你鸡腿".当然,你可以开一个新的分支,把当前代码提交过去,回头再merge,具体代码如下
繁琐的工作流示例
# ... hack hack hack ...
git checkout -b my_wip
git commit -a -m "WIP"
git checkout master
edit emergency fix
git commit -a -m "Fix in a hurry"
git checkout my_wip
git reset --soft HEAD^
# ... continue hacking ...
我们可以通过git stash
来简化这个流程
正确姿势
# ... hack hack hack ...
git stash //保存开发到一半的代码
edit emergency fix
git commit -a -m "Fix in a hurry"
git stash pop //将代码追加到最新的提交之后
# ... continue hacking ...
提交特定文件
如果对多个文件做了修改,但是只想提交几个文件,或者想先暂时保存几个修改,测试其他文件的执行结果.可以通过git stash save --keep-index
来进行.
# ... hack hack hack ...
git add --patch foo //只将第一部分加入管理the index
git stash save --keep-index //将其余部分保存起来
edit/build/test first part
git commit -m 'First part' //提交全部的git管理中的代码
git stash pop //继续进行存储代码的工作
# ... repeat above five steps until one commit remains ...
edit/build/test remaining parts
git commit foo -m 'Remaining parts'
恢复被错误clear/drop
的存储
如果因为失误对存储仓库进行了clear
或者drop
操作,在一般机制下是不能恢复的.但是可以通过以下指令来获取仍在仓库中的,但是已经不可获取的存储列表
git fsck --unreachable |
grep commit | cut -d\ -f3 |
xargs git log --merges --no-walk --grep=WIP
git stash 的具体用法
git stash
通过在指令后添加其他的附件选项,实现复杂的定制化操作,下面我们来对具体用法进行讲解.
save, push
-
save [-p|--patch] [-k|--[no-]keep-index] [-u|--include-untracked] [-a|--all] [-q|--quiet] [<message>]
-
push [-p|--patch] [-k|--[no-]keep-index] [-u|--include-untracked] [-a|--all] [-q|--quiet] [-m|--message <message>] [--] [<pathspec>…]
save
和push
命令都可以用于存储修改.并且将git
的工作状态切回到HEAD
也就是上一次合法提交上.后面的<message>
是选填项.
如果给定具体的文件路径,git stash
只会处理路径下的文件.其他的文件不会被存储
--keep-index
(简写为-k
)只会存储为加入git
管理的文件
--include-untracked
为追踪的文件也会被缓存,当前的工作空间会被恢复为完全清空的状态.如果不使用--include-untracked
而是用--all
,那么除了未加入管理的文件,被git
忽略(ignore
)的文件也会被缓存.
--patch
命令可以让我们选择当前修改和HEAD
提交diff
部分.
list
list [<options>]
展示当前存储库中的存储单元列表.每个元素包含的信息有索引位置,存储时所在的分支,存储前的提交的描述.举例
stash@{0}: WIP on submit: 6ebd0e2... Update git-stash documentation
stash@{1}: On master: 9cc0589... Add git-stash
show
show [<stash>]
展示存储单元和最新提交的diff
结果.如果没有给定<stash>
参数时,会对比最新的存储单元.
pop
pop [--index] [-q|--quiet] [<stash>]
移除单个存储单元.和git stash save
的作用相反.
网友评论