Git 入门的一种(一)

不了解任务,也就不能更好的使用工具(的特性)—— 陈原

为了保证效率和质量,大型软件项目离不开源码版本的控制与管理(version-control system)工具的帮助,一种编码以外的,属于项目管理的重要工具之一,VCS提供包括「版本跟踪」和「多人协作」的功能。源码版本的控制的概念还是比较直观的,任务不难,但是当功能和任务扩展到版本的多人协作管理,再加上分布式,版本仓库在分布在多个网络节上时,VCS任务变得很复杂。参与VCS的人员涵盖了开发者,项目管理者,和周边人员(系统管理人员,学习者,软件用户),VCS是一个十足的Ecosystem,一种类似生态结构系统。

复杂回报是功能强大,灵活,以Git为例,一种现代的VCS,相当的复杂,相当的强大。然而,这对于初学者,很是畏惧,面对诸多的命令和概念,甚至有点无从下手的感觉。

怎么说Git只是一个工具,只是囊括了多种不同性质「项目源码跟踪和管理任务」,集结了多样的功能,造成学习上的困难,所以学习Git的第一步应该大略「划出这些任务」,和对应的工作角色。

下面的讨论假设你对一般VCS任务有一定认识和经验,并对Git这个最流行的VCS软件有过一定了解。如果没有Git经验可以看我之前写的一篇文章,还有这里

排除学习Git无从下手的方法,是将VCS任务进行划分,并通过完成一项具体任务来慢慢消化。

三层角色

Git VCS任务粗略可划成三层角色:git system administrator、项目经理和开发者(编码者)。理解此三个角色的例子是,你想提交代码进行版本跟踪,你必须先是一个项目的开发者;作为一个开发者想参与项目必须先有一个项目,由项目经理控制和管理;项目经理则必须有一个git系统给它用。这三层区分是最粗略的,还可以再细致,例如,「编码者」具体提交是在一个分支(branch)上的,「开发者」内部会有分支管理的任务;而开发所在的项目一般是分布式协作,有多个版本仓库,所以「项目经理」有远程管理版本仓库的任务(例如下面讲的克隆一个仓库到本地进行阅读)。

实践中,我们常常只从开发者的角度思考,模糊了前两者的角色,因为开发者身兼了多职,最好将它们分开。

一项具体任务

VCS具体任务很多,最具意义当然要数「提交新版本」这个任务,但最直观的,我认为是「查看一个项目源码」。因为我们常常需要阅读别人的作品,例如github上的开源项目。

所谓「查看一个项目源码」,最直观的理解(使用非VCS词汇)是下载一个公共托管项目的源代码(例如github上的项目)到本地进行阅读。github都提供了项目压缩包,然而我们要通过git来下载。

查看一个项目源码

要阅读一个现存git项目最新版本的源码,你得有一个源码项目,一个git仓库,一个git系统。在一台git空白的机器上,你得一一按顺序安装和创建这些阅读条件。在这个过程中,你扮演着多重身份,这个必要清楚。

git 系统 与 git administrator

第一个条件,当然是一台git功能可用的机器,一个完整的git系统,这里我不介绍GUI工具,git系统界面是纯正的cli界面。所以你的第一个角色,是git system administrator,安装和配置git 系统。

安装git 还是比较简单,这里不述,请参考官方文档。

安装好后可以执行以下管理命令,检查安装版本和配置:

$ git --version
$ git config -l

查看配置帮助(git config)发现配置内容还不少,但是基本使用主要关注以下几项即可:

第一,配置文件;配置文件分配系统、用户和项目三层或范围,具体局部配置会覆盖全局一般的配置,例如「项目配置」会覆盖「用户配置」;

  • 全局:etc/gitconfig
  • 用户:~/.gitconfig or ~/.config/git/config file
  • 项目:config file in the Git directory (that is, .git/config)

第二,必选的git用户标识(Identity)配置;每一个 Git 的Commit都会使用这些信息,它会写入到你的每一次快照Commit中,不可更改,如果没有配置标识,则每次提交都要填。注意,如果你针对一个特殊项目使用了不同git用户标识,那么要该项目本地配置git用户标识(使用无--global配置开关);

$ git config --global user.name "John Doe"
$ git config --global user.email johndoe@example.com

第三,可选配置编辑器,git 操作有些需要添加编辑内容,例如为一个新Commit编写描述信息,默认使用vim;

$ git config --global core.editor emacs

第四,可选配置界面着色;

$ git config --global color.ui 'auto'

第五,查看配置

$ git config --list
user.name=John Doe
user.email=johndoe@example.com
color.status=auto
color.branch=auto
color.interactive=auto
color.diff=auto

更多的配置选配请查阅文档(安装配置)。

git 仓库 与 git repo mgr

现在有了可用 git 系统,我们可以操作git仓库了。要查看现存git项目最新版本的源码,我们要通过在本地克隆一个github开源项目的仓库,然后从中签出最新版本。在掌握这个任务,我们必须认识 git 仓库的创建技术,git repo mgr的第一任务。

严格上说,git repo,git项目,和源码项目,是有区别的,「git repo」约等于「git项目」,何为?因为,「git repo」特指所有版本历史数据的版本仓库,而「git项目」是指包含「git repo」和一个签出(checkout)版本的开发项目文件夹。源码项目则是没有被git 跟踪管理的项目。认识这些差别是理解创建和维护git repo的基础。

EM:git 作为一种工具,有三个层面:repo、branch和commit,分别解决不同的软件开发协作任务。

根据你的情况,创建git 仓库的可能方式有三种:

  • 第一,空项目;就是还有没开发源代码的空项目,只有一个文件夹;
  • 第二,已有的源码项目;只是没有被git 跟踪管理的项目;
  • 第三,克隆现有的仓库;在有加入项目的新成员时,这种方式是常见的,也是本「具体任务」的目标;

EM:创建一个本地git repo,一人开发,和创建一个完整分布式git 项目,多人网络协作,还是有区别。后面介绍git remot时会看到。

创建新仓库

为空项目,和已有源码项目创建仓库的任务是类似的,只是有源码项目时,需要提交一次commit将现有代码数据添加入仓库,作为初始版本。

$ cd /your/project/dir
$ git init
$ git add *.c // 这个有什么文件取决于你的项目情况
$ git add LICENSE
$ git commit -m 'initial project version'

git add / commit不属于git repo mgr的任务,所以这里不详细,看后面。

克隆仓库

以上只是在本地创建了一个单机仓库,在git设计上,和具体实践上,「项目仓库」由分布在多台主机上的多个仓库组成,仓库间存在remote关系。这些分布式版本仓库一般由一个用于管理的中心库(origin)和多个由开发者拥有开发库组成(看下图),git本身并没有规定或划定仓库的角色(或库分布式模型),这些都是作业最佳实践,就像后面会讲到的「分支模型」一样,也是最佳实践,被证实的有价值的工具。 centr decentr 2x

而git 克隆概念,一般是指完整的从中心仓库复制一份副本。git克隆操作是:

$ git clone <url>

要克隆仓库的条件是得先有一个克隆的目标,这里假定有一个目标(例如github上的开源项目,或者一个私有的git项目组),详细创建仓库中心,参考文档(getting git on server):

$ cd /your/allprojects
$ git clone https://github.com/libgit2/libgit2
$ git clone https://github.com/libgit2/libgit2 mylibgit //这个使用自定义文件夹

这会在当前目录下创建一个名为 “libgit2” 的目录,并在这个目录下初始化一个 .git 文件夹,从远程仓库拉取下所有数据放入 .git 文件夹,然后从中读取最新版本的文件的拷贝。git clone只是对多个基础操作的逻辑包装,包括git init, git fetch, git checkout等。

到此,你已经基本学会了「查看一个项目源码」这个任务了。然而,我们不仅仅只是为了查阅源码,我们需要分享源码创作进行项目协作,git repo mgr需要维护多个远程仓库的任务,包括多个仓库的远程配置,和数据协同。

分布式仓库配置

克隆仓库的操作揭示了,「完整的git项目」是由多个分布式仓库组成,每个仓库都有一个remote属性,可互相关联推拉数据,共同协作。而查阅和配置remote属性也是repo mgr的工作:

// 1`查阅,和添加关联仓库

$ git remote
origin // 这是中心库,在克隆后自带的remote属性
$ git remote add pb https://github.com/paulboone/ticgit //添加一个协作库,与paul协作开发
$ git remote -v
origin https://github.com/schacon/ticgit (fetch)
origin https://github.com/schacon/ticgit (push)
pb https://github.com/paulboone/ticgit (fetch)
pb https://github.com/paulboone/ticgit (push)

//2` 改名

$ git remote rename pb paul
$ git remote
origin
paul

// 3`删除关联

$ git remote remove paul
$ git remote
origin

协同仓库

现在我们知道「如何配置分布式仓库」了,配置好后我们有了同步协作的功能,在两个或多个仓库间进行数据协同。

// 1` 查看与中心库origin关联状况,这个使用git remote命令,算是repo admin
$ git remote show origin
* remote origin
Fetch URL: https://github.com/schacon/ticgit
Push URL: https://github.com/schacon/ticgit
HEAD branch: master
Remote branches:
master tracked
dev-branch tracked
Local branch configured for 'git pull':
master merges with remote master
Local ref configured for 'git push':
master pushes to master (up to date)

// 2` 拉取别人的贡献,但不合并
$ git fetch pb
remote: Counting objects: 43, done.
remote: Compressing objects: 100% (36/36), done.
remote: Total 43 (delta 10), reused 31 (delta 5)
Unpacking objects: 100% (43/43), done.
From https://github.com/paulboone/ticgit
*[new branch] master -> pb/master
*[new branch] ticgit -> pb/ticgit

// 3`拉取别人的贡献并且合并
$ git pull

//4` 分享你的贡献
$ git push origin master

git 分支与git pm

到此,我们也已经学会了如何与中心库,和同事的库之间进行数据更新,同步协作成果。而在正开发编码并进行版本记录之前,我们还要学会「分支」的创建和管理,因为我们的任何commit都是在一条具体的分支上进行的。

git commit与git pp

参考

裸男
Nakeman.cn 2023 Build by Gatsby and Tailwind, Deploy on Netlify.