代码托管平台与版本控制系统
开始以下的内容前,读者需要了解:
- 软件的构建,语义版本编号
代码托管
顾名思义,代码托管平台是一个托管代码的平台,其目的,就是保管用户的代码。当然,托管平台也提供除了保管之外的其他功能,接下来将会逐一介绍。
回顾上文的场景,可以得知,要想愉快的和别人分享代码,我们需要一个能够支持用户评论、提出问题,并且获得最新动态的平台。
在现有的代码平台,对于上述的应用场景,通常会有这么几个概念:
-
维护者(maintainer):简单地说,就是负责维护代码的人,当代码出现问题时会着手解决。
-
组织(organization):类似于现实生活中的组织,即若干用户组成的小组,其名下可以有若干项目。
-
项目(project):这里的项目类似于现实中的项目,即为了解决一个问题而提出的方案。
-
仓库(repository):类似于现实生活,仓库中可以存放很多东西(文件),一般是代码以及相应的资源文件等。仓库也简称“repo”。一般情况下,一个仓库对应一个项目,也就是解决一个或一类问题。具体尺度的把握需要用户在使用过程中进行体会。
-
“issue”:用户可以向代码维护者提出“issue”。“issue”,即“议题”,针对项目中存在的问题或者可以改进的地方都可以在“issue”中提出。任何具有对项目(仓库)访问权限的用户都可以提出“issue”,或者参与进讨论当中。一个“issue”在解决后就被“close”掉,即当提出的问题被解决,或者仓库维护者认为该问题不够成为问题时。
-
“watch”:用户可以“watch”一个仓库,这样,当仓库有新的动态时,用户就会被提醒。
-
“star”:用户可以给自己喜欢的项目标星。一个仓库的星星数越多,可能说明其越受欢迎。
版本控制
项目的开发必然会有不同的阶段,使用者可能会使用同一项目的不同版本,项目所有者可能也需要记录项目的变化过程。项目的开发过程中可能还涉及协作,每个开发者不同的版本,最后需要进行汇总。以上这些需求,涉及到版本控制,往往需要版本控制系统(VCS,Version Control Systerm)来实现。
一般,代码托管平台会有以下涉及到版本控制的概念:
-
“commit”:提交。在版本控制系统(verison control system)中,存在着“快照(snapshot)”的概念,即仓库中各个文件在某一时刻的状态。而每一次提交,就是对项目进行的一次“快照”。使用版本控制系统,我们可以轻松的记录或回退到之前的某个状态,这样不仅可以记录项目的变化,也能很容易地在发生错误后进行恢复,甚至能找到问题发生的时间和相关责任人。每次提交,都对应一串哈希值,用户可以通过这个值来定位到相应的状态。
-
“diff”:一般来说,在版本控制系统的可视化中,我们会看到每次提交所对应的更改(diff)。这是版本控制系统将这次提交对应的快照与上次快照进行比对而得到的结果。事实上,我们可以比较任意两次快照之间的不同。对于大小不太大的纯文本来说,这种比较(逐行比较)可以很容易的进行,并且让我们清楚的看到代码的变动。而对于图像等文件,“逐行比较”则不具有这种意义了。
-
“Release”:发行版。当仓库中的项目达到一定阶段,维护者可以选择推出“发行版”,发行版需要保证功能完备且稳定。发行版其实就是仓库的某一次快照,或者说,对一次提交的哈希值起了一个好记的别名。每个版本一般会有一个版本编号。
-
“fork”:用户可以在代码平台上“fork”一份代码在自己的账户下。这个过程类似于复制仓库当前的状态到自己的账户下。用户可以在自己 fork 的这份代码上进行修改。
-
“clone”:存储在代码托管平台(或者自建服务器等远程计算机)上的代码仓库叫做远端仓库。我们可以在本地“克隆”一份仓库的副本。默认的“clone”会复制仓库所有的历史版本。
-
“pull”:拉取。即从其他的版本(快照)拉取代码到当前版本。执行 pull 时,版本控制系统软件会为我们检测冲突。如果代码有冲突,会自动合并;否则则需用户手动解决冲突。
-
“push”:推送。即将代码从一个版本推送向另一个版本。比如,用户在本地仓库修改代码并执行 commit 后,可以将代码推送到远端仓库。
-
“branch”:分支。分支可以理解为若干连续快照所形成的时间线。一个项目可以由多个用户并行完成。代码的主要变更线为主分支。得益于分支,我们可以在一个仓库中同时维护一个项目的若干版本,也可以在不影响现有功能的情况下开发、测试新的功能,并在测试完成后合并到主项目。不同用户也可以同时开发各自负责的新功能,而不至于互相干扰。
-
“merge”:合并。将两个不同分支快照合并在一起。当用户在分支上的工作完成后,可将更改合并到其他分支(如主分支)。
-
“Pull Requests”:当然,用户也可以不止步于提出“issue”,而直接参与到项目中来。用户通过“fork”取得对应仓库的状态,之后在其上进行修改,完成后可以向目标仓库发起“Pull Request(简称 PR)”,一般来说,目标仓库的维护者需要对代码进行“review”,确认无误后,用户方可执行“merge(合并)”操作,即将自己的修改汇入目标仓库中。
关于代码托管平台,有一些需要注意的地方。所谓代码,主要指的是“源代码”,也就是纯文本格式的源文件。这说明了两点:
-
只要是文本格式、易于为人类所读的文本文档,都可以是它理想的服务对象,我们在上文也提及了纯文本文件的优势——可以比较状态之间的更改。比如,除了代码,用户也可以对自己撰写的小说、散文,甚至是矢量图进行管理(使用纯文本字符、以人类易读方式记录的矢量图)。
-
我们在开发时关注的是源文件,即生成我们需要的物品的原始内容,而不应该包含生成之后的物品,以及生成过程的中间产物。具体来说,在开发过程中,我们的项目文件夹中会产生一些不必要的文件,比如编译产物、缓存文件等,这些文件对于项目的分享和记录没有帮助,是不应该被记录在版本控制系统中的,需要使用者进行排除。
构建(build),是指将源代码变成独立的、具体可感的软件制品的过程。我们也会用“build”来称呼构建所得到的产品。比如,C/C++ 的源代码不能直接被机器执行,需要编译成对应平台的可执行文件。具体请参考之前的章节。
一般,项目所有者可能会将构建产物发布在 Release 中。发布预构建的制品一般是为了节省使用者构建所需的时间,也可能是由于项目所有者不希望用户对自己的产品进行修改。
下一个章节会具体的来介绍如何进行以上的过程。