还记得我刚开始用git,还没理解rebase和merge的区别时,就看到队友童鞋飞一样地打命令,几秒钟把事情搞定了,然后在我还没看清楚他干了啥就清理了界面😂(这货有强迫症)。那时起,我开始意识到漂亮的GUI不一定有打命令快捷方便。
这篇我想分享一些我感觉很好用的方法,包括:
- git命令 – 建议通过
git --help
来查看更多的细节和选项 - Oh-my-zsh的快捷命令 – 这里有完整的Cheatsheet
- VSCode扩展插件
开始工作之前
将仓库克隆到本地
大部分时候只需要将git网站提供的clone命令复制黏贴就好,或者用命令:
bash
git clone <git_url> [目标地址]
用Oh-my-zsh可以更为简短:
bash
gcl <git_url> [目标地址]
Js中文网 – 全球前端挚爱的技术成长平台 www.javascriptC.com
Javascript中文网是以前端进阶资源教程分享为主的专业网站,包括:前端教程、JavaScript资讯、大厂面试题、typescript教程、程序人生、React.js源码解读、Vue3.js技术揭秘等,以帮助开发者成长为愿景的社区
并且它还包括了一个递归clone所有submodule的选项。
不过现在我更喜欢用VSCode的git命令工具来clone,这样就可以顺便打开新clone的仓库开始工作:
- Mac用
command
+shift
+p
,Windows用ctrl
+shift
+p
打开命令面板,输入git
来找到Git: Clone
-
粘贴仓库地址:
如果是github的仓库可以直接用”Clone from Github”功能(需要github账号登陆)。
-
选择目的地址:
-
克隆完成后,右下角弹窗会提示打开仓库:
切换到某个分支
我通常用命令行加tab
自动完成分支名来切换自己的分支:
bash
git checkout <分支名>
// In Oh-my-zsh
gco <分支名>
需要查看别人分支而我不熟悉分支命名的时候,就用VSCode git扩展在左下角状态条上放的分支切换入口:
点击后会弹出命令行选择分支:
![VSCode status bar – switch git branch]
创建新分支
新分支的创建只需加上-b
选项:
bash
git checkout -b <分支名>
// Oh-my-zsh:
gco -b <分支名>
分支重命名
有时候我不小心打了错别字或者有更好的名字,就用以下方式重命名:
bash
git branch -m <新名字>
// Oh-my-zsh:
gb -m <新名字>
查看分支状态
如果一个分支已经推送到远端,并且存在有多人协作、或是一个人用多设备(公司电脑和家里电脑)写代码,那时不时查看一下现在分支状态是个不错的习惯。这样可以避免因为没有基于最新代码开始工作而导致的一些麻烦。
命令:
bash
git fetch
git status
// Oh-my-zsh:
gf
gst
然后就会打印类似这样的信息:
有时候感觉这信息太简单了,不够清晰。那我就会查看git历史。大多数时候只需要最基本的命令就行了:
bash
git log
不过这命令提供了不少有意思的选项(说实话太多了记不住啊),比如--stat
会显示变化的文件, --graph
会画个丑丑的分支图, --oneline
把每个commit的信息压缩成一行显示……很多都太长了,还是用Oh-my-zsh别名吧,比如:
bash
glg // git log --stat
glgg // git log --graph
glo // git log --oneline --decorate
保持分支最新
如果我的分支没有任何修改,但git status
告诉我这个分支上有更新:
这时只需要用命令:
bash
git pull
// Oh-my-zsh
gl
来更新本地的分支。
如果不巧远端分支有更新的话,会稍稍麻烦一些。我们会在稍后的”解决冲突”部分作详细讨论。
完成并提交修改
提交前验证一下自己的改动
在提交代码前,我通常会再看一眼自己的改动来降低提交不必要的代码(比如测试用的console.log)和错误的几率。这时就感到VSCode自带的git diff非常好使:
点击“刷新”图标来显示更新,然后可以点击“树状列表”图标切换为更清晰的目录,点击其中的文件会显示非常容易看清楚改动的比较窗口。
提交改动
验证完毕后,在这个“SOURCE CONTROL”里可顺便选择这次需要提交的文件(点文件或文件夹右侧的➕号):
再输入适当的提交信息,点击✅图标提交。
然而这儿有个比较麻烦的地方是,提交经常会因为配置了commit hook样式验证、type类型验证而失败,并且失败后在VSCode OUTPUT面板打印的错误信息不如直接在命令行运行时打印的好阅读。因此我更喜欢命令行提交:
bash
git commit -m 'My commit message'
// Oh-my-zsh
gc -m 'My commit message'
如果想跳过手动stage文件,直接提交所有改动,则可以加-a
选项:
bash
git commit -am 'My commit message'
// Oh-my-zsh
gc -am 'My commit message'
// 或
gcam 'My commit message'
注意-a
选项时不会包括新创建,以前没有提交过的文件的。这时候需要多加一步:
bash
// 把所有当前目录下的文件都stage:
git add .
// Oh-my-zsh:
ga .
// 如果就想把所有仓库下的更改加入也可以这样:
git add --all
// Oh-my-zsh:
gaa
修改提交信息
同分支名,有时发现拼写错误或漏加了一些文件。那我就通过以下命令修改:
bash
git commit --a
// Oh-my-zsh
gc --a
把修改推送到远端
如果推送的是个新分支,或是从来没设置过远端上游分支的话,推荐使用-u
设置上游:
bash
git push -u origin <分支名>
// Oh-my-zsh:
ggp -u
然后就可以在查看分支状态时看到本地分支跟远端分支的差异(就像在“查看分支状态”一节中提到的一样)。并且下次推送的时候就不再需要这样的操作了:
bash
git push
// Oh-my-zsh:
ggp
解决冲突
第一选项是rebase
当分支的修改量不大的时候,rebase
是我的第一选项。因为它会确保我的更新是建立在最新代码上的,避免很多问题。
rebase上游可以通过git pull
实现:
bash
git pull --rebase
// Oh-my-zsh:
ggu
不过我更多情况下会rebase最新的主分支:
bash
git rebase origin/master
// Oh-my-zsh:
grb origin/master
// 或
grbm
指定从origin
这样的上游会确保git从远端拉取最新的代码再rebase。
Rebase或merge之前考虑先压缩一下commits
有时我在开发中提交了多个小改动,这些提交在主分支中没啥存在意义,或者存在一些对某个模块的反复修改。然而这些commits会在我试图rebase或者回过头来查看修改的缘由时造成一定的麻烦,因此我会考虑在合并代码前将这些commits压缩成一个。
如果在自己的分支,我只想简单地把所有此次修改压缩成1个commit的话,我就:
- 通过合并请求看一下有多少commits(像这个),或在git log里查看 (参照查看分支状态 一节)
git reset --soft HEAD~<commit数>
或git reset --soft <commit_SHA>
(注意这儿的commit SHA是需要保留的最新的commit SHA)来把那些commits移除,所有改动恢复为staged状态 – 需要注意的是reset一个合并分支的commit会同时reset所有被合并的commits,因此这里的commit数量跟数出来的可能不同。gc -m <new_commit_message>
来创新一个新的commitgp -f
– 如果这些提交之前已经被推送到远端,那这时因为我们修改了原本的git历史树结构,所以需要加-f
来强制推送。这其实挺危险的,请确保这样做的安全性。
如果需要保留原有的消息,和作者的信息。那就考虑用git的交互模式:
git rebase -i HEADER~<commit_counts>
或git rebase -i <commit_SHA>
-
然后它会打开命令行编辑器如
vi
:根据提示信息修改每行commit消息头部的操作命令词(打开时候都是
pick
)。 假设这边我就把3个提交合成1个,那我需要保持第一个commit为pick
,并修改剩余两个为squash
或s
。 -
保存退出。修改成功则会显示如下确认信息编辑界面:
-
再度保存退出就完成了。
比较复杂的情况下选用merge
如果想更新一个共享分支(多人基于这个分支上开发),rebase就不是一个很好的选项,因为它会导致所有基于它的其他分支都遇到很严重的冲突。
还有一种情况是在开发一个比较大的项目,为了更好地控制版本,特意分了多次提交。这时用rebase就会遇到需要多次解决代码冲突,而我通常解决2个冲突之后就开始迷失自我不知道这是哪儿了。
这时用merge
比较好:
如果只是要合并上游分支的话git pull
就可以了:
bash
git pull
// Oh-my-zsh:
gl
更多情况下我需要合并主分支, 那就用:
bash
git merge origin/master
// Oh-my-zsh:
gm origin/master
解决冲突
一想到解决冲突就想到Webstorm那个超赞的冲突解决工具。但是,我几年前还是抛弃了Webstorm,因为它特别能把我的内存和CPU吃光,系统异常卡顿,然后我一去不复返。这边还因为没有能媲美的工具导致我有个比较长的适应期,现在感觉VSCode自带的git工具也挺好的。
合并或rebase的时候,如果遇到冲突,切换到“SOURCE CONTROL”面板点击“刷新”图标就能看到用“C”标注出来的冲突文件:
选择打开这些文件,然后就在编辑器里看到高亮显示和 Current Change
、Incoming Change
这些选项。讲真,这比通常git工具显示的ours
和 theirs
要好理解多了。
这儿不太方便的地方是它是上下显示的,而不是像Webstorm这样左右比较的,所以在冲突区域大的时候就感觉不太好使了。这儿我暂时还没有更好的办法,也不想因为这个较少遇到的情况单独装个软件,先就这样用着吧。
为啥代码写成这样
当有地方坏了或看起来很奇怪,这时有意义的提交信息和可追溯的git历史树就显得特别有用。这里我超爱用VSCode的GitLens插件:
它提供了特别多的功能来帮我们查看历史,不过我几乎只用 LINE HISTORY
和 FILE HISTORY
来帮我了解这块代码是怎样一步步变成现在的模样的:
清理不需要的分支
清理远端的分支记录
如果有在本地打开一些远端分支,在这些分支被合并之后,本地关于这个分支的记录是不会自动清理的。大多情况下这没什么,就让它在那好了。但在大型代码仓库有一定几率遇到奇怪的问题而导致无法做任何git操作的麻烦。因此我会隔段时间清理一下:
bash
git remote prune origin
// 或者可以用fetch来跑:
git fetch --all --prune
// Oh-my-zsh会比较方便:
gfa
本地分支的清理
本地分支清理起来比较麻烦。我有很长一段时间都只依靠像这样手动删:
bash
git branch | cat // 打印出所有本地分支
git branch -D <分支名>
后来我发现Oh-my-zsh的一个快捷命令,它可以删掉所有已经被合并到master
/develop
/dev
的分支:
bash
gbda
作者:蛋黄酱
链接:https://juejin.im/post/6887796314411646989
看完两件小事
如果你觉得这篇文章对你挺有启发,我想请你帮我两个小忙:
- 把这篇文章分享给你的朋友 / 交流群,让更多的人看到,一起进步,一起成长!
- 关注公众号 「画漫画的程序员」,公众号后台回复「资源」 免费领取我精心整理的前端进阶资源教程
本文著作权归作者所有,如若转载,请注明出处
转载请注明:文章转载自「 Js中文网 · 前端进阶资源教程 」https://www.javascriptc.com