接下来的问题是,如何让在不同系统上的开发者协同工作?于是,集中化的版本控制系统(Centralized Version Control Systems,简称 CVCS)应运而生。这类系统都有一个单一的集中管理的服务器,保存所有文件的修订版本,而协同工作的人们都通过客户端连到这台服务器,取出最新的文件或者提交更新。
Linux 内核作为参与人数众广的开源项目,绝大多数维护工作都花在了提交补丁和保存归档的繁琐事务上(1991-2002年间)。 到 2002 年,整个项目组开始启用一个专有的分布式版本控制系统 BitKeeper 来管理和维护代码,却于 2005 年被开发 BitKeeper 的商业公司结束合作关系,他们收回了 Linux 内核社区免费使用 BitKeeper 的权力。 这就迫使 Linux 开源社区(特别是 Linux 的缔造者 Linux Torvalds)基于使用 BitKcheper 时的经验教训,开发出自己的版本系统 -- Git。 他们对新的系统制订了若干目标来能高效管理类似 Linux 内核一样的超大规模项目(速度和数据量):
前注1:本文写作用时 5 小时 55 min,预计阅读时间 15 分钟。 前注2:本文基于学习型写作。查阅+写作+总结+迭代同步进行。
ARTICLE.INTRODUCTION.序
Git 作为以命令行为主的免费开源分布式版本控制系统,说简单也简单,说难也绝非易事。本文以快速上手 Git 单人开发为最终目标,贯穿讲解 Git 背景等相关知识,内容较长,却也循序渐进,以期达到融汇贯通的效果,不足之处还望指点。在看本文之前,你最好能够提前了解 Linux 基本命令的使用。
ABOUT.VCS.了解版本控制系统(VCS)
本地版本控制系统(LVCS)
为了解决复制整个项目目录的方式来保存不同的版本问题,人们很久以前就开发了许多种本地版本控制系统,大多都是采用某种简单的数据库来记录文件的历次更新差异。
其中最流行的 RCS 的工作原理是在硬盘上保存补丁集(补丁是指文件修订前后的变化);通过应用所有的补丁,可以重新计算出各个版本的文件内容。
集中化版本控制系统(CVCS)
接下来的问题是,如何让在不同系统上的开发者协同工作?于是,集中化的版本控制系统(Centralized Version Control Systems,简称 CVCS)应运而生。这类系统都有一个单一的集中管理的服务器,保存所有文件的修订版本,而协同工作的人们都通过客户端连到这台服务器,取出最新的文件或者提交更新。
这种做法带来了许多好处:每个人都可以在一定程度上看到项目中的其他人正在做些什么,而管理员也可以轻松掌控每个开发者的权限。但考虑到中央服务器的单点故障、中心数据库所在的磁盘发生损坏等问题,整个项目的历史记录被保存在单一位置,就有丢失所有历史更新记录的风险。
分布式版本控制系统(DVCS)
于是分布式版本控制系统(Distributed Version Control System,简称 DVCS)面世了。 在这类系统中,像 Git、Mercurial、Bazaar 以及 Darcs 等,客户端并不只提取最新版本的文件快照,而是把代码仓库完整地镜像下来。 这么一来,任何一处协同工作用的服务器发生故障,事后都可以用任何一个镜像出来的本地仓库恢复。 因为每一次的克隆操作,实际上都是一次对代码仓库的完整备份。
更进一步,许多这类系统都可以指定和若干不同的远端代码仓库进行交互。籍此,你就可以在同一个项目中,分别和不同工作小组的人相互协作。 你可以根据需要设定不同的协作流程,比如层次模型式的工作流,而这在以前的集中式系统中是无法实现的。
GET.START.GIT 简史
Git 的由来
Linux 内核作为参与人数众广的开源项目,绝大多数维护工作都花在了提交补丁和保存归档的繁琐事务上(1991-2002年间)。 到 2002 年,整个项目组开始启用一个专有的分布式版本控制系统 BitKeeper 来管理和维护代码,却于 2005 年被开发 BitKeeper 的商业公司结束合作关系,他们收回了 Linux 内核社区免费使用 BitKeeper 的权力。 这就迫使 Linux 开源社区(特别是 Linux 的缔造者 Linux Torvalds)基于使用 BitKcheper 时的经验教训,开发出自己的版本系统 -- Git。 他们对新的系统制订了若干目标来能高效管理类似 Linux 内核一样的超大规模项目(速度和数据量):
自诞生于 2005 年以来,Git 日臻成熟完善,在高度易用的同时,仍然保留着初期设定的目标。 它的速度飞快,极其适合管理大项目,有着令人难以置信的非线性分支管理系统(Git 分支)。
谁在使用 Git
以下是官网上列出的使用 Git 的著名公司、项目,但远不止这些。
DEEP.IN.深入Git
因此,Git 是分布式版本控制系统中很流行的一种, 和其它大部分系统以文件变更列表的方式存储信息对比:后者将它们保存的信息看作是一组基本文件和每个文件随时间逐步累积的差异,而 Git 更像是把数据看作是对小型文件系统的一组快照。
Git 的三个特点
24b9da6552252987aa493b52f8696cd6d3b00373
Git 的三种状态
Git 系统上的文件有三种状态已修改(modified)和已暂存(staged)、已提交(committed)。
由此引入 Git 项目的三个工作区域的概念:
Git 的工作流程
可以用如下命令随时查看 Git 系统中文件的状态:
USE.WAY.Git 使用方式
Git 有多种使用方式。 你可以使用原生的命令行模式,也可以使用 GUI 模式,这些 GUI 软件也能提供多种功能。以下分别介绍这两种模式,首推命令行模式。
使用 Git 的命令行工具【推荐】
只有在命令行模式下你才能执行 Git 的所有命令,而大多数的 GUI 软件只实现了 Git 所有功能的一个子集以降低操作难度。此外,由于每个人的想法与侧重点不同,不同的人常常会安装不同的 GUI 软件,但所有人一定会有命令行工具。
在 Mac 上安装 Git 直接在命令行输入 Git 并回车,没有的话会提示安装。
在 Windows 上安装 Git
从源代码安装 Git
安装 Git 的 GUI 工具
这里只做 Github Desktop 的介绍和推荐,有关 Github 的相关知识点之后提及。
可以看出,Git 的图形化操作比命令行操作用起来要方便也更加直观。多平台的 Github Desktop 将 Git 的图形化操作发挥到了极致。
但重回之前所说,只有在命令行模式下你才能执行 Git 的所有命令,而大多数的 GUI 软件只实现了 Git 所有功能的一个子集以降低操作难度。Git 的 GUI 对使用分布式版本控制的开发者来说还无法普及。
PLATFORM.TOOL.基于 Git 的 Github 代码托管平台
GitHub 是一个面向开源及私有软件项目的托管平台,因为只支持 Git 作为唯一的版本库格式进行托管,故名 GitHub。GitHub 于 2008 年 4 月 10 日正式上线,除了 Git 代码仓库托管及基本的 Web 管理界面以外,还提供了订阅、讨论组、文本渲染、在线文件编辑器、协作图谱(报表)、代码片段分享(Gist)等功能。目前,其注册用户已经超过350万,托管版本数量也是非常之多,其中不乏知名开源项目 Ruby on Rails、jQuery 等。
放入自己的开源项目,实战的同时还能帮助需要的人,多么有意义。
SINGLE.DEVELOPMENT.实战 Git 单人开发
于是到了实战环节,基于命令行模式,开始我们的 Git 单人开发。
01.配置 Git 基本信息
Git 自带一个 git config 的工具来帮助设置控制 Git 外观和行为的配置变量。 这些变量存储在三个不同的位置:
每一个级别覆盖上一级别的配置,所以 .git/config 的配置变量会覆盖 /etc/gitconfig 中的配置变量。
在 Windows 系统中,Git 会查找 $HOME 目录下(一般情况下是 C:\Users\$USER )的 .gitconfig 文件。 Git 同样也会寻找 /etc/gitconfig 文件,但只限于 MSys 的根目录下,即安装 Git 时所选的目标位置。
如上图,安装好 Git 之后就应该去配置自己的用户名和邮箱号,因为每一个 Git 的提交都会使用这些信息,并且它会写入到你的每一次提交中,不可更改。很多 GUI 工具都会在第一次运行时帮助你配置这些信息。
02.添加 Git 忽略文件
有些时候,你必须把某些文件放到Git工作目录中,但又不能提交它们,比如保存了数据库密码的配置文件,再比如Node 模块也是这样,只需把项目所需依赖名添加至 package.json 中,克隆到本地后本地安装依赖即可。
这就需要用到 Git 的 .gitignore 文件。Git 对于 .ignore 配置文件是按行从上到下进行规则匹配的,意味着如果前面的规则匹配的范围更大,则后面的规则将不会生效。下面列举几个常用的配置语法。
.gitignore 文件一般不存在,需要在仓库根目录下手动创建。
03.创建本地仓库
选择工作目录创建仓库,这里命名为“gittest”。
进入 gittest 文件夹
04.初始化版本库
新建的文件夹并不是 git 仓库,需要在根目录里面进行初始化。
初始化正常情况下应该得到如下命令行反馈:
初始化成功会发现新的 Git 仓库中多出了一个 .git 隐藏文件夹。用编辑器打开可以看到,.git 隐藏文件夹是
git init
后在当前目录生成的一个管理 git 仓库的文件夹,这里存储着 git 你现在检出(checkout)的文件,当你在项目不同分支切换时,工作目录里的文件经常会被替换和删除。所有历史信息都保存在当前目录中。05.添加与提交
之前的两步已经建立好了一个空的 Git 仓库,开始添加新文件。
06.创建和删除分支
几乎每一种版本控制系统都以某种形式支持分支。使用分支意味着你可以从开发主线上分离开来,然后在不影响主线的同时继续工作。和许多其他版本控制系统不同,Git 鼓励在工作流程中频繁使用分支与合并,哪怕一天之内进行许多次都没有关系。在创建仓库的时候,master 是“默认的”。在其他分支上进行开发,完成后再将它们合并到主分支上。
创建一个叫做“feature_x”的分支,并切换过去:
切换回主分支:
再把新建的分支删掉:
分支的版本回退:
除非你将分支推送到远端仓库,不然该分支就是不为他人所见的:
07.更新与合并
要更新你的本地仓库至最新的改动,执行如下命令以在工作目录中获取(fetch)并合并(merge)远端的改动。
要合并其他分支到你的当前分支,可以执行如下命令。
两种情况下,git 都会尝试去自动合并改动。不幸的是,这可能导致产生需要自己手动合并的冲突(conflicts)。改完冲突后,执行以下命令标记合并成功:
在合并改动之前,可以使用如下命令查看:
08.日志操作
大雁塔酒店。
09.撤销与修改
用来撤销最后一次 git add files,你也可以用 git reset 撤销所有暂存区域文件。
把文件从暂存区域复制到工作目录,用来丢弃本地修改。
通常,一个合并会产生一个合并提交(commit),把两个父分支里的每一行都合并起来。
修改
git commit
时填错的错误信息但是,如果当前分支和另一个分支没有内容上的差异(即冲突),git就会执行一个"快速向前(fast-forward)"操作,git不会创建新的提交,只是将当前分支指向合并进来的分支。
10.生成 SSH 密钥
为了使本地仓库和远端安全链接,于是到了这一步。
SSH key提供了一种与 GitHub 通信的方式,通过这种方式,能够在不输入密码的情况下,将GitHub作为自己的remote端服务器,进行版本控制。分为如下三步。
查看 SSH 密钥是否存在,如果有则备份删除。
生存密钥,过程中可直接按回车。
最后得到两个文件:id_rsa 和 id_rsa.pub 并获取其中密钥
在代码托管平台(这里是 Github )中添加公钥。
11.创建远端仓库
这里用到的是对 Git 版本控制系统运用最好的全球最大代码托管平台兼同性交友平台 -- Github。创建好自己的 Github 账号并邮箱验证后便可以创建 Git 远端新仓库。这里创建一个和本地同名的仓库“gittest”。
12.绑定本地到远端仓库
由于之前的操作都只是本地的,没有对远端仓库进行任何绑定,需要如下命令。
这里链接到了我的 github 地址的 gittest 仓库。这时我的仓库是这样子的,什么都没有。
13.推送改动
在进行
git commit -m ""
后所有改动已经在本地仓库的 HEAD 中了。执行如下命令以将这些改动提交到远端仓库:再次刷新 github 远端仓库,发现改动推送成功。
14.克隆远端仓库
从执行如下命令以创建一个本地仓库的克隆版本。
如果是远端服务器上的仓库,你的命令会是这个样子。
git 常用命令清单