版本控制系统可以分为集中式(CVCS, Centralized Version Control System, 例如CVS、Subversion)和分布式(DVCS, Distributed Version Control System,例如Git)版本控制系统。
传统的集中式版本控制系统,本地只保存代码库的一个版本拷贝。 所有历史版本都保存在服务器。GIT 与之最大的不同是,本地不仅保存一个快照,而且保存着整个代码库(repository)。因此它可以“离线”工作。
GIT 使用 SHA-1 哈希码(40个字符)来标识提交,同时保证本次提交后整体(一个快照)的完整性。
文件状态分为:未跟踪 (untracked) 和已跟踪 (tracked),已跟踪又分为三种状态: 已暂存(staged),已修改(modified),已提交(committed)
一般过程如下:
1) 新建文件,该文件状态为“未跟踪”,位于工作区;
2) 用 git add a.txt 加入该文件,状态变为已跟踪的“已暂存”,位于暂存区;
3) 用 git commit a.txt -m "ha" 提交该文件,状态变为“已提交”,位于代码库(repository )。
当文件处于已跟踪的状态下,
4)编辑该文件并保存,状态变为“已修改”,位于工作区;
5) 重复步骤2、3,可提交代码至代码库。
我们创建一个测试项目来感受下如何通过命令行,使用Git对文件进行版本控制。
创建版本库
在多数版本控制系统,例如Subversion,工作目录与版本库是分开存放的。而在Git中,版本库(.git目录)是与工作目录树(Working Trees)并排放在同一个目录中的。
在Git中创建版本库,首先要决定把项目源代码存放在哪里。本例中,要创建一个简单的HTML页面,所以给这个项目取名为test。首先创建一个同名目录“test”,并进入到这个目录,然后输入命令git init。整个过程如下:
D:\test>git init
Initialized empty Git repository in D:/test/.git/
创建完成。从现在开始,这个Git版本库就可以用来记录和跟踪该项目的代码了。
添加初始文件
前面的操作已经创建了一个空版本库,现在该往里添加文件了。现在我们创建一个名为index.html的文件,并添加标题文本“Hello world”。详细内容如下:
<html>
<body>
<h1>Hello World!</h1>
</body>
</html>
创建了一个简单的HTML文件后,就可以开始跟踪版本了。我们会向这个文件不断添加更多的内容。要想让Git跟踪这个文件,须先让它知道这个文件要分两步走:首先使用git add命令把该文件添加到版本库的索引(index);然后使用git commit命令提交。
D:\test>git add index.html
D:\test>git commit -m "inital version"
[master (root-commit) 96707ef] inital version
1 file changed, 5 insertions(+)
create mode 100644 index.html
文件或文件列表可以作为git add命令的参数。
git commit命令创建一个提交记录。提交记录是存储在版本中的历史记录,每提交一次创建一个记录,并标记出代码的演进。Git把提交者的姓名和邮件地址,以及提交留言,都添加到提交记录中。
前面命令中参数-m的作用是,告诉Git本次提交的注释为initial version。对于任何版本控制系统,适当书写的提交留言都是极其重要的。它可以说明提交的原因:新添加的文件是做什么用的?修改那行代码的原因是什么?
现在我们已经提交了一个文件到版本库中。运行命令git log可以看到这个提交相关的信息:
D:\test>git log
commit 96707ef87920925b664ea3cafc5c4926bee20de8
Author: jag <[email protected]>
Date: Fri Sep 19 09:23:47 2014 +0800
inital version
命令git log运行后输出的第一行显示提交名称,该名称是Git自动产生的SHA-1码。Git通过它来跟踪提交。Git使用该哈希码可以保证每个提交的名称都是独一无二的。这在分布式的环境中非常重要。第二行是提交者的信息。第三行是提交日期。第四行是提交的注释。
用命令git commit显示的七位字符来表示一个提交,通常已经足够了,没有必要使用完整的40位哈希码。但是命令git log将显示完整的40位哈希码。
修改文件
下面开始学习怎样处理文件修改。
刚才的HTML文件里还没有<head>和<title>元素。下面为该文件添加这些元素:
<html>
<head>
<title>Hello World in Git</title>
</head>
<body>
<h1>Hello World!</h1>
</body>
</html>
修改完毕,Git可以检测到文件被修改。命令git status会显示工作目录树的状态,即当前的视图状态。Git中的工作目录树与Subversion和CVS中的工作拷贝差不多是一个概念。
D:\test>git status
On branch master
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: index.html
no changes added to commit (use "git add" and/or "git commit -a")
上面的输出结果表明Git检测到了修改,但还不知道如何处理它们。修改过的文件在Changed but not updated下列出来,如果要提交,须要暂存(stage)修改。
暂存修改,以准备把修改提交到版本库。Git中有三个地方可以存放代码。第一个地方是工作目录树,编辑文件时可以直接在这里操作。第二个是索引(index),也就是暂存区(staging area)。暂存区是工作目录树和版本库之间的缓冲区。第三个是版本库。暂存区中存放的是准备提交到版本库中的修改。
回头看命令git add,它可以暂存对index.html刚刚做的修改。它跟前面添加一个新文件时使用的是同一个命令,只不过,这次它告诉Git要跟踪的是一个新的修改而非新的文件。
D:\test>git add index.html
D:\test>git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: index.html
暂存修改过的index.html后,执行命令git status可以看到,输出信息中的标题从Changed but not updated变成了Changes to be committed。如果打开颜色开关,index.html这一行会由红色变为绿色。
使用命令git commit时,不要忘记使用带-m的参数,并在参数后面加上提交注释,以解释修改的原因。如下所示:
D:\test>git commit -m "add <head> and <title> to index"
[master 12e743e] add <head> and <title> to index
1 file changed, 3 insertions(+)
命令git log可以快速浏览提交的注释。
D:\test>git log
commit 12e743e19386b25ed22d8dc8ac49771233774e26
Author: jag <[email protected]>
Date: Fri Sep 19 09:57:54 2014 +0800
add <head> and <title> to index
commit 96707ef87920925b664ea3cafc5c4926bee20de8
Author: jag <[email protected]>
Date: Fri Sep 19 09:23:47 2014 +0800
inital version
获取历史文件
如果要获取某个老版本的文件,则可以使用git checkout命令,并指定文件名,如下所示:
D:\test>git checkout ed941ed97975757490256fb2b956c27d900e1059 index.html
一旦熟悉了以上命令后,我们使用GUI进行可视化操作时也将信手拈来,如下图所示:
到目前为止,我们已经感受了如何使用Git,包括添加新文件、修改文件、查看版本库的历史记录等。
参考资料:
《版本控制之道:使用Git》