和一个长期使用 IDE(eclipse)集成 git 进行代码版本管理的人交流项目,博文内容将采用类似《大话设计模式》的对话体进行,场景真实,有代入感。
正文部分前面是对方参照我写的 readme 搭建基于 vue-cli 的 demo 项目,安装 node 并通过 npm 安装项目依赖并本地启动项目等等,由于对方为后端 Java 开发,对新前端
技术栈了解比较少,在搭建环境和启动项目过程中滋生一些趣事。
比如使用 npm 启动项目后如何在浏览器访问项目,我为了让其醒目意识到我们的项目首页就是未经改动的 Vue-cli 首页,于是我将首页改动并推到远程 master 分支,后面便是我们的搞笑对话。
正文
暂定对方昵称为lzz
Begin
我:“你再从 master 拉一下最新的代码,然后重跑一下”
lzz:“速度教一波拉代码,我没操作过命令行”
我:“git pull origin master”
lzz:“我天天在 eclipse 操作”
lzz:“要在项目目录下吗”
我:“嗯”
lzz:“这是 pull 下来吧,接下来的呢,ok 了?”
我:“pull 会自动合并进当前分支,fetch 只拉,还需要手动 merge”
此处涉及 git pull 和 git fetch & git merge 的区别
lzz:“怎么上传分支”
我:“你新建分支了吗,我瞅瞅”
lzz:“如何瞅,命令行在哪看”
我:“截图,git checkout -b 新建的分支名”
我:“git branch 看现在在哪个分支”
lzz:“你的分支”
lzz:“我拉你的分支还是从主分支上拉比较好”
我:“当然主分支,你为啥在我的分支”
lzz:“我看看怎么拉主分支”
我:“git checkout master”(我因得知他在我的分支上,所以让他先切到主分支上去)
lzz:“我又没上传这个分支”
我:“切换到主分支,你为啥会到我的分支”
lzz:“不知道”
我:“骚操作”
lzz:“昨晚 zz 教我拉的时候拉的吧”
我:“不学好”
lzz:”fxxk,还要提交,我直接把这个分支删了吧“(我内心 os:"… 为啥要删我分支 …")
我:”你改啥了,你改动后删不掉的,git status“
这里涉及使用
git status
查看本地仓库文件状态
lzz:”fxxk you“
我:”fxxk you too“
我:”git status, 看看改啥了“
lzz:”嗯“
我:”git checkout .“
我:”git checkout master“
我:”git checkout -b lzz“
我:”git push origin lzz“
lzz:”我还原了,这是依赖吧“
然后我看到他的控制台还有 package.json 和 package-lock.json 文件为已修改状态,于是提示他撤销全部
我:”git checkout .“
lzz:”npm clean?“
我:”no“
lzz:”你这是重放个位置了“
我:”你执行就是了“
lzz:”没鸟用,是../吧“
我:”git status“
他了一张截图,提示他所在目录不是一个 git 目录,因为他已经通过..到了项目上一级目录,自然不是 git 目录
我:”回到项目目录“
lzz:”git init?“
我:”你乱跑啥“
我:”cd ./项目目录名“
我:”init 你妹“
此时他已回到项目目录再次 git status,提示工作树干净(working tree clean)
我:”git checkout master“
我:”git checkout -b lzz“
我:”git push origin lzz“
我:”赶紧,让我看到你的分支,刷个存在感“
经过操作,他在远端仓库推送了新的分支 lzz 到项目
我:”不容易“
lzz:”这个主分支和你的分支就 index.html 不一样吗“(因为他看到的是旧的 master,他并没有按照我的要求使用 git pull origin master 拉取我新提交的 master)
我:”你就没改东西,一毛一样,现在三个分支内容一样“
lzz:”页面不一样“
我:”一样的,master 我改了,你刚才看到的就是 master 的“
lzz:”嗯,提交就是,git push origin lzz?“
严谨来说这里并不一定,因为 origin 只是 git 约定俗成的远程主机名,其实这个参数可以自定义,比如你需要推到多个远程仓库时,需要在 origin 之外自定义远程主机名
我:”不是“
lzz:”还是直接 git push“
我:”这是把本地分支推到远程“
lzz:”嗯“
我:”提交是 git commit“
lzz:”1,想起来了“
我:”直接 git push 需要把本地同名分支和远程同名分支绑定“
这里有待考究,我说的这是否是必要条件,但 git 的确是提供了-u 参数用于绑定本地分支与一个默认远程分支,这样仅使用 git pull 和 git push 便可将该远程分支与本地分支进行互动
lzz:”git checkout . 放弃文件的修改吧?“
我:”是,其实是把远端的覆盖本地的“
关于 git checkout 的使用,理解为放弃修改,从效果上看的确是这样的,也是我一开始学习和使用 git 的理解,但从本质上 git checkout 实际还是在执行其本质行为,就是检出远程文件,只不过这样做的确就会将本地的覆盖,达到放弃本地文件的修改的效果
lzz:”我每次重新切换分支,要 npm install 吗?“
我:”新分支需要,已经 install 过的分支不需要“(此处涉及 npm 项目的知识,与本文关系不大)
lzz:”我 push 的时候不会将这些包带着吧“
我:”不会,.gitignore 忽略 node_modules 目录“(这当然是我配置的,不过这个问题问的很好,说明其意识到的 git 对于项目文件的管理细节)
lzz:”貌似没有忽略啊“(他看到 package.json 和 package-lock.json 文件被提示尚未加进暂存区)
我:”这两个文件可以提交,也可以手动忽略,我加一下“(所谓手动忽略当然就是使用 git checkout 检出远程同名文件覆盖本地的修改,我加一下是指其实 package-lock.json 的确不需要提交,而 package.json 随着项目的迭代可能有包的更新,所以项目团队间需要互通,不过如果使用相同的 node 环境,这样的更新每个人在本地都会有及时的感知,所以这两个文件是否要纳入版本管理不重要)
lzz:”上面的.json 文件我并未改动,应该就像 maven 的 pom 文件一样,为什么会变动呢“(此处涉及 npm 对于依赖包的管理)
我:”因为你又 npm install 了,会更新版本“
lzz:”拉下新的版本,拉下我的“
我:”干啥“(其实我已经在远端仓库客户端,我们会使用的 gitee,看见他的修改,一个小小的恶作剧)
lzz:”你瞅瞅我的 master piece“
我:”你发 pull request“
此处涉及 gitee、github 这类用于公共开源,不同于 gitlab 的 merge request,而是通过发起 pull request 将分支合入 master
他给我发了一张他提交记录的截图,标识他已经将自己本地的分支提交到远端仓库
我:”你不提交 pull request,你就只是在自己的分支玩,你看看你能 merge 进 master 吗“
lzz:”你拉我的分支不行吗,你把我的分支拉下来啊“
我:”我干嘛要拉你的分支“
我给他发一张我对于其提交的评论截图(基于 gitee)
lzz:”你这个页面在哪,github 还是码云上“
我:”gitee“
lzz:”什么鬼???“(因为码云这个对于代码评论的功能的确做的看上去和 github 很像)
我:”码云,就是 gitee“
我:”洗洗睡吧“
lzz:”这样?“
他发了一张在操作 pull request 操作的截图,但填写是错误的,源分支为远程 lzz,目标分支为远程 lzz,其实 pull request 是要发起申请将你提交到远程仓库的分支 merge 进远程的 master 分支,经过操作,他最终成功发起了正确的 pull request
lzz:”知道 PR 啥作用了“
我:”目标分支填 master 啊“
lzz:”嗯,知道了,睡觉“
END
总结
整个过程其实就是一个经典的新手入手 git 并结合第三方远程仓库管理个人项目的各种操作,对话看上去愚蠢,但其实基本覆盖了团队基于 git 进行协作的基本操作和重要核心的 git flow
结论
在此过程中虽然我使用 git 有一些经验,但还是觉得仍有部分环节的细节有待深入研究,不过经验就是:使用 git 一定要随时保持清醒,知道自己所处位置(git 仓库、暂存区、本地仓库、远程仓库),对分支的分分合合要有着清醒的头脑,否则很有可能在使用 git 这个管理代码和版本的强大工具之下也会搞的一团糟,它就像一把双刃剑,用好的话可以事倍功半,用不好也可能对代码项目带来严重的灾难