一、关于版本控制
什么是版本控制?我真的需要吗?版本控制是一种记录若干文件内容变化,以便将来查阅特定版本修订情况的系统。在本书所展示的例子中,我们仅对保存着软件源代码的文本文件作版本控制管理,但实际上,你可以对任何类型的文件进行版本控制。
如果你是位图形或网页设计师,可能会需要保存某一幅图片或页面布局文件的所有修订版本(这或许是你非常渴望拥有的功能)。采用版本控制系统 (VCS)是个明智的选择。有了它你就可以将某个文件回溯到之前的状态,甚至将整个项目都回退到过去某个时间点的状态。你可以比较文件的变化细节,查出最 后是谁修改了哪个地方,从而导致出现怪异问题,又是谁在何时报告了某个功能缺陷等等。使用版本控制系统通常还意味着,就算你乱来一气把整个项目中的文件改 的改删的删,你也照样可以轻松恢复到原先的样子。但额外增加的工作量却微乎其微。
本地版本控制系统
许多人习惯用复制整个项目目录的方式来保存不同的版本,或许还会改名加上备份时间以示区别。这么做唯一的好处就是简单。不过坏处也不少:有时候会混淆所在的工作目录,一旦弄错文件丢了数据就没法撤销恢复。为了解决这个问题,人们很久以前就开发了许多种本地版本控制系统,大多都是采用某种简单的数据库来记录文件的历次更新差异(见图 1-1)。
其中最流行的一种叫做 rcs,现今许多计算机系统上都还看得到它的踪影。甚至在流行的 Mac OS X 系统上安装了开发者工具包之后,也可以使用 rcs 命令。它的工作原理基本上就是保存并管理文件补丁(patch)。文件补丁是一种特定格式的文本文件,记录着对应文件修订前后的内容变化。所以,根据每次 修订后的补丁,rcs 可以通过不断打补丁,计算出各个版本的文件内容。
集中化的版本控制系统
接下来人们又遇到一个问题,如何让在不同系统上的开发者协同工作?于是,集中化的版本控制系统( Centralized Version Control Systems,简称 CVCS )应运而生。这类系统,诸如 CVS,Subversion 以及 Perforce 等,都有一个单一的集中管理的服务器,保存所有文件的修订版本,而协同工作的人们都通过客户端连到这台服务器,取出最新的文件或者提交更新。多年以来,这 已成为版本控制系统的标准做法(见图 1-2)。
这种做法带来了许多好处,特别是相较于老式的本地 VCS 来说。现在,每个人都可以在一定程度上看到项目中的其他人正在做些什么。而管理员也可以轻松掌控每个开发者的权限,并且管理一个 CVCS 要远比在各个客户端上维护本地数据库来得轻松容易。
事分两面,有好有坏。这么做最显而易见的缺点是中央服务器的单点故障。如果宕机一小时,那么在这一小时内,谁都无法提交更新,也就无法协同工作。要 是中央服务器的磁盘发生故障,碰巧没做备份,或者备份不够及时,就还是会有丢失数据的风险。最坏的情况是彻底丢失整个项目的所有历史更改记录,而被客户端 提取出来的某些快照数据除外,但这样的话依然是个问题,你不能保证所有的数据都已经有人事先完整提取出来过。本地版本控制系统也存在类似问题,只要整个项 目的历史记录被保存在单一位置,就有丢失所有历史更新记录的风险。
分布式版本控制系统
于是分布式版本控制系统( Distributed Version Control System,简称 DVCS )面世了。在这类系统中,像 Git,Mercurial,Bazaar 以及 Darcs 等,客户端并不只提取最新版本的文件快照,而是把原始的代码仓库完整地镜像下来。这么一来,任何一处协同工作用的服务器发生故障,事后都可以用任何一个镜 像出来的本地仓库恢复。因为每一次的提取操作,实际上都是一次对代码仓库的完整备份(见图 1-3)。
更进一步,许多这类系统都可以指定和若干不同的远端代码仓库进行交互。籍此,你就可以在同一个项目中,分别和不同工作小组的人相互协作。你可以根据需要设定不同的协作流程,比如层次模型式的工作流,而这在以前的集中式系统中是无法实现的。(来源:http://blog.jobbole.com/25775/)
常见的版本管理软件:
版本管理的发展过程:
常用术语:
•分支(Branch): 在一个时间点,复制一份处于版本控制之下的文件,从这之后,这两份拷贝就可以独立的互不干扰的进行各自开发。
二、git简介
Git是一个免费的开放源码的 分布式版本控制系统,用于处理从小到大的项目,速度和效率的一切。
Git 易于学习,具有 闪电般快速的性能,占地面积小。它超越了像Subversion,CVS,Perforce和ClearCase这样的SCM工具,具有便宜的本地分支,便利的分段区域和 多个工作流等功能。
git诞生:
git发展:
git设计目标:
git工作模式:
版本库初始化
个人计算机从版本服务器同步
操作
90%以上的操作在个人计算机
添加文件
修改文件
提交变更
查看版本历史等
版本库同步
将本地修改传送
到版本服务器
git文件存储:
二、git基础
git文件状态:
GIT文件
已被版本库管理的文件
已修改
在工作目录修改GIT文件
已暂存
对已修改的文件执行git暂存操作,将文件存入了暂存区
已提交
将已暂存的文件执行git提交操作,将文件存入对象库
本地服务器与服务器版本库
git安装
1、安装依赖
yum install curl-devel expat-devel gettext-devel openssl-devel zlib-devel gcc perl-ExtUtils-MakeMaker -y
2、编译安装
wget https://github.com/git/git/archive/v2.7.4.zip
unzip v2.7.4.zip
cd git-2.7.4
make prefix=/usr/local/git all
make prefix=/usr/local/git install
rm -rf /usr/bin/git
ln -s /usr/local/git/bin/git /usr/bin/git
git --version
配置用户信息
这两条配置很重要,每次 Git 提交时都会引用这两条信息,说明是谁提交了更新,所以会随更新内容一起被永久纳入历史记录:
[root@linux-node1 test]# git config --global user.name "zhangyang"
[root@linux-node1 test]# git config --global user.email 992747643@qq.com
查看配置信息:
[root@linux-node1 test]# git config --list
user.name=zhangyang
user.email=992747643@qq.com
core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true
三、git的相关操作
1、创建版本库
[root@linux-node1 ~]# mkdir project
[root@linux-node1 ~]# cd project/
[root@linux-node1 project]# git init
初始化空的 Git 仓库于 /root/project/.git/
[root@linux-node1 project]# ls -la
总用量 4
drwxr-xr-x 3 root root 17 5月 8 21:38 .
dr-xr-x---. 15 root root 4096 5月 8 21:38 ..
drwxr-xr-x 7 root root 111 5月 8 21:38 .git
2、添加到版本库
[root@linux-node1 project]# touch test1
[root@linux-node1 project]# git add test1
[root@linux-node1 project]# git status
位于分支 master
初始提交
要提交的变更:
(使用 "git rm --cached <文件>..." 以取消暂存)
新文件: test1
3、提交到版本库
[root@linux-node1 project]# git commit -m "first commit"
[master(根提交) fbaa9b5] first commit
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 test1
[root@linux-node1 project]# git status
位于分支 master
无文件要提交,干净的工作区
4、版本回滚
[root@linux-node1 project]# echo "v1" >test1.txt
[root@linux-node1 project]# cat test1.txt
v1
[root@linux-node1 project]# git add test1.txt
[root@linux-node1 project]# git commit -m "first commit v1"
[master(根提交) e915a51] first commit v1
1 file changed, 1 insertion(+)
create mode 100644 test1.txt
[root@linux-node1 project]# echo "v2" >test1.txt
[root@linux-node1 project]# cat test1.txt
v2
[root@linux-node1 project]# git add test1.txt
[root@linux-node1 project]# git commit -m "commit v2"
[master cc3a990] commit v2
1 file changed, 1 insertion(+), 1 deletion(-)
[root@linux-node1 project]# git log
commit cc3a99027ef1615e9f4ec92dee6522f8f764e3fa
Author: zhangyang <992747643@qq.com>
Date: Mon May 8 21:45:04 2017 +0800
commit v2
commit e915a51e7497ce3319f0cce4f97510cfd6269b46
Author: zhangyang <992747643@qq.com>
Date: Mon May 8 21:44:04 2017 +0800
first commit v1
注意:如果嫌输出信息太多可以加上--pretty=oneline参数
[root@linux-node1 project]# git log --pretty=oneline
cc3a99027ef1615e9f4ec92dee6522f8f764e3fa commit v2
e915a51e7497ce3319f0cce4f97510cfd6269b46 first commit v1
回退到 v1
[root@linux-node1 project]# git reset --hard e915a51e7497
HEAD 现在位于 e915a51 first commit v1
[root@linux-node1 project]# cat test1.txt
v1
[root@linux-node1 project]# git log
commit e915a51e7497ce3319f0cce4f97510cfd6269b46
Author: zhangyang <992747643@qq.com>
Date: Mon May 8 21:44:04 2017 +0800
first commit v1
注意:git reset 三个参数
--soft 缓存区和工作目录都不会改变。
--mixed 默认选项,缓存区和你指定的提交同步,单工作目录不受限制影响。
--hard 缓存区和工作目录都同步到你的提交。
5、移除文件
[root@linux-node1 project]# git rm test1.txt
rm 'test1.txt'
[root@linux-node1 project]# ll
总用量 0
[root@linux-node1 project]# git status
位于分支 master
要提交的变更:
(使用 "git reset HEAD <文件>..." 以取消暂存)
删除: test1.txt
--cache 从暂缓区中移除
6、修改文件
[root@linux-node1 project]# cat test1.txt
v1
[root@linux-node1 project]# echo "m v1" >test1.txt
[root@linux-node1 project]# cat test1.txt
m v1
[root@linux-node1 project]# git add test1.txt
[root@linux-node1 project]# git status
位于分支 master
要提交的变更:
(使用 "git reset HEAD <文件>..." 以取消暂存)
修改: test1.txt
[root@linux-node1 project]# git commit -m "commit m v1"
[master 1b1a8a6] commit m v1
1 file changed, 1 insertion(+), 1 deletion(-)
7、撤销修改
[root@linux-node1 project]# cat test1.txt
m v1
[root@linux-node1 project]# echo "m2 v1" >test1.txt
[root@linux-node1 project]# cat test1.txt
m2 v1
[root@linux-node1 project]# git status
位于分支 master
尚未暂存以备提交的变更:
(使用 "git add <文件>..." 更新要提交的内容)
(使用 "git checkout -- <文件>..." 丢弃工作区的改动)
修改: test1.txt
修改尚未加入提交(使用 "git add" 和/或 "git commit -a")
[root@linux-node1 project]# git checkout -- test1.txt
[root@linux-node1 project]# git status
位于分支 master
无文件要提交,干净的工作区
[root@linux-node1 project]# cat test1.txt
m v1
8.创建分支并切换分支
[root@linux-node1 project]# git status
位于分支 master
无文件要提交,干净的工作区
[root@linux-node1 project]# git checkout -b slave
切换到一个新分支 'slave'
[root@linux-node1 project]# git branch --list
master
* slave
git branch 其他操作
用法:git branch [<选项>] [-r | -a] [--merged | --no-merged]
或:git branch [<选项>] [-l] [-f] <分支名> [<起始点>]
或:git branch [<选项>] [-r] (-d | -D) <分支名>...
或:git branch [<选项>] (-m | -M) [<旧分支>] <新分支>
或:git branch [<选项>] [-r | -a] [--points-at]
通用选项
-v, --verbose 显示哈希值和主题,若参数出现两次则显示上游分支
-q, --quiet 不显示信息
-t, --track 设置跟踪模式(参见 git-pull(1))
--set-upstream 改变上游信息
-u, --set-upstream-to <upstream>
change the upstream info
--unset-upstream Unset the upstream info
--color[=<何时>] 使用彩色输出
-r, --remotes 作用于远程跟踪分支
--contains <提交> 只打印包含该提交的分支
--abbrev[=<n>] 用 <n> 位数字显示 SHA-1 哈希值
具体的 git-branch 动作:
-a, --all 列出远程跟踪及本地分支
-d, --delete 删除完全合并的分支
-D 删除分支(即使没有合并)
-m, --move 移动/重命名一个分支,以及它的引用日志
-M 移动/重命名一个分支,即使目标已存在
--list 列出分支名
-l, --create-reflog 创建分支的引用日志
--edit-description 标记分支的描述
-f, --force 强制创建、移动/重命名、删除
--merged <提交> 只打印已经合并的分支
--no-merged <提交> 只打印尚未合并的分支
--column[=<风格>] 以列的方式显示分支
--sort <key> 排序的字段名
--points-at <对象> 只打印指向该对象的分支
9、git merge
[root@linux-node1 project]# echo "v1" >test2.txt
[root@linux-node1 project]# git add test2.txt
[root@linux-node1 project]# git commit -m "first commit v1"
[slave f3a6fe9] first commit v1
1 file changed, 1 insertion(+)
create mode 100644 test2.txt
[root@linux-node1 project]# git status
位于分支 slave
无文件要提交,干净的工作区
[root@linux-node1 project]# git checkout master
切换到分支 'master'
[root@linux-node1 project]# git merge slave
更新 1b1a8a6..f3a6fe9
Fast-forward
test2.txt | 1 +
1 file changed, 1 insertion(+)
create mode 100644 test2.txt
git工作流程图:
四、git常用命令
!评论内容需包含中文