看完了 Git 的介绍后,也是时候动手尝试一下了,不过我们需要先安装好它。它有许多种安装方式,主要分两种,一种是通过编译源代码来安装;另一种是使用为特定平台预编译好的安装包,这里就不做赘述了。
配置
一般运行前,我们都需要配置下自己的 Git 工作环境。配置工作只需一次,以后升级时还会沿用现在的配置。当然,如果需要,你随时可以用相同的命令修改已有的配置。Git 提供了一个叫做 git config 命令
专门用来配置或读取相应的工作环境变量。
用户信息配置,分别用来配置用户名和邮箱:
$ git config --global user.name "John Doe" $ git config --global user.email [email protected]
文本编辑器配置,Git 需要你输入一些额外消息的时候,会自动调用一个外部文本编辑器给你用。默认会使用操作系统指定的默认编辑器,一般可能会是 Vi 或者 Vim。或者你有其他偏好,比如 emacs:
$ git config --global core.editor emacs
差异分析工具,用于解决合并冲突时使用哪种差异分析工具,比如我们要指定 vimdiff:
$ git config --global merge.tool vimdiff
配置完成后,可以使用 $git config --list 命令。
操作
在讲解之前,给大家共享一个 Git 工具,Atlassian 公司的 SourceTree,这是他们公司的一个免费的 Git 操作工具,非常方便,好,接下来我们来看一下 Git 的主要操作。
有两种方法可以取得 Git 项目仓库,第一种是在现存目录下通过导入所有文件来创建新的 Git 仓库,第二种方式是从已有的 Git 仓库克隆一个新的镜像仓库。
创建
使用 $ git init 初始化后,在当前目录下会生成一个 .git 的目录,如果当前项目下有几个文件想要纳入版本控制,需要先用 git add 命令告诉 Git 开始对这些文件进行跟踪,然后提交 git commit,这样你就得到了一个可以维护的 Git 仓库。
克隆
如果说我们想迁出一个现有项目的话,就可以使用 git clone 命令,这里有一个细节,就是他用的是 clone 而不是 checkout。这就是 Git 同集中式版本控制软件的显著差别,Git 收取的是项目历史的每一个文件每一个版本,服务器上的数据通过克隆之后本地也都有了。即便服务器发生故障,用任何一个克隆出来的客户端都可以重建服务器上的仓库。假设我需要克隆 GitHub 上面的 guava 项目,就可以使用如下命令:
$git clone https://github.com/Krockey/guava.git
Git 支持许多传输协议,如 git:// 协议、 http(s):// 或者 [email protected]:/path.git 表示的 SSH 传输协议。
跟踪
工作目录下面的所有文件都不外乎这两种状态:已跟踪或未跟踪。已跟踪的文件是指本来就被纳入版本控制管理的文件,在上次快照中有它们的记录,工作一段时间后,它们的状态可能是未更新,已修改或者已放入暂存区。而所有其他文件都属于未跟踪文件。它们既没有上次更新时的快照,也不在当前的暂存区域。初次克隆某个仓库时,工作目录中的所有文件都属于已跟踪文件,且状态为未修改。在编辑过某些文件之后,Git 将这些文件标为已修改。我们逐步把这些修改过的文件放到暂存区域,直到最后一次性提交所有这些暂存起来的文件,如此重复。
要确定哪些文件处于什么状态,可以使用 git status 命令
暂存
暂存操作,是把文件放到暂存区,要暂存这次更新前,需要运行 git add 命令(这是个多功能命令,根据目标文件的状态不同,此命令的效果也不同:可以用它开始跟踪新文件,或者把已跟踪的文件放到暂存区,还能用于合并时把有冲突的文件标记为已解决状态等),但是这里可能会出现一个令大家困惑的地方。例如我们要提交一个 benchmarks.rb 文件,先运行了一次 git add 命令,然后又做了一次修改,再次跟踪状态,发现 benchmarks.rb 居然出现了两次!一次算未暂存,一次算已暂存,这怎么可能呢?实际上 Git 只不过暂存了你运行 git add
命令时的版本,如果现在提交,那么提交的是添加注释前的版本,而非当前工作目录中的版本。所以,运行了 git add
之后又作了修订的文件,需要重新运行 git add
把最新版本重新暂存起来。
$ vim benchmarks.rb $ git status On branch master Changes to be committed: (use "git reset HEAD <file>..." to unstage) new file: README modified: benchmarks.rb Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: benchmarks.rb
忽略
在项目中我们总会遇到一些文件无需纳入 Git 的管理,也不希望他们总是出现在未跟踪的列表中,我们可以创建一个 .gitignore 的文件,列出忽略的文件模式,该文件的格式规范如下:
- 所有空行或者以注释符号
#
开头的行都会被 Git 忽略。 - 可以使用标准的 glob(简化的正则表达式) 模式匹配。
- 匹配模式最后跟反斜杠(
/
)说明要忽略的是目录。 - 要忽略指定模式以外的文件或目录,可以在模式前加上惊叹号(
!
)取反。
提交
如果暂存区域已经准备妥当可以提交了,运行 git commit 命令即可。当然,可能你觉得使用暂存区域的方式略显繁琐,Git 提供了一个跳过使用暂存区域的方式,只要在提交的时候,给 git commit 加上-a 选项,Git 就会自动把所有跟踪过的文件暂存起来一并提交。在提交了若干个版本后,你可能想回顾下提交历史,可以使用 git log 命令查看。
撤销
任何时候,你都有可能需要撤消刚才所做的某些操作。但是有些撤销操作是不可逆的,所以请务必谨慎小心。想要撤消刚才的提交操作,可以使用 git commit --amend
选项重新提交,此命令将使用当前的暂存区域快照提交。如果刚才提交完没有作任何改动,直接运行此命令的话,相当于有机会重新编辑提交说明,但将要提交的文件快照和之前的一样。如果说文件已加入到暂存中,我们又不想提交了,可以使用 git reset HEAD <file>...
的方式取消暂存。可能有时候,我们不希望对文件进行修改了,在提交前,我们可以使用丢弃操作来丢弃更改,你可以使用 git checkout --file 来完成更改。
拉取
当然,如果大家是合作开发,一般来说会有一个远程仓库来进行项目协作,远程仓库是指托管在网络上的项目仓库,可能会有好多个,其中有些你只能读,另外有些可以写。如果说你需要从远程获取最新版本到本地,可以使用 $ git fetch [remote-name] 命令来实现此操作。如果是克隆了一个仓库,此命令会自动将远程仓库归于 origin 名下。所以,git fetch origin
会抓取从你上次克隆以来别人上传到此远程仓库中的所有更新(或是上次 fetch 以来别人提交的更新)。有一点很重要,需要记住,fetch 命令只是将远端的数据拉到本地仓库,并不自动合并到当前工作分支,只有当你确实准备好了,才能手工合并。实际上,默认情况下 git clone
命令本质上就是自动创建了本地的 master 分支用于跟踪远程仓库中的 master 分支(假设远程仓库确实有 master 分支)。所以一般我们运行 git pull
,目的都是要从原始克隆的远端仓库中抓取数据后,合并到工作目录中的当前分支。
推送
项目进行到一个阶段,要同别人分享目前的成果,可以将本地仓库中的数据推送到远程仓库。实现这个任务的命令很简单: git push [remote-name] [branch-name]
。如果要把本地的 master 分支推送到origin
服务器上(再次说明下,克隆操作会自动使用默认的 master 和 origin 名字),可以运行 $ git push origin master 命令。
标签
同大多数 VCS 一样,Git 也可以对某一时间点上的版本打上标签。人们在发布某个软件版本(比如 v1.0 等等)的时候,经常这么做。Git 使用的标签有两种类型:轻量级的(lightweight)和含附注的(annotated)。轻量级标签就像是个不会变化的分支,实际上它就是个指向特定提交对象的引用。而含附注标签,实际上是存储在仓库中的一个独立对象,它有自身的校验和信息,包含着标签的名字,电子邮件地址和日期,以及标签说明,标签本身也允许使用 GNU Privacy Guard (GPG) 来签署或验证。一般我们都建议使用含附注型的标签,以便保留相关信息;当然,如果只是临时性加注标签,或者不需要旁注额外信息,用轻量级标签也没问题。