git中比较有用的两个命令, git stash 和 git worktree, 你值得了解一下
部门从SVN签到了Git, 总算跟上了潮流的脚后跟. 其实从技术的角度来说, SVN没有那么烂. 但是从当今的角度来说, Git已经代表潮流, SVN已经没落并将持续没落下去, 继续把宝贵的时间投入到SVN这种注定没落的技术上, 实在是得不偿失.
不信? 看下google trends:
全球2004年至今趋势图(蓝线git, 红线SVN):
中国2004年至今趋势图(蓝线git, 红线SVN):
SVN已经注定被放入历史的记忆箱, 就像曾经的perl和pascal, 不会消失, 但会渐渐淡化, 直到成为老一辈程序员心中的记忆和口中的谈资.
SVN有个缺点, 代码不方便本地保存, 我一般都是通过文件夹右键zip来保存本地修改. 相比之下, Git的本地保存功能很强大, 十分喜欢.
关于本地保存的优点, 讲个故事:
有个同事, 曾经coding两天在周五开发出一版UI, 拿给设计看, 设计不满意, 就换了一种设计风格, 让同事再实现一次. 同事周六周日加班了两天, 把新的设计实现了, 拿给设计看, 结果设计说:”好像, 好像上一版更好看, 还是用上一版吧”. But, 同事的上一版代码没有保存, 只能凭着记忆把上一版代码重新撸出来, 不知浪费多少时间和脑细胞.
SVN的保存都是push到中央代码库, 保存很重, 同事觉得没完成的东西不应该push保存. 所以…
相比之下, Git的保存就很轻, 可以先commit提交到本地保存, 或者stash保存. 等到开发完成后, 再push到远端. 甚至, push到远端的, 你还可以通过push -f覆盖掉远端的代码(只建议强制push自己的库, push -f master会死人的). 修改本地提交记录和远程提交记录也不在话下, 比如git commit --amend
修改最近一次提交记录, git rebase -i "commit id"^ & git push -f
修改本地提交记录并强制推送到远程.
git的本地保存中, 我觉得最好用的是git stash.
当你在项目的一部分上已经工作一段时间后, 所有东西都进入了混乱的状态, 而这时你想要切换到另一个分支做一点别的事情. 问题是, 你不想仅仅因为过会儿回到这一点而为做了一半的工作创建一次提交. 这时, 你可以选择stash.
当你git pull代码时, 提示代码冲突, 拉下来可能会覆盖本地代码. 这时, 你可以先stash代码, pull代码后, 恢复stash的内容. 就算合并失败, 还可以hard reset, 因为代码在stash中还有一份, 不虚.
git stash 命令如下, 但是推荐使用sourcetree界面操作stash, 因为查看修改处比较方便, 而且不用记git又臭又长的命令.
_git stash_ list
_git stash_ show
_git stash_ drop -q|--quiet
_git stash_ ( pop | apply ) --index
_git stash_ branch
_git stash_ [push -p|--patch-k|--no-keep-index] -q|--quiet
-u|--include-untracked -m|--message
--]
_git stash_ clear
_git stash_ create
_git stash_ store -m|--message
SourceTree UI操作stash:
SourceTree贴心的展示了stash分支和stash信息,超赞?,当你stash五次以上,会爱死这个功能。
点击某次stash即可查看这个stash存的内容, 右键应用或者删除stash.
最初使用时, Git的checkout使用体验很不如SVN. 在SVN下, 习惯在branch下新建一个分支, 拉下来进行开发, 开发完成后把代码push上去. 这样不同的开发分支A和B是在不同的文件夹下的, 不会相互影响. 但是在Git下, checkout的分支还是在同一个目录, 这样就很不方便代码管理.
比如featureA在开发中, featureB开发完成在测试中. 你正在featureA上开发, 测试忽然提了一个bug, 你需要checkout到featureB去修复. 修复后checkout回featureA, 但是你发现gradle需要同步, java需要重新编译, 你需要10分钟甚至更久才能恢复到你原来的代码状态. 这样的bug来几次, 你就要疯了, 然后觉得git clone代码, 放在不同的文件夹下是个挺好的主意. 需要checkout时, 就去不同的文件夹checkout, 相互不影响挺好.
幸好, git提供了worktree命令, 就是为了解决这种需要checkout多个分支的情况.
git worktree命令如下:
_git worktree add_ -f --checkout -b
_git worktree list_ --porcelain
_git worktree lock_ --reason
_git worktree move_
_git worktree prune_ -n --expire
_git worktree remove_ -f
_git worktree unlock_
一个例子:
使用 git worktree add …/locat_dir brach_name检出分支到指定文件夹.
这样在local_dir里的修改, 在主git库里是没有反应的, 也就不用担心一个分支的修改影响另外一个分支. 不用担心, 这个检出的分支仍然是git托管的, 你可以正常的commit/push/pull/merge/rebase, 并且这个分支的stash是显示在git主库里的.
学会了git stash和git worktree后, 你的Git功力大涨不少.
不信? 你看下面的cheatsheet都没有这两个命令: