前言:翻译自《Pro Git》。正在学习Git,于是打算翻译这篇文档。一方面锻炼自己英文文档阅读能力,翻译成中文也可以方面别人。正所谓赠人玫瑰,手有余香。鉴于本人水平有限,当然是不可能达到信、达、雅的水准。不过在翻译过程中,我会尽量保证遵循原文,有些不好直译的部分我会根据理解意译,对于有些实在不知道用中文怎么去表述但是不影响所讲述内容的英文,我可能会直接忽略掉。此外,对于没有把握的专有名词,我会给出翻译的同时保留原文。

 

1. 简介

此处省略若干字……

2. 起步

这一章的内容主要关于如何开始使用Git。我们首先要讲一些关于版本控制工具的背景,然后讲解如何在你的系统上让Git运行起来,最后讲讲使用之前需要做的一些设置。在本章的末尾,你会明白为什么Git会流行起来,而你为什么应该用它。

2.1 关于版本控制

什么是版本控制,为什么你需要关注它?版本控制是能记录一个或者一组文件随着时间推移所发生的变化并且方便日后回忆起某个特定版本的系统。举例来说,在这本书中,你会使用软件源代码作为被版本管理控制的文件,然而实际上,你可以对几乎电脑上任何类型的文件进行版本控制。

如果你是一个图形或者web设计师,你希望能够保存一张图片或者一个布局的每个版本,那么使用一个版本控制系统(Version Control System)则是很明智的选择。版本控制系统允许你将文件恢复到之前的状态,恢复整个项目至之前的状态,比较随着时间推移发生的变化,看看是谁最后修改了什么东西导致出问题的,谁在何时报告了一个缺陷等等。使用版本控制系统还意味着如果你把东西弄乱了或者弄丢了你可以轻松的恢复他们。而完成这一切只需要很小的开销。

2.1.1本地版本控制系统

许多人进行版本控制的方法就是将文件拷贝到另外一个目录(或者如果他够聪明的话,拷贝到一个带有时间戳的目录),这种方法很常见,因为他实现简单,但是这种方式也是非常容易出错的。你很容易忘了当前正在那个目录从而不小心写入错误的文件或者干脆将不想拷贝的文件拷贝进去了。

要对付这个问题,程序员们在很久以前就开发出了具有一个小型数据库的本地版本控制系统来保存文件的所有变化来进行版本控制,见图1-1。

clip_image001

一个叫做rcs的系统调用是这类VCS工具中非常受欢迎的一个。这个系统调用至今仍然分布在许多的计算机中。甚至在非常受欢迎的MacOS X操作系统中,只要你装了开发者工具,就包含了这个命令。这个工具的基本思路就是跟踪一个版本与另一个版本之间补丁集(patch set,也就是文件之间的不同),并且在硬盘上以特殊的形式记录下来;然后,它可以根据一个个不定重新看到每个版本文件的内容。

2.1.2 集中式版本控制系统

接下来碰到的问题就是需要和别的系统上的开发人员协作。为了解决这个问题,人们开发出了集中式版本控制系统(Centralized Version Control Systems,CVCSs)。这些版本控制系统,例如CVS、SVN和Perforce有一台包含了所有具有版本号的文件的服务器,和若干个从中央签出(check out)文件的客户端。这种模式在很长一段时间成为了版本控制的标准,如图1-2。

clip_image002

这种模式有许多优点,尤其是相比本地版本控制管理来说。例如,每个人一定程度上知道这个项目中别人在干些什么事情。管理员可以细粒度地控制每个人能干什么,而管理一个CVCS比和每个客户端的本地数据库打交道要简单多了。

尽管如此,这种模式也有一些知名的缺点。最明显的一个就是中央服务器的故障。如果中央服务器宕机一小时,那么这段时间谁也不能和别人协同工作,也没办法保存他们正在处理的文件的版本信息。如果中央服务器的硬盘发生损坏,而这时候并没有保存合适的备份,那么你惨了,出了少数客户端上可能保存的几个项目快照(Snapshots),其他所有的东西都丢了——这个项目所有的历史都不复存在了。本地版本控制系统同样有这个问题——任何时候你将整个项目的历史保留在一个地方,那么你就会有丢失所有东西的风险。

2.1.3 分布式版本控制系统

这正是分布式版本控制系统(Distributed Version Control Systems, DVCSs)涉足的领域。在一个DVCS系统中(例如Git、Mercurial、Bazaar和Darcs),客户端不是仅仅签出文件的最近快照,而是保存整个工厂的镜像。因此,如果某个服务器挂了,这些系统通过它协作,任何一个客户端工厂都可以拷给服务器用来恢复。任何一次签出实际上是所有数据的一个备份,如图1-3:

clip_image003

此外,这种系统可以很好的同时和多个远程工厂打交道。因此,你可以在一个项目内同时和不同团体以不同的方式协作。这样允许你设置不同类型的工作流程,而这在传统的集中式版本控制系统中是不可能的。

2.2 Git简史

同许多伟大的事物一样,Git诞生于一个创造性的毁灭和巨大的争议中(原文:Git began with a bit of creative destruction and fiery controversy)。Linux内核是一个超大规模的开源软件项目。对于Linux内核维护的大部分时间(1991-2002),软件的修改变更都是通过不定和归档文件传递的。2002年,Linux内核项目开始使用一个叫做BitKeeper的专有的分布式版本控制系统。

2005年,Linux内核开发社区与BitKeeper的研发公司之间闹僵了,而这个工具的免费使用权被收回了。这提醒了Linux研发社区(尤其是Linux的创始人Linus Torvalds)利用在使用BitKeeper过程中的体会开发属于自己的工具。这个新系统的一些目标如下:

  • 快速
  • 设计简单
  • 对于非线性开发(数以千计的并行分支)的强大支持
  • 完全分布式
  • 能够高效处理像Linux内核这样的超大项目(速度和数据量)

自从2005年诞生以来,Git逐渐演进变得易于使用同时还保持了这些最初的优点。对于大的项目来说,它快速高效,并且对于非线性开发来说有着超乎想象的分支系统(见第三章)。

2.3 Git基础

那么,什么是Git呢?这是一个需要搞清楚的重要问题,因为如果你明白什么是Git以及它的基本工作原理,那么高效的使用Git才可能比较简单。当你学习Git的时候,你最好吧脑子里你知道的关于其他VCS系统,例如SVN、Perforce的所有东西都清除掉。这样的话有助于避免在使用这个工具是产生困惑。Git存储与看待信息的方式与其他系统有很大的不同,尽管用户界面是类似的。明白这些概念可以防止你在使用Git的时候出现困惑。

2.3.1 快照(Snapshots),不是差别(Differences)

Git和SVN以及其他的版本控制系统最大的一个区别是Git看待其数据的方式。概念上来说,其他的版本控制系统将信息存储为一本基于文件变化的列表。这些系统将它们保管的信息看作是一些列文件以及每个文件随着时间推移的变化。如图1-4所示。

clip_image005

Git并不是这样存储与看待它的数据的。相反,Git更多的把它的数据看成于一个小型文件系统的一组快照。每一次你提交或者在Git中保存你的项目的状态,它首先做一个当前你的所有文件的快照,然后存储对这个快照的引用。为了保证效率,如果文件没有发生变化,Git不会再次保存文件——而是仅仅链接到之前那个已经存储过的文件。如图1-5所示。

clip_image007

这是Git和几乎所有其他的VCS之间的一个重要的区别。这使得Git几乎重新考虑了所有其他VSC系统的所有方面的设计。这使得Git相比于一个单纯的VCS系统,更像是一个带有一系列功能极其强大的工具构建于其上的小型文件系统。我们将会在讲到第三章Git分支的时候体会到以这种方式看待数据所带来的好处。

2.3.2 几乎所有的操作都在本地

大部分Git的操作都只需要本地的文件和资源来进行——一般来说不需要从网络上其他计算机获取任何信息。如果你习惯于那些每个操作几乎都有网络延迟的集中式版本控制系统,那么Git的这方面特点会让你觉得它具有上帝的力量。由于项目完整的历史都保存在本地,因此几乎所有的操作都会立刻完成。

例如,要浏览整个项目的历史,Git不需要去远程服务器获取历史然后展现给你——它只需要从本地数据库中直接读取。这意味着你几乎即刻就能看到项目历史。如果你想看一个文件当前的版本和一个月前版本的变化,Git可以查找一个月前的这个文件并且做一个本地的差别计算,而不需要让远程服务器做或者pull到本地然后做本地差别计算。

这意味着如果你断网或者没连接***也几乎没有什么你不能做的。如果你在飞机或者火车上并且想做点工作,你可以开心的提交修改然后等到有网的时候再上传。如果你在家,然后***客户端不能连接,你依然可以工作。而在其他的版本控制系统,这种情况要么不可能发生,要么很费劲。例如,在Perforce中,如果没连接到服务器,你做不了什么东西;在CVS和SVN中,你可以编辑文件,但是不能提交到数据库中(除非数据库是离线的)。这一点乍一看似乎没什么大不了,但是慢慢的你会被这个变化能带来的好处shock到的。

