人人都能看懂的全栈开发教程——Git

人人都能看懂的全栈开发教程——Git

Chris Yue No Comment
Posts

我们偶尔会想在现有项目代码的基础上做一些尝试,来验证自己的某些想法。

『在这之前记得做好文件的备份』,正当你准备对某个文件添加尝试性质的代码时,一个声音突然冒出来:

『也许你一会儿就不知道代码原本是什么样了』

备份的确是一个好习惯,但现在已经 2020 年,大家都用 Git 了。

『Git 改变了我生活』程序员小王如是说到。

Git 是什么?

Git 是一个版本管理系统,版本管理系统也叫做 VCS (Version Control System)。

什么又是版本管理系统?

大家都用过软件吧?大家升级软件的时候都会看见『版本号』,假如你给某个软件升级之后变得反而不好用了,你还可以想办法找回之前的版本,重新安装。

对于我们的代码来说也是这样的,我们可以给项目某一个状态设置一个版本。随着我们继续开发升级,版本也会越来越多。

可能我们在开发到某个新功能时,发现这个功能做不下去,一开始的设计就有问题,我们也可以将代码恢复到之前的某个版本重新再来。

另外,版本管理系统并不是只有 Git,在 Git 流行之前,是 SVN 的天下。但 Git 的设计比 SVN 更有优势,导致目前 Git 几乎已经是所有开发人员管理代码的标配了。具体 Git 比 SVN 有优势在什么地方,后面再说。

既然 Git 这么多人都开始在用了,就赶紧用起来吧

首先我们得安装 Git,依然以 Ubuntu 为例子

sudo apt install git

完成之后,可通过 git --version 命令来确认是否安装。

在我们的项目根目录下,我们执行命令 git init,来初始化 Git 环境。实际上初始化 Git 环境,就是在我们的项目根目录下创建了一个隐藏的目录 .git。在 *nix 系统里,隐藏的目录都是 . 开头的,ls 命令需要添加 -a 参数,才能看到隐藏目录,大家可以试一下。

大家可以猜测到 .git 里存放了当前项目的版本信息。如果我们删除掉这个目录,那项目又跟之前一样,不再受版本管理。当然 .git 里的内容也不仅仅是只有代码版本的信息,后面我们还会进入到这个目录内部去做一些有意思的事情,敬请期待。

初始化好 Git 环境之后,我们可以通过 git status 命令来确认当前状态。

我们可以看到返回的结果出现很多红色的目录和文件,都是属于我们项目的文件和文件夹。如果一个文件(夹)是红色,表示它还没有被标记上版本,无法被还原。我们把标记上版本这个操作,叫做『提交』(commit)。

git add 命令则是将需要被提交的文件(夹)放在『准备提交』状态,git add 命令后面接的是要提交的文件(夹)的路径。因为我们要提交整个项目的代码,所以我们路径就是当前项目的路径 .

但我们做这个操作之前需要明确一个代码管理的规则,那就是只有项目自己的代码才应该被管理起来,而我们引用别人的第三方库,就不应该被管理了。因为第三方库有专门的工具 Composer 去管理。

由于第三方库都是放在 vendor 目录下的,那是不是意味着我们只能把除了 vendor 之外的其他文件(夹)一个一个依次去 git add 了呢?

这个问题其实早就被各种版本管理工具考虑到了。在 Git 里解决的方法是,在项目根目录下创建一个 .gitignore 文件,即忽略(ignore)列表文件,并输入我们想让 Git 忽略的目录:

# 这行是 .gitignore 文件的注释,井号在此文件里就好比 PHP 的 //
/vendor

这个时候执行 git status 会发现 vendor 目录已经没有列出来了,我们执行

git add .

就可以直接把除了 vendor 之外的其他文件(夹)都设置成『准备提交』状态。此时再执行 git status 会发现之前红色的文件(夹)都变成了绿色,表示已经在准备提交态了。

事实上,除了第三方库文件不应该被提交,还有一种文件也不能被提交。有一些项目,会在运行的时候生成很多临时的文件,就是典型的不能被提交的内容,因为这些内容,即不是开发创建的代码,也不是什么跟项目本身有关的文件,它们只是跟某一个具体的开发环境有关系的文件而已。总结一下就是,如果一个文件,它的存在并不影响整个项目的开发或者运行,或者这个文件只是跟某个具体的开发环境有关系(即每个开发环境虽然都有这个文件,但是内容都有可能不一样),那么这个文件就不应该被提交。

可能大家没有注意到,在之前我们使用 Composer 安装了 PHPUnit 库之后,项目里实际是多了一个 composer.lock 文件的。虽然这个文件也是程序生成的,但它会影响项目的运行,不能被忽略。大家如果好奇可以打开 composer.lock 文件来看。可以看到这个文件也是 JSON 格式的,内容是项目依赖的库——以及库依赖的库——的详细信息,比如版本号,下载地址等。有了 composer.lock 文件之后,我们把代码交给其他人,则其他人就不需要再自己去 composer require 库了,直接一句 composer install 就搞定。并且因为所有的库的下载地址都知道了,composer 也不会去花时间去查询库信息和依赖信息,直接下载,要比 composer require 的时候快很多。但最重要的是 composer.lock 文件保证了项目组所有成员所使用的依赖库都是完全一模一样的版本号,不会因个别成员下载到了不同版本的库文件而报一些只有他能遇到的错。

最后一步,我们确认好提交内容之后,就可以执行 git commit 即提交操作了。git commit 接受一个 -m 参数,即提交的相关说明,我建议大家都应该好好写每次提交的提交信息,好让其他人能看见代码每次更新都是为什么,或者有什么变化。沟通的方式有很多,无论什么方式,沟通顺畅了,工作的效率才能有质的提高。这里我们就这么写吧:

git commit -m '命令行和网站下列出所有任务;网站可添加任务;命令行可注册用户'

提交完成后,再次执行 git status 命令,你会发现已经没有列表了,主分支(master 分支)已经『干净』。分支也是一个大话题,以后再说。

On branch master

nothing to commit, working tree clean

如果你修改某一个文件,或者添加了某一个文件,执行 git status 之后会发现这个文件又会以红色显示出来,如果你想把这个文件也提交,再重复执行上面的操作就行了。

正如文中开头所说,可能你也只是写了一些探索性质的代码,如果想还原,可以执行

git checkout -- 你想恢复的文件(夹)路径
# 如果是想恢复整个项目
git reset HEAD --hard
# 或者
git checkout -- .

小提示:我们经常会提交了代码才发现,还有一些修改没写,补完之后再次提交吧,又觉得不知道写什么提交信息好,这个时候有两种方式,第一种,将变化的文件添加待提交状态后,用 git commit --amend --no-edit ,意思是拿这一次的修改去修复(amend)上一次的修改,并且不改提交信息(no-edit);还有一种方法是提交信息就随便写点啥,表示用来修复上面的提交的,一般都写 fixup,当你提交了好多个 fixup 的修改之后,再执行 git rebase -i 命令来将 fixup 的提交记录都『融合』到最开始的记录里去。git rebase -i 的用法不是一两句话能说清楚的,我也就不说了,大家看 Git 的官方文档了解。

Git 的功能非常丰富,我无法以一篇博客文章为载体为大家全部介绍,只能说一些最最最基本的,其他用法陆续会介绍。

如你所见,使用 Git 作 VCS,不用联网就可以。这是相对于 SVN 来说的,SVN 必须要求连接 SVN 服务器才能用版本管理的功能,它的版本信息都是存在服务器上的。

而 Git 也能像 SVN 一样,将代码上传到服务器上,供其他人克隆(Clone),注意 Git 上传的不仅是代码,还有每一次的版本。需要解释一下的是,在 Git 的世界里上传代码叫做推送(Push),后面我们会见到这个命令。

这也是 Git 相比 SVN 更有优势的一个地方。其他人去拉取代码时,实际上拉取的还有所有的提交记录。如果服务器出现故障无法访问,只要有人有一份克隆,可以立马创建另外一个服务器,将本地的代码推送上去就好了,如果是 SVN,一旦服务器完蛋,就只能指望这个服务器能恢复了。这就是所谓『分布式』相较与『集中式』最大的好处。

可能有了解 Git 的读者已经注意到我每个章节提供的完整代码示例,就是一个 Git 仓库。所以对于每一个章节的代码,各位读者实际也可以直接克隆我的项目:

git clone https://e.coding.net/chrisyue/full-stack-tutorial-1.git minetodo

composer install 安装依赖库,并执行 migrations 目录里的 SQL 之后就可以用了。

本章节完整项目代码见这里

人人都能看懂的全栈开发教程——Git by Chris Yue is licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License.

微信赞赏码

写作累,服务器还越来越贵
求分担,祝愿好人一生平安
天使打赏人

发表评论

36 − 31 =