前言:随着参与的系统开发复杂程度越来越高,我们面临着多人、异地协作的挑战!如何高效有序的协调好大家的开发工作?一个优秀的版本控制系统非常重要。即使是对于个人用户来说,采用版本控制系统管理个人的代码,可以很方便的在公共开发环境和私人开发环境上协调工作,而且代码安全有保障!常用的版本管理系统有Git和SVN,当然还有很多基于它们的GUI图形界面工具,本文的重点是推荐和学习使用Git在命令行模式下完成代码管理工作。
一、Git简介和安装
1、重点推荐使用Git版本管理系统工具的原因主要有以下三点:
a、分布式版本控制系统
Git是分布式版本控制系统,绝大多数的业务操作只需要访问本地文件和资源,比需要网络通信开销的集中式版本控制系统处理速度快很多。这就意味着代码的修改、提交是可以在很短时间内完成的,管理的代码量越大带给我们的体验感提升也越大!同时,Git可以在处于断网情况下提供数据的修改、提交。当然,分布式系统所有的这些好处都是建立在开销了更多存储空间的基础上,但是我们用的爽啊!
b、快照流的方式管理数据
Git和其它版本控制系统最主要的差别在于管理数据的方式不同,大部分的系统都是以文件变更列表的方式存储信息,它们保存的信息可以看作是一组基本文件和每个文件随时间逐步累积的差异。
如图所示:
Git 更像是把数据看作是对文件系统的一组快照,每次提交更新或者保存项目状态时,它主要对当时的全部文件制作一个快照并保存这个快照的索引。为了高效,如果文件没有修改,Git不再重新存储该文件,而是只保留一个链接指向之前存储的文件。这种管理数据的方式所带来的好处,我们将在学习Git分支管理时了解到。
如图所示:
C、数据管理完整性和安全性
Git 中所有数据在存储前都计算校验和(采用SHA-1算法),然后以校验和来引用数据,这也就意味着系统通过校验比对可以发现数据在存储和传送过程中的数据丢失和损坏!执行的Git操作都是在添加数据,几乎没有例如删除这样的不可逆操作。
2、Git管理文件的三种状态
Git中的文件存在三种状态:已提交(committed)、已修改(modified)和已暂存(staged)。已提交表示数据已经安全的保存在本地数据库中;已修改表示修改了文件,但还没保存到数据库中;已暂存表示对一个已修改文件的当前版本做了标记,使之包含在下次提交的快照中。由此引入 Git 项目的三个工作区域的概念,Git 仓库、工作目录以及暂存区域,如图所示:
a、Git 仓库目录保存着确定的版本文件(压缩处理过),是Git中最重要的部分,从其它计算机克隆仓库时,拷贝的就是这里的数据。
b、工作目录是从Git仓库提取出来并解压的某个版本的内容,放在磁盘上提供使用或修改。
c、暂存区域是一个文件,保存了下次将提交的文件列表信息,一般在 Git仓库目录中。有时候也被称作“索引”,不过一般说法还是叫暂存区域。
3、在linux、mac、win安装Git
Git有多种使用方式,可以采用原生的命令行模式,也可以采用GUI图形界面模式,更屌是可以在自己的项目中嵌入Git。建议优先学会命令行下如何操作,熟悉了基本使用流程后使用GUI软件也不会有什么困难。
Linux环境:
可以使用linux发新版包含的基础软件包管理工具安装Git。
基于Fedora的发行版,使用yum命令:sudo yum install git
基于Debian的发行版,使用apt-get命令:sudo apt-get install git
了解更多版本安装方法,参考:http://git-scm.com/download/linux
Mac环境:
方案一:安装Xcode Command Line Tools。对于较新版本的系统中,可直接在Terminal里面执行git命令,如果 没有安装过命令行开发工具,将会提示安装。
方案二:官方维护的OSX Git二进制安装程序可以在Git官方网站下载,网址为:
http://git-scm.com/download/mac
Win环境:
官方维护的Win Git二进制安装程序可以在Git官方网站下载,网址为:
http://git-scm.com/download/win
注:以上方式安装Git成功后即可在命令行下使用Git,本文并不涉及GUI图形化工具的安装使用。使用源码编译安装比较复杂,后续进一步深入学习使用Git时可以再学习。
4、初始化配置
安装Git完成后需要配置变量,程序的升级会保留配置信息,随时可以通过命令修改配置。Git自带一个git config工具来帮助设置控制 Git外观和行为的配置变量, 这些变量存储在三个不同的位置:
a、 /etc/gitconfig 文件包含系统上每一个用户及他们仓库的通用配置,使用git config --system命令读写。
b、 ~/.gitconfig 或 ~/.config/git/config 文件只针对当前用户,使用git config --global命令读写。
C、当前使用仓库的Git目录中的config文件(就是.git/config)针对该仓库。
注:每一个级别覆盖上一级别的配置,所以.git/config的配置变量会覆盖/etc/gitconfig中的配置变量。
配置用户信息和文本编辑器示例:
git config --global user.name babyTiger
git config --global user.email xxxx@gmail.com
git config --global core.editor vim
注:用户名称和邮箱配置非常重要,每一次Git的提交操作都需要记录这两个信息到提交记录中,可以使用git config --list和gitconfig <key>命令查看配置。
5、获取帮助手册的三种命令
git help <verb>
git <verb> --help
man git-<verb>
二、Git使用基础
1、获取Git仓库
有两种取得Git项目仓库的方法:
a、在现有项目或目录下新建Git仓库
第一步、命令行下进入该项目目录并执行git init命令(注意在win下使用git bash采用linux命令)
第二步、执行git status命令,结果如下:
首先,命令执行结果显示了当前所在分支master,这是默认的分支名,我们在下一节内容中再详细了解。其 次,结果中的untracked files将列出项目目录下是否有文件或子目录没有被跟踪,如果我们需要使用Git版本控制 工 具管理这些内容,则需要确保它们处于被跟踪状态!
第三步、至此已经初始化成功一个管理指定文件目录的Git仓
b、从一个服务器克隆一个现有的Git仓库。
使用git clone [url] 命令将从url确定的远程Git服务器上克隆一个完整的仓库到命令行当前目录,注意这里是默 认克隆到命令行当前目录。
2、使用仓库记录每个版本
我们已经获得了一个管理项目的Git仓库,并期望管控该项目的每一次修改。文件版本管理流程如图所示:
a、跟踪文件
前文中提到,对于已经建立Git仓库的项目,只有其中处于被跟踪中的文件或子目录才会被系统管控到。
第一步、执行git status命令查看项目目录中未被跟踪的内容
第二步、执行git add 文件名/目录名,该命令使用文件或目录的路径作为参数,如果参数是目录的路径,将递 归的跟踪该目录下的所有文件。
b、暂存文件
执行git add命令可以暂存改动后的文件和目录,这个命令可以理解为“添加内容到下一次提交中”。特别注 意,暂存文件到缓存区后如果再次修改了该文件,需要再暂存一次才能保证缓存区的文件版本是最新的!
c、状态简览
我们应该意识到Git管理文件的每个步骤都需要使用到git status命令来查看文件状态信息,确保我们的操作得 当。如果使用git status -s命令或git status --short命令,可以得到一种更为紧凑的格式输出。例如:
M readme1.txt
MM readme2.txt
A readme3.txt
M readme4.txt
?? readme5.txt
注:??表示未被跟踪的文件或目录;A表示新添加到缓存区域的文件或目录;M 有两个可以出现的位置,出现在 右边的 M 表示该文件或目录被修改了但是还没放入暂存区,出现在靠左边的 M 表示该文件或目录被修改了并 放入了暂存区,而两个MM表示该文件或目录被修改了并放入暂存区后再次被修改了。
d、忽略文件
通常对于一些项目自动生成的文件,比如日志文件或者编译过程中创建的临时文件等,我们并不考虑管理。在这 种情况下,可以创建一个.gitignore文件,列出要忽略的文件类型。规范如下:
空行或者以#开头的行都会被Git默认为注释行。
可以使用标准的 glob 模式匹配。
匹配模式可以以(/)开头防止递归,即当前目录有效。
匹配模式可以以(/)结尾指定目录。
要忽略指定模式以外的文件或目录,可以在模式前加上惊叹号(!)取反。
注: glob 模式是指 shell 所使用的简化了的正则表达式。星号(*)匹配零个或多个任意字符;[abc] 匹 配 任 何一个列在方括号中的字符(这个例子要么匹配一个 a,要么匹配一个 b,要么匹配一个 c);问号 (?)只匹配 一 个任意字符;如果在方括号中使用短划线分隔两个字符,表示所有在这两个字符范围内的都可以匹配(比如
[0-9] 表示匹配所有 0 到 9 的数字)。使用两个星号(*)表示匹配任意中间目录,比如a/**/z 可以配 a/z, a/b/z
或 a/b/c/z等。
e、查看已暂存和未暂存的修改
使用git status命令可以输出文件状态,但是我们并不清楚具体修改的地方。使用git diff命令查看未暂存的修 改,git diff --cached或git diff --staged命令查看已暂存的修改。
f、提交更新
使用git commit命令提交更新,在此之前最好使用git status命令查看一下是否有文件还没有暂存的,该命令只 提交更新暂存的文件。提交更新命令有三种用法:
git commit 调起文本编辑器提供编辑提交更新信息,退出编辑时会附带编辑的信息生成一次提交,提 示git status信息。
git commit -v 调起文本编辑器提供编辑提交更新信息,退出编辑时会附带编辑的信息生成一次提交,提 示git diff信息。
git commit -m “XXXXXXX” 附加字符串并提交更新。
注:虽然使用暂存区域可以有效减少错误,但是有时候也会觉得多一步流程很繁琐,使用git commit -a 命 令 将把所有已经跟踪过的文件暂存起来一并提交。
g、移除文件和移动文件
从Git中移除文件有两种情况:一种是将文件从磁盘移除并将文件从已跟踪清单中移除;还有一种是仅仅从已跟 踪清单中移除。
第一种情况:git rm (支持glob模式匹配多个文件或目录)
第二种情况:git rm --cached
从Git中移动文件同样需要考虑文件的跟踪关系,有两种等价的实现方式:
第一种:git mv fileFrom fileTo
第二种:mv fileFrom fileTo
git rm fileFrom
git add fileTo
3、查看提交历史
如图所示,调用git log命令后,打印出两条提交历史记录。命令不带参数,会列出每个提交的SHA-1校验和、 作者的名字和电子邮件地址、提交时间以及提交说明。按提交时间列出所有的更新,最近的更新排在最上面。
注:使用带参数的git log命令可以筛选特定记录和特定的信息输出格式。
4、撤销操作
在文件版本管理的每个状态,都可能需要撤销某些操作,特别注意有些撤销操作是不可逆的。
a、撤销提交操作
git commit --amend
该命令将重新提交暂存区内容并覆盖上一次的提交更新,覆盖内容包括文件、目录和上一次的提交信息。
b、撤销暂存的文件
git reset HEAD
注意git reset是一个功能非常强大的命令,可能极大影响工作目录。
c、撤销对文件的修改
git checkout --
该命令的实质是拷贝一个旧版本的文件来覆盖原文件,所以还原的程度完全取决于已保存的旧版本文件,调 用需谨慎!
5、提交打标签
Git可以在提交更新后打上版本标签,以重点标识最近一次提交的版本。Git 使用两种主要类型的标签:轻量标 签(lightweight)与附注标签(annotated)。一个轻量标签很像一个不会改变的分支,它只是一个特定提交的 引用。附注标签是存储在 Git 数据库中的一个完整对象,可以被校验。其中包含打标签者的名字、电子邮件地址、 日期时间,还有一个标签信息,并且可以使用 GNU Privacy Guard (GPG)签名与验证。通常建议创建附注标 签,这样你可以拥有以上所有信息,但是如果你只是想用一个临时的标签,或者因为某些原因不想要保存那些信 息,轻量标签也是可用的。
a、git tag 以字母顺序排列标签
b、git tag -l ‘xxx’ 排列出匹配后接字符串的标签
c、git show 查看标签详情
d、附注标签
git tag -a xxx 带-a参数命令添加一个附注标签,将调起文本编辑器添加标签信息
git tag -a xxx -m ‘xxx’ 使用-m参数的命令直接附加标签信息
e、轻量标签
git tag xxx 使用不带参数的命令打轻量标签
f、历史版本打标签
Git中可以对历史提交打标签,只需要在最后附加待打标签的提交校验和。
6、Git自定义命令别名
某些Git命令我们使用频繁的时候,就可以通过给它们设置别名方便使用。比如这里为用户jerry配置一个取消暂 存的别名:
git config --global jerry.unstage ‘reset HEAD --’