2.3.3 Git具有完整性

Git中的所有东西在保存前都会进行校验和计算然后接下来通过这个checksum来进行引用。这意味着不可能在Git不知道的情况下修改Git管理的任何一个文件或者目录。这个功能在底层内置于Git中并且行程其设计哲学的一部分。如果文件在传输中数据丢失或者文件损坏了,Git立马能检测到。

Git使用SHA-1哈希算法来计算校验和。这是一个40位的十六进制字符串,然后根据Git中的文件内容或者目录结构进行计算。一个SHA-1哈希看起来像这样:24b9da6552252987aa493b52f8696cd6d3b00373。

在Git中到处都是用了这种哈希值,以至于你到处都可以看到他们。事实上,Git存储文件不是靠文件名,在其数据库中可寻址的存储其内容的hash值。

2.3.4 Git只添加数据

当你在Git中做操作,几乎所有的操作都只会向数据库中添加数据。所以所有的操作几乎都是可以撤销或者擦除的。类似任何一个VCS,你可以丢失或者弄乱那些还没有提交的变化,但是一旦你提交一个快照到Git,就不会丢失,尤其是当你定期将你的数据库push到另一个仓库中去。

这使得使用Git成为一种享受,因为我们知道,我们可以随便实验,不用担心把东西彻底弄糟。更加深入的了解Git如何存储数据以及如何恢复看起来已经丢失的数据,详见第九章内容。

2.3.5 三种状态

注意啦。关于一点你需要特别注意,Git中的文件有三种主要的状态:已提交(committed)、已修改(modified)、暂存状态(staged)。提交状态意味着数据已经安全的提交到数据库中。修改状态意味着你有修改文件,但是还没有安全的提交到数据库中。暂存状态意味着你已经将一个已修改状态的文件放入下一个要提交的快照中。

Git中的项目有三个主要部分:Git目录、工作目录和暂存区域。

clip_image009

Git目录是Git为你的项目存放元数据和对象数据库的地方。这是Git中最重要的部分,当你从别的电脑拷贝一个仓库时拷贝的就是这部分东西。

工作目录是项目某个版本的一个checkout。这些文件是从Git目录中的压缩了的数据库中pull out出来然后存放在你的硬盘供你使用和修改的。

暂存区域是一个文件,它存放在Git目录中用以记录下一次需要提交的文件。暂存区域又有时被叫做是索引,但是现在它的标准叫法是暂存区域。

基本的Git工作流程如下:

1. 你在工作空间中修改文件

2. 暂存文件,将它们的快照放进暂存区

3. 提交——将暂存区文件的快照永久存储进Git目录。

如果某个文件的特定版本已经在Git中,那么它被视为已经提交。如果已经修改尚未提交,也未放入暂存区,视为已修改状态。如果已经添加进暂存区,视为暂存状态。

2.4 安装Git

要开始使用Git,首先得安装Git。你有几种方式获得Git;两种主要的方式是从源代码安装以及选择你的平台上的安装包。

2.4.1 从源代码安装

如果可以的话,从源代码安装Git非常有用,因为这样可以安装最近的版本。Git的每个版本会包含有用的UI增强元素,如果你觉得从源码编译软件是一件很舒服的事情,那么你就可以获取最新的版本。

要安装Git,你需要安装以下的依赖包:curl、zlib、openssl、expat和libiconv。例如如果你的系统有yum或者apt-get,你就可以使用下面的命令安装依赖包:

$ yum install curl-devel expat-devel gettext-devel \

openssl-devel zlib-devel

$ apt-get install libcurl4-gnutls-dev libexpat1-dev gettext \

libz-dev libssl-dev

如果所有需要的包已经具备,你可以继续然后抓取Git官方网站上最近的快照:

http://git-scm.com/download

然后,编译并且安装:

$ tar -zxf git-1.7.2.2.tar.gz

$ cd git-1.7.2.2

$ make prefix=/usr/local all

$ sudo make prefix=/usr/local install

完成之后你可以通过Git获得Git:

$ git clone git://git.kernel.org/pub/scm/git/git.git

2.4.2 在Linux上安装

如果你要在Linux通过二进制包安装Git,你可以使用你的系统发行版自带的基本的包管理工具安装,如果你在Fedora,你可以使用yum:

$ yum install git-core

如果你在一个基于Debian的发行版,例如Ubuntu,试试apt-get:

$ apt-get install git-core

2.4.3 在Mac上安装

在Mac上有两种简单地方式安装Git。最简单的是使用图形Git安装器,可以从Google Code的页面下载,见图1-7:

http://code.google.com/p/git-osx-installer

clip_image011

另一个主流的方式是使用MacPorts(http://www.macports.org)。如果你安装了MacPorts,你可以这样安装Git:

$ sudo port install git-core +svn +doc +bash_completion +gitweb

你不需要添加所有的附加包,如果你需要使用Git处理SVN仓库,那么你需要加上+svn包。

2.4.4 在Windows上安装

在Windows上安装Git非常简单,msysGit项目有一个简单地安装过程,只需要下载安装文件并运行就好了:

http://code.google.com/p/msysgit

安装完之后,包含命令行版本和标准GUI。

2.5 初次使用Git的设置

既然你已经安装了Git,你可能想对自己的Git环境做一些个性化设置。这些事情你只需要做一次,及时更新这些设置依然会保留。当然你也可以随后通过命令再次改变这些设置。

Git有一个叫做git config的工具,他可以让你获取并且设置配置变量来设置Git看起来怎样,怎么操作。这些变量可以在三个地方存储:

  • /etc/gitconfig文件:包含适用于系统中每个用户以及他们所有的仓库的变量值。如果你传--system选项给git config,那么Git会从这个文件读写。
  • ~/.gitconfig文件:只对当前用户生效。如果你传递--global给git config,那么Git会从这个文件中读写。
  • 在任意一个你所工作的仓库的Git目录下面的配置文件(.git/config):只对当前这个仓库生效。没一个级别的配置会覆盖上一级别的配置。

在Windows中。Git回去$HOME中去找配置文件(C:\Documents and

Settings\$USER),它还会去查找/etc/gitconfig。

2.5.1 你的身份

设置Git的第一件事就是需要设置你的名字和email,这一点很重要,因为每次提交,Git都需要使用这些信息。这些信息不可变的传递进commit的信息里:

$ git config --global user.name "John Doe"

$ git config --global user.email johndoe@example.com

再说一遍,如果你传递--global选项,那么这件事情你只需要做一次就可以了,当你在这个系统上做任何事情Git都会自动的去使用这些信息。如果你需要对特定的项目用另一个姓名或者email去覆盖之前的设置,你可以运行上面的命令不加--global选项。

2.5.2 你的编辑器

既然身份信息已经确立下来了,接下来你可以配置当需要输入信息时,Git默认使用的文本编辑器了。默认情况下,Git会使用你的系统的默认编辑器,一般来说是Vi或者Vim。如果你想使用其他的编辑器,例如Emacs,你可以这样:

$ git config --global core.editor emacs

2.5.3 你的Diff工具

另外一个有用的选项你可能需要配置的是默认的diff工具用来解析合并的冲突,假设你想使用vimdiff,你可以:

$ git config --global merge.tool vimdiff

Git支持kdiff3、tkdiff、meld、xxdiff、emerge、vimdiff、gvimdiff、ecmerge、和opendiff。你也可以设置一个自定义的工具,详见第七章相关内容。

2.5.4 检查你的设置

如果你需要检查一下你的设置,可以使用git config --list命令来列出所有的设置:

$ git config --list

user.name=Scott Chacon

user.email=schacon@gmail.com

color.status=auto

color.branch=auto

color.interactive=auto

color.diff=auto

...

你可能会看到一些重复的key这是因为Git会从不同的文件中去读取key值。在这个例子中,Git使用每个key的最后一个值。

你还可以通过git config {key}来查看特定key的值。

$ git config user.name

Scott Chacon

2.6 获取帮助

如果你在使用Git的时候需要帮助,有三种方法可以查看任何Git命令的帮助文档:

$ git help <verb>

$ git <verb> --help

$ man git-<verb>

你可以运行下面的命令来获得config命令的manpage:

$ git help config

这些命令非常好,因为即使离线状态你也可以使用它们。如果本书和这些manpage还不够用来解决你的问题,你可以试试Freenode IRC服务器上的#git或者#github频道。这些频道里面有很多熟悉Git的人,他们往往会愿意帮助你。

2.7 小结

你需要对Git是什么以及为什么Git与其他一些你正在使用的集中式版本控制系统不同有一些基本的了解。你现在应该已经有了一个Git版本并且已经设置了你的个人信息,是时候学点Git基础了。