版本控制介绍
版本控制系统之前如何维护文档的版本
集中式和分布式
集中式版本控制
集中式版本控制,版本库是集中存放在中央服务器的,用的都是自己的电脑干活,所以要先从中央服务器取得最新的版本,然后再开始干活,干完活了,再把自己的活推送给中央服务器。需要联网。
有代表性的软件:cvs、 svn
分布式版本控制
分布式版本控制系统根本没有“中央服务器”,每个人的电脑上都是一个完整的版本库,这样,你工作的时候,就不需要联网了,因为版本库就在你自己的电脑上。为了多人协同开发时,同事之间交换版的方便,可以定一个中央服务器,只是用于多人之间的版本交换和比对。不需要联网
有代表性的软件: git
1 Git 使用
1.1 简单介绍
很多人都知道,Linus在1991年创建了开源的Linux,从此,Linux系统不断发展,已经成为最大的服务器系统软件了。
Linus虽然创建了Linux,但Linux的壮大是靠全世界热心的志愿者参与的,这么多人在世界各地为Linux编写代码,那Linux的代码是如何管理的呢?
事实是,在2002年以前,世界各地的志愿者把源代码文件通过diff的方式发给Linus,然后由Linus本人通过手工方式合并代码!
你也许会想,为什么Linus不把Linux代码放到版本控制系统里呢?不是有CVS、SVN这些免费的版本控制系统吗?因为Linus坚定地反对CVS和SVN,这些集中式的版本控制系统不但速度慢,而且必须联网才能使用。有一些商用的版本控制系统,虽然比CVS、SVN好用,但那是付费的,和Linux的开源精神不符。
不过,到了2002年,Linux系统已经发展了十年了,代码库之大让Linus很难继续通过手工方式管理了,社区的弟兄们也对这种方式表达了强烈不满,于是Linus选择了一个商业的版本控制系统BitKeeper,BitKeeper的东家BitMover公司出于人道主义精神,授权Linux社区免费使用这个版本控制系统。
安定团结的大好局面在2005年就被打破了,原因是Linux社区牛人聚集,不免沾染了一些梁山好汉的江湖习气。开发Samba的Andrew试图破解BitKeeper的协议(这么干的其实也不只他一个),被BitMover公司发现了(监控工作做得不错!),于是BitMover公司怒了,要收回Linux社区的免费使用权。
Linus可以向BitMover公司道个歉,保证以后严格管教弟兄们,嗯,这是不可能的。实际情况是这样的:
Linus花了两周时间自己用C写了一个分布式版本控制系统,这就是Git!一个月之内,Linux系统的源码已经由Git管理了!牛是怎么定义的呢?大家可以体会一下。
Git迅速成为最流行的分布式版本控制系统,尤其是2008年,GitHub网站上线了,它为开源项目免费提供Git存储,无数开源项目开始迁移至GitHub,包括jQuery,PHP,Ruby等等。
历史就是这么偶然,如果不是当年BitMover公司威胁Linux社区,可能现在我们就没有免费而超级好用的Git了。
1.2 安装 Git
linux 安装
yum install git
假如多人协作开发,应该在每个使用者的机器上安装 git
1.3 初始化版本库
什么是版本库呢?版本库又名仓库,英文名repository,可以简单理解成一个目录,这个目录里面的所有文件都可以被Git管理起来,每个文件的修改、删除,Git都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以“还原”。
1.3.1 创建版本库:
- 首先,选择一个合适的地方,创建一个空目录
$ git init # 初始化,把当前目录变为由 git 管理的版本库
Initialized empty Git repository in /Users/yanshunjun/Desktop/mygithub/.git/
$ ls -a
. .. .git
可以看到在当前目录下会创建一个隐藏的文件夹 .git 轻易不用动它里面的任何文件,因为这个目录是 Git 来跟踪和管理版本库用的,假如你搞坏了,它就会给你点儿颜色看(Git 仓库就会被破坏)。
- 非空目录其实也是可以创建仓库的,不过不建议这么干。有必要吗!
1.3.2 版本库(Repository)
.git 目录就是 Git 的版本库
Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支 master(通常称为主分支),以及指向 master 的一个指针叫HEAD
- 分支和指针后面再讲
1.4 工作区、暂存区和 master 分支
Git 和 SVN 不同之一,就是有 工作区、暂存区的概念
- 工作区: 用来平时的开发、编辑文件之用,在你创建的仓库目录下,就是工作区
- 暂存区: 用来暂时存放准备提交到仓库的文档的地方,在 .git 目录下。
- master 分支: 真正用来存放和发布已经完成的代码文件的地方,在 .git 目录下。
1.4.1 三者的关系位置见下图
-
最初文件在工作区
git add readme.txt 后,文件被添加到暂存区,此时工作区的文件和暂存区的文件一致。
-
git commit -m "new file readme.txt" 后,在暂存区的所有文件和目录都将后被提交(移动)到分支 master。
而此时,工作区的文件会和当前分支 master 的文件一致,而暂存区没有任何文件,是清洁的。
总结: 一个文件被提交到版本库的基本流程是:
1. 在你的工作区创建编写你的代码文件 readme.txt (当然也包括目录)
2. 用命令 git add readme.txt 将文件 readme.txt 放到暂存区,这个可以多次执行添加
3. 用命令 git commint -m "new file readme.txt" 将暂存区的所有文件和目录一起提交到 master
可以多次添加,一次提交
1.4.2 实操:
$ pwd
/Users/yanshunjun/Desktop/mygithub
$ mkdir study
$ cd study
$ vi readme.txt
$ cd ..
$ git add study # 我这里是把目录一起提交了
$ git commit -m "crete a readme file"
[master (root-commit) 63e4ecd] crete a readme file
1 file changed, 2 insertions(+)
create mode 100644 study/readme.txt
- 强调一下, git commit 的 -m 参数后面跟的是关于这次提交版本的描述信息。 这个参数不是必须的,但是强烈要求这么干,这样便于以后自己对版本回滚操作,协同开发时,也便于其他人员可以获取到每次提交改动的基本信息
暂存区是Git非常重要的概念,弄明白了暂存区,就弄明白了Git的很多操作到底干了什么。
1.5 时空穿越
git 支持版本的回滚操作,并且,你可以在之前任何一个版本和当前最新有效提交后的版本之间来回切换。
1.5.1 提交修改
之前,我们知道了如何创建一个新的文件 readmi.txt ,并提交到仓库;现在让我们来修改这个文件,内容变为这样:
Git is a distributed version control system.
Git is free software.
并且再创建一个新的空文件 test.txt 和空文件夹 newdir
bash-3.2$ pwd
/Users/yanshunjun/Desktop/mygithub
bash-3.2$ vi study/readme.txt
bash-3.2$ touch test.txt;mkidr newdir
- 观察一下仓库的最新变化和状态
bash-3.2$ git status
On branch master
Changes not staged for commit: # 未提交的更改
(use "git add ..." to update what will be committed)
(use "git checkout -- ..." to discard changes in working directory)
modified: study/readme.txt # 已经修改的文件
Untracked files: # 没有被添加过的文件
(use "git add ..." to include in what will be committed)
test.txt
no changes added to commit (use "git add" and/or "git commit -a")
空的目录是不会被 Git 跟踪的,也没这个必要!
- 可以看看被修改过的文件,到底修改了哪些内容
bash-3.2$ git diff study/readme.txt
diff --git a/study/readme.txt b/study/readme.txt
index 46d49bf..9247db6 100644
--- a/study/readme.txt
+++ b/study/readme.txt
@@ -1,2 +1,2 @@
-Git is a version control system. # 修改前的内容
+Git is a distributed version control system. # 修改后的内容
Git is free software.
(END)
- 之后一起放到暂存区
bash-3.2$ git add .
注意上面命令中最后的 点
- . 会把当前目录下需要提交的所有文件和目录放到暂存区
提交前可以再次观察下仓库的状态
bash-3.2$ git status
On branch master
Changes to be committed: # 下面的文件将会被提交
(use "git reset HEAD ..." to unstage)
modified: study/readme.txt
new file: test.txt # 第一次被添加后的状态为 new file
- 提交到仓库
bash-3.2$ git commit -m "add distributed"
[master a34d237] add distributed
2 files changed, 1 insertion(+), 1 deletion(-)
create mode 100644 test.txt
- 再次观察仓库的状态
bash-3.2$ git status
On branch master
nothing to commit, working tree clean # 不需要提交,工作区是清洁的
1.5.2 回到过去(版本的回滚)
想象一种场景,你把你代码写好,提交到版本库,准备发布 v1.0。但此时,你的老板说要添加一个新的功能。于是你就在原来的代码文件的基础上修改添加,又再次提交到版本库。可老板这时候,又反悔了,说这个功能不能现在添加。那你是不是又要,再次修改呢?有了git 当然不用,此时你就需要版本回滚,滚到原来最初的版本。
让我们来模拟一下
- 首先把 readme.txt 文件的内容修改成下面的样子
Git is a distributed version control system.
Git is free software distributed under the GPL.
- 然后提交修改后的文件
bash-3.2$ vi study/readme.txt
bash-3.2$ git status
On branch master
Changes not staged for commit:
(use "git add ..." to update what will be committed)
(use "git checkout -- ..." to discard changes in working directory)
modified: study/readme.txt
no changes added to commit (use "git add" and/or "git commit -a")
bash-3.2$ git add .
bash-3.2$ git status
On branch master
Changes to be committed:
(use "git reset HEAD ..." to unstage)
modified: study/readme.txt
bash-3.2$ git commit -m "add GLP for readme.txt"
[master da197f4] add GLP for readme.txt
1 file changed, 1 insertion(+), 1 deletion(-)
bash-3.2$ git status
On branch master
nothing to commit, working tree clean
- 验证最新提交后的版本
bash-3.2$ pwd
/Users/yanshunjun/Desktop/mygithub
bash-3.2$ cat study/readme.txt
Git is a distributed version control system.
Git is free software distributed under the GPL.
- 准备版本回退
在回退版本之前,我们先来回想一下 readme.txt 文件共修改了几次, 3 次对吧。但实际的开发中,有很多文件,一个文件里会有上千行代码,修改过的次数远远超出了你的智商能够承受的范围。怎么办? Git 早就为你想好了。
git log 命令可以查看提交的版本历史
commit da197f447342e65bbf37f5b2e609c71d52db7955 (HEAD -> master)
Author: sharkgit1976
Date: Sun Oct 15 10:04:23 2017 +0800
add GLP for readme.txt
commit a34d2370138d520d1fabc1aa2acc2d234047a39a
Author: sharkgit1976
Date: Sat Oct 14 17:31:19 2017 +0800
add distributed
commit 63e4ecd9409ff1679b8367c116a1c68f045af88d
Author: sharkgit1976
Date: Sat Oct 14 16:16:22 2017 +0800
crete a readme file