1/28
Git版本控制系统
版本控制系统
功能:版本控制是一种记录一个或若干文件内容变化,以便将来查阅特定版本修订情况的系统。
具体功能:记录文件的所有历史变化随时可恢复到任何一个历史状态多人协作开发或修改错误恢复多功能
并行开发
版本控制系统分类
1、本地版本控制系统(Local VCS)
优点:只能单机使用
缺点:不能实现文件版本信息的资源共享
2、集中化版本控制系统(Centralized VCS)
常用软件:SVN(以前软件开发公司几乎都用这款软件)
优点:集中化管理文件数据的版本,方便、快捷。
缺点:工作在C/S模式下,C端必须跟S端联网才能正常使用,即必须在线使用,不能离线使用
3、分布式版本控制系统(distributed VCS)
常用软件: git 开发者:由linux内核的开发者林纳斯.托瓦兹开发
优点:文件版本数据信息分布存储,支持离线使用。
版本控制系统基本概念
1、repository --- 仓库。存放所有文件及其历史信息
2、checkout --- 取出或切换到指定版本的文件
3、version --- 记录标识一个版本(编号或其他代码)
4、tag --- 标签。记录标识一个主要版本(1.0 2.0 3.0)
Git安装
查:rpm -q git
安装:yum install -y git
查所有文件列表:rpm -ql git
查配置文件列表:rpm -qc
git查git的man手册:man git
版本控制系统介绍
版本控制系统
版本控制是一种记录若干文件内容变化,以便将来查阅特定版本修订情况的系统。大部分时候我们使用最
频繁的还是对源代码文件的版本控制,其实任何文件都可以纳入版本控制系统。
1).更好备份:相比于将不同版本的文件以时间等命名存储备份,使用版本控制系统能节约更多的磁盘空
间,因为版本控制系统不是文件的复制备份,而是差异备份,文件快照备份等等。
2).更好的回溯:可以将某个文件回溯到之前的任何一个提交状态,甚至将整个项目回退到过去的某个时间
点。
3).更好的团队协作:这是最重要的,团队共同开发一款软件,如果没有版本控制,那是不可想象的,简单
点的可以使用文件传输到某一位核心开发者库上进行合并,但如果团队的成员是分散在全国各地的,甚至
2/28
是世界各地的,比如linux内核的开发,那完全是没办法进行的。使用版本控制后,可以比较文件的变化系
统,可以查询是谁提交了新的更新,并且可以由项目负责人管理提交,进行更新的管理。
相比于svn, git有什么优势?
从不同的角度和不同的需求可能都会有不同的观点,这里也只能说明两者的适用情景。
svn属于集中化的版本控制系统:
有一个单一的集中管理的服务器,保存所有文件的修订版本,而协同工作的成员通过客户端连接到这台
服务器,进行文件上传和更新。
优点:
a.使用简单,比较符合我们的常规思维(我当年从SVN转向Git也花费了不少时间)。
b.同步代码比较简单,只要一步操作即可。
缺点:
a.丢失数据的风险:最显而易见的,由于集中化的特点,如果版本库的服务器磁盘发生故障等,你不
能保证所有的数据已经有人提取出来了,最坏的情况是彻底的丢失整个项目的所有历史更改记录。
b.网络中断的情况下,协作就无法进行了,因为无法连接服务器进行上传和更新。
git属于分布式版本控制系统:
客户端并不只提取最新版本的文件快照,而是把原始的代码仓库完整地镜像下来。
优点:
a.由于任何人每次提取操作,实际上都是一次对代码仓库的完整备份,因此近乎所有的操作都可以在
本地执行,速度就是相当的快,并且可以在网络断开的时候操作仍然不受影响,可以频繁的进行提
交
更新,等到有网络的时候再上传到远程的镜像仓库就可以了。
b.文档很详细,并且命令行的提示也很到位,用起来比较得新应手,而且很多的设置与操作跟linux操
作很相近(不亏是linux之父创造的)。
c.git的分支模型,相当的轻量级,被称为“必杀技”。
缺点:
a.每个开发人员都拥有所有的代码,不利于核心代码的保密(如果有重要代码需要保密,则不建议使
用git)
git的历史
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社区的免费使用权。
3/28
Linus可以向BitMover公司道个歉,保证以后严格管教弟兄们,嗯,这是不可能的。实际情况是这样的:
Linus花了两周时间自己用C写了一个分布式版本控制系统,这就是Git!一个月之内,Linux系统的源码已经
由Git管理了!牛是怎么定义的呢?大家可以体会一下。
Git迅速成为最流行的分布式版本控制系统,尤其是2008年,GitHub网站上线了,它为开源项目免费提
供Git存储,无数开源项目开始迁移至GitHub,包括jQuery,PHP,Ruby等等。
历史就是这么偶然,如果不是当年BitMover公司威胁Linux社区,可能现在我们就没有免费而超级好用的
Git了。
集中式vs分布式
Linus一直痛恨的CVS及SVN都是集中式的版本控制系统,而Git是分布式版本控制系统,集中式和分布式版
本控制系统有什么区别呢?
先说集中式版本控制系统,版本库是集中存放在中央服务器的,而干活的时候,用的都是自己的电脑,所
以要先从中央服务器取得最新的版本,然后开始干活,干完活了,再把自己的活推送给中央服务器。中央
服务器就好比是一个图书馆,你要改一本书,必须先从图书馆借出来,然后回到家自己改,改完了,再放
回图书馆。
集中式版本控制系统最大的毛病就是必须联网才能工作,如果在局域网内还好,带宽够大,速度够快,可
如果在互联网上,遇到网速慢的话,可能提交一个10M的文件就需要5分钟,这还不得把人给憋死啊。
那分布式版本控制系统与集中式版本控制系统有何不同呢?首先,分布式版本控制系统根本没有“中央服务
器”,每个人的电脑上都是一个完整的版本库,这样,你工作的时候,就不需要联网了,因为版本库就在你
自己的电脑上。既然每个人电脑上都有一个完整的版本库,那多个人如何协作呢?比方说你在自己电脑上
改了文件A,你的同事也在他的电脑上改了文件A,这时,你们俩之间只需把各自的修改推送给对方,就可
以互相看到对方的修改了。
和集中式版本控制系统相比,分布式版本控制系统的安全性要高很多,因为每个人电脑里都有完整的版本
库,某一个人的电脑坏掉了不要紧,随便从其他人那里复制一个就可以了。而集中式版本控制系统的中央
服务器要是出了问题,所有人都没法干活了。
在实际使用分布式版本控制系统的时候,其实很少在两人之间的电脑上推送版本库的修改,因为可能你们
4/28
俩不在一个局域网内,两台电脑互相访问不了,也可能今天你的同事病了,他的电脑压根没有开机。因
此,分布式版本控制系统通常也有一台充当“中央服务器”的电脑,但这个服务器的作用仅仅是用来方便“交
换”大家的修改,没有它大家也一样干活,只是交换修改不方便而已。
当然,Git的优势不单是不必联网这么简单,后面我们还会看到Git极其强大的分支管理,把SVN等远远抛在
了后面。
CVS作为最早的开源而且免费的集中式版本控制系统,直到现在还有不少人在用。由于CVS自身设计的问
题,会造成提交文件不完整,版本库莫名其妙损坏的情况。同样是开源而且免费的SVN修正了CVS的一些
稳定性问题,是目前用得最多的集中式版本库控制系统。
除了免费的外,还有收费的集中式版本控制系统,比如IBM的ClearCase(以前是Rational公司的,被IBM收
购了),特点是安装比Windows还大,运行比蜗牛还慢,能用ClearCase的一般是世界500强,他们有个共
同的特点是财大气粗,或者人傻钱多。
微软自己也有一个集中式版本控制系统叫VSS,集成在Visual Studio中。由于其反人类的设计,连微软自己
都不好意思用了。
分布式版本控制系统除了Git以及促使Git诞生的BitKeeper外,还有类似Git的Mercurial和Bazaar等。这些分
布式版本控制系统各有特点,但最快、最简单也最流行的依然是Git!
git概念
5/28
工作区
版本库
暂存区
HEAD
版本号
版本日志
工作区(Working Directory):
存放git版本仓库的目录就是工作区
版本库(Repository):
工作区有一个隐藏目录.git,这个不算工作区,而是Git的版本库。
暂存区:
Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动
创建的第一个分支master,以及指向master的一个指针叫HEAD。
HEAD:
你的本地仓库由 git 维护的三棵“树”组成。
第一个是你的 工作目录,它持有实际文件;
第二个是 缓存区(Index),它像个缓存区域,临时保存你的改动;
第三个HEAD,指向你最近一次提交后的结果。
6/28
添加修改到暂存区:
创建两个文件add到stage:
#git add 文件名
或者
#git add *
从stage提交到当前master分支的HEAD:
#git commit -m “版本描述信息” //提交暂存区里的修改到版本库的分支
7/28
Git跟踪并管理的是修改,而非文件:
什么是修改?比如你新增了一行,这就是一个修改,删除了一行,也是一个修改,更改了某些字符,也是
一个修改,删了一些又加了一些,也是一个修改,甚至创建一个新文件,也算一个修改。
第一次修改 -> git add -> 第二次修改 -> git add -> git commit
每次修改,如果不add到暂存区,那就不会加入到commit中。
实验(本实验要学过基本操作后再做):
1.现有源文件:
[root@vm20 gittest]# cat a.txt
friday
monday
2.第一次修改:添加一行tuesday
[root@vm20 gittest]# cat a.txt
friday
monday
tuesday
3.执行add:
[root@vm20 gittest]# git add a.txt
4.第二次修改:添加一行wednesday
[root@vm20 gittest]# cat a.txt
friday
monday
tuesday
wednesday
5.不做add,直接提交:
[root@vm20 gittest]# git commit -m "看看第二次修改有没有被commit"
[master 0e14810] 看看第二次修改有没有被commit
1 file changed, 1 insertion(+)
[root@vm20 gittest]# git status
# 位于分支 master
# 尚未暂存以备提交的变更:
8/28
# (使用 "git add <file>..." 更新要提交的内容)
# (使用 "git checkout -- <file>..." 丢弃工作区的改动)
#
# 修改: a.txt
#
修改尚未加入提交(使用 "git add" 和/或 "git commit -a")
注意:如果第二修改也被add了不会出现上面的提示
6.查看当前版本和a.txt文件内容的区别(有输出内容,说明现在版本库和文件a.txt内容有区别,也就是第
二次修改并没有被提交):
[root@vm20 gittest]# git diff HEAD -- a.txt
diff --git a/a.txt b/a.txt
index 1091166..adfd1e9 100644
--- a/a.txt
+++ b/a.txt
@@ -1,3 +1,4 @@
friday
monday
tuesday
+wednesday
7.再次add后,发现工作区干净了,而且当前版本库HEAD和a.txt没有任何区别了:
[root@vm20 gittest]# git add a.txt
[root@vm20 gittest]# git commit -m "再看第二次修改有没有被commit"
[master fe18903] 再看第二次修改有没有被commit
1 file changed, 1 insertion(+)
[root@vm20 gittest]# git status
# 位于分支 master
无文件要提交,干净的工作区
[root@vm20 gittest]# git diff HEAD -- a.txt
[root@vm20 gittest]#
版本号:
也就是commit id,和SVN不一样,Git的commit id不是1,2,3……递增的数字,而是一个SHA1计算出
来的一个非常大的数字,用十六进制表示。为什么commit id需要用这么一大串数字表示呢?因为Git是分
布式的版本控制系统,如果多人在同一个版本库里工作,如果大家都用1,2,3……作为版本号,那肯定就
冲突了。
查看版本号:
版本号可以通过版本日志查看
版本日志:
commit完成的功能类似快照,可以使用git log查看每次的commit记录
[root@vm20 gittest]# git log
commit fbecfa3d04ae5038aa11bf55942e46c840077ace
Author: tom@up.com <tom>
Date: Fri Sep 29 02:20:51 2017 -0400
add haha
9/28
commit 7e99d947e4878029edb3bf7f32e5dcc4c785e765
Author: tom@up.com <tom>
Date: Fri Sep 29 00:01:50 2017 -0400
添加hello一行
commit addd750a13477d215cc75f4634aae0a686133e90
Author: tom@up.com <tom>
Date: Thu Sep 28 23:15:25 2017 -0400
test
显示分支:
[root@vm20 gittest]# git log --graph
单行方式显示:
[root@vm20 gittest]# git log --pretty=oneline
fbecfa3d04ae5038aa11bf55942e46c840077ace add haha
7e99d947e4878029edb3bf7f32e5dcc4c785e765 添加hello一行
addd750a13477d215cc75f4634aae0a686133e90 test
[root@vm20 gittest]# git log --graph
创建版本库
版本库:
又名仓库,英文名repository,可以简单理解成一个目录,这个目录里面的所有文件都可以被Git管理起
来,每个文件的修改、删除,Git都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以“还
原”.
1.创建一个空目录:在vm20上创建
[root@vm20 /]# mkdir gittest
[root@vm20 /]# cd gittest/
2.通过git init命令把这个目录变成Git可以管理的仓库:
方式1.创建本地库:
这样创建的库其他机器可以clone,但是没办法push
10/28
[root@vm20 gittest]# git init
初始化空的 Git 版本库于 /gittest/.git/
创建完成后查看库目录:
[root@vm20 gittest]# ls -a
. .. .git
方式2.创建裸库: 适用与作为远程中心仓库使用
创建裸库才可以从别处push代码过来,使用--bare参数
[root@vm20 gittest2]# git init --bare
初始化空的 Git 版本库于 /gittest2/
默认会把当前所在目录做成库目录,可以在命令后面跟目录指定子目录为版本库
git init --bare 库名字
裸库创建完成后查看库目录:
[root@vm20 gittest2]# ls
branches config description HEAD hooks info objects refs
注:不一定必须在空目录下创建Git仓库,选择一个已经有东西的目录也是可以的
添加文件到版本库
所有版本控制系统,其实只能跟踪文本文件的改动,比如TXT文件,网页,所有的程序代码等等,Git也
不例外。版本控制系统可以告诉你每次的改动,比如在第5行加了一个单词“Linux”,在第8行删了一个单
词“Windows”。而图片、视频这些二进制文件,虽然也能由版本控制系统管理,但没法跟踪文件的变化,
只能把二进制文件每次改动串起来,也就是只知道图片从100KB改成了120KB,但到底改了啥,版本控制
系统不知道,也没法知道。
Microsoft的Word格式是二进制格式,因此,版本控制系统是没法跟踪Word文件的改动的,如果要真正
使用版本控制系统,就要以纯文本方式编写文件。
强烈建议使用标准的UTF-8编码,所有语言使用同一种编码,既没有冲突,又被所有平台所支持。
3.在gittest目录下创建一个测试文件readme.txt
[root@vm20 gittest]# cat readme.txt
Git is a version control system.
Git is free software.
4.把文件添加到暂存区:使用 "git add" 建立跟踪
[root@vm20 gittest]# git add readme.txt
使用#git status可以查看状态
使用#git rm --cached readme.txt可以删除文件跟踪,但是不可以回退文件内容的修改,建议使用下一
节讲到的撤销修改
5.提交文件到仓库分支:
[root@vm20 gittest]# git commit -m "test"
[master(根提交) addd750] test
1 file changed, 2 insertions(+)
create mode 100644 readme.txt
-m 本次提交的说明
11/28
6.查看git状态:
[root@vm20 gittest]# git status
位于分支 master
无文件要提交,干净的工作区
修改文件后再此查看状态:
[root@vm20 gittest]# echo hello >> readme.txt
[root@vm20 gittest]# git status
位于分支 master
尚未暂存以备提交的变更:
(使用 "git add <file>..." 更新要提交的内容)
(使用 "git checkout -- <file>..." 丢弃工作区的改动)
#
修改: readme.txt
#
修改尚未加入提交(使用 "git add" 和/或 "git commit -a")
查看修改了什么内容:
[root@vm20 gittest]# git diff
diff --git a/readme.txt b/readme.txt
index 795d143..57083df 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,2 +1,3 @@
Git is a version control system.
Git is free software.
+hello
再次提交可以先add再commit,也可以使用-a和commit一起:
[root@vm20 gittest]# git commit -a -m "添加hello一行"
[master 7e99d94] 添加hello一行
1 file changed, 1 insertion(+)
[root@vm20 gittest]# git status
位于分支 master
无文件要提交,干净的工作区
撤销修改
撤销修改
场景1:当你改乱了工作区某个文件的内容,想直接丢弃工作区的修改时,用命令git checkout -- file。
场景2:当你不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步,第一步用命
令git reset HEAD file,
就回到了场景1,第二步按场景1操作。
场景3:已经提交了不合适的修改到版本库时,想要撤销本次提交,使用版本回退,不过前提是没有推送到
远程库。(见下节)
场景1: 源文件添加了一行thursday,还没有add到stage(前提:之前提交过此文件)
[root@vm20 gittest]# cat a.txt
12/28
wednesday
thursday
撤销刚才的修改:
[root@vm20 gittest]# git checkout -- a.txt
[root@vm20 gittest]# cat a.txt
wednesday
场景2:源文件添加了一行thursday,并且add到了stage(前提:之前提交过此文件)
[root@vm20 gittest]# cat a.txt
wednesday
thursday
[root@vm20 gittest]# git add a.txt
[root@vm20 gittest]# git status
位于分支 master
要提交的变更:
(使用 "git reset HEAD <file>..." 撤出暂存区)
#
修改: a.txt
#
[root@vm20 gittest]# git reset HEAD a.txt
重置后撤出暂存区的变更:
M a.txt
[root@vm20 gittest]# cat a.txt
wednesday
thursday
[root@vm20 gittest]# git checkout -- a.txt
[root@vm20 gittest]# cat a.txt
wednesday
版本回退
场景3:已经提交到版本库
13/28
查看现在的版本:
[root@ansible gittest]# git log
commit 898a61cb50da77daeda51453bef38c98fecd46a0
Author: wing <wing@wing.com>
Date: Sun Feb 25 18:04:27 2018 +0800
test1
commit d75411fb17e661cefc1900a09c8a784e8aa0d79a
Author: wing <wing@wing.com>
Date: Sun Feb 25 17:56:45 2018 +0800
test1
版本回退(切换):
在Git中,上一个版本就HEAD^,上上一个版本就是HEAD^^,当然往上100个版本写100个^比较容易数
不过来,所以写成HEAD~100
回到上一个版本:
[root@vm20 gittest]# git reset --hard HEAD^
HEAD 现在位于 83f6e8d Signed-off-by: tom@up.com <tom>
回到指定的版本(根据版本号):
[root@vm20 gittest]#git reset --hard 6fe5b9a2
消失的ID号:
回到早期的版本后再查看git log会发现最近的版本消失,可以使用reflog查看消失的版本ID,用于回退到消
失的版本
[root@vm20 gittest]# git reflog
32c31f5 HEAD@{0}: reset: moving to 32c31f54c1
6fe5b9a HEAD@{1}: reset: moving to 6fe5b9a2
928ab9e HEAD@{2}: reset: moving to HEAD^^
83f6e8d HEAD@{3}: reset: moving to HEAD^
6fe5b9a HEAD@{5}: commit: 这个能写中文
83f6e8d HEAD@{6}: commit: Signed-off-by: tom@up.com <tom>
32c31f5 HEAD@{7}: commit: add a line monday
928ab9e HEAD@{8}: commit (amend): this is a new file test
bee2ba0 HEAD@{9}: commit: this is a new file test
c8e6b87 HEAD@{10}: commit: 添了两个
fbecfa3 HEAD@{11}: commit: add haha
7e99d94 HEAD@{12}: commit: 添加hello一行
addd750 HEAD@{13}: commit (initial): test
Git的版本回退速度非常快,因为Git在内部有个指向当前版本的HEAD指针,当你回退版本的时候,Git仅仅
是把HEAD从指向
append GPL:
14/28
git-head
改为指向add distributed:
git-head-move
然后顺便把工作区的文件更新了。所以你让HEAD指向哪个版本号,你就把当前版本定位在哪。
删除文件
删除文件:
从工作区删除a.txt,并且从版本库一起删除
[root@vm20 gittest]# rm -rf a.txt
[root@vm20 gittest]# git status
# 位于分支 master
# 尚未暂存以备提交的变更:
# (使用 "git add/rm <file>..." 更新要提交的内容)
# (使用 "git checkout -- <file>..." 丢弃工作区的改动)
#
# 删除: a.txt
#
修改尚未加入提交(使用 "git add" 和/或 "git commit -a")
[root@vm20 gittest]# git rm a.txt
rm 'a.txt'
[root@vm20 gittest]# git commit -m "删除文件a.txt"
[master 4bb90a4] 删除文件a.txt
1 file changed, 4 deletions(-)
delete mode 100644 a.txt
[root@vm20 gittest]# git status
# 位于分支 master
无文件要提交,干净的工作区
删除了文件readme.txt之后又后悔了,恢复回来
[root@vm20 gittest]# ls
readme.txt
[root@vm20 gittest]# rm -rf readme.txt
[root@vm20 gittest]# git checkout -- readme.txt
[root@vm20 gittest]# ls
readme.txt
15/28
Git远程仓库
Git远程仓库
Git远程仓库实际就是保存在服务器上的git仓库文件
http协议:只支持下载,不支持上传
ssh协议:支持上传和下载,采用ssh认证
git协议:支持上传下载,效率高
Git基础 Git安装完成之后,需要进行一些基本信息设置
1、设置用户名git config --global user.name "flyer“设置用户邮箱
2、git config --global user.email flyer@qq.com
3、查看设置git config --list
初始化一个新的git仓库
创建一个文件夹(或使用已有文件夹)mkdir /flyer在文件夹内初始化git,创建git仓库cd /flyergit initls -
a 发现多了一个.git目录,即初始化成功
Git checkout取所需的版本
git log 查看版本日志,复制其中的commit的MD5值的左边6个字符
git checkout 粘贴第1版本的commit的MD5值c
at hosts 发现内容为第1个版本的
git log 查看当前状态以前的的日志
git reflog 查看参考日志(即所有日志)
cat .git/logs/HEAD 查看所有日志
git checkout 用第2版的commit的MD5值cat hosts
git的本地使用
mkdir -pv /jim ; cd /jim
git init
cp -av /etc/host* /jim/
git status
git add *
git status
git tag v001
git commit -m "desc:host files v1."
git log 或 git reflog
rm -rfv hosts*
git status
git commit -a -m "desc:host files v2."
cp -av /etc/{passwd,group} /jim/
git add *
git commit -m "desc:add passwd group v3."
git log 请复制v1版的commit值的前6个字符
ls
git checkout 请粘贴v1版的commit值的前6个字符
Git删除文件
1、本地删除文件rm README
2、从git中删除文件 文件依然记录在git仓库历史中git rm README
16/28
3、提交操作git commit -m "delete README"
测试:cd /mydocgit statusrm hostsgit rm hostsgit commit -m 'del hosts'git status git
log 查看当前日志; git reflog 查看所有日志
码云平台使用
在linux或windows系统中安装git软件注册“码云”平台账号。官网:http://git.oschina.net/登录github账
号:在“码云”平台创建网络仓库(也称为项目)
cd /opt
git clone https://gitee.com/rshare/jin0312.git
ls
cd jin0312
ls -a
cp -v /etc/host* ./
git status
git add *
git commit -m ‘host* file v1.‘
git status
git log
git push输入码云平台的用户账号 rshare输入密码 ****自动上传数据到码云平台的仓库中
17/28
使用“码云“github”平台
安装git软件注册“码云”平台账号。
官网:http://git.oschina.net/登录github账号:在“码云”平台创建网络仓库(也称为项目)Linux创建ssh
密钥,并复制公钥到“码云”平台个人账号中。(仅用于push更新网络仓库数据时验证身份)测试ssh身份验证
是否成功同步github仓库数据到本地:
git clone git@git.oschina.net:rshare/conf.git
用git命令添加add、提交commit文件
用git push origin master上传更新网络github数据在“码云”平台查看是否有新数据用git删除文件
实例:rshare个人github同步数据实战。
git环境准备:yum install -y git
git config --help
git config --global user.name "sky" //用户信息
git config --global user.mail "sky@qq.com"
//用户邮箱第1步,登录github:
1、注册Github账号,网站:https://github.com 我的账号:rshare 密码:pass000
2、Linux创建SSH密钥:
方法一:非交互式生成密钥:ssh-keygen -t rsa -N '' -f ~/.ssh/id_rsa -C "12700696@qq.com" cat
~/.ssh/id_rsa.pub //提交密钥,复制里面的密钥(第3步要粘贴)说明:ssh-keygen是ssh密钥生成器,-t指
定算法为rsa,-N指定密码为空,-f指定私钥位置,-C指定注释信息(不指定则为主机名)。
3、将公钥加入到Github账户信息Account Settings->SSH Key方法:登录到github网页中登陆自己的账
号,然后再account setting中,找到SSH KEY讲复制的密钥加入(需要再次输入github的密码)
4、测试验证是否成功。ssh -T git@github.com 提示successfully说明成功Hi someone! You've
successfully authenticated, but GitHub does not provide shell access.
##同步github到本地
1、复制项目到本地:mkdir /testcd /testgit clone git@github.com:rshare/mydocker.git ##以SSH方
式克隆到本地,可以读写 git clone https://github.com/rshare/docker-installer.git ##以https方式克隆
到本地,可以读写 ls 查看文件列表
2、创建新文件,并上传到github中。
cd /test/mydocker
ls -a
git remote
cp -v /etc/{hosts,group,passwd} ./
git add hosts group passwd
git status
git commit -m '3files'
git push -u origin master
验证:在github个人网站的mydocker仓库中查看是否多了三个文件(hosts,group,passwd)。git其他命
令:git branch #查看分支(即目录结构)
3、删除远程仓库中的文件。cd /test/mydocker
ls -a
git rm --cached hosts group passwd #删除缓存数据,并不删除本地文件
git status
git commit -m "hehe"
git push origin 验证:在github个人网站的mydocker仓库中查看是否少了三个文件
(hosts,group,passwd)。
18/28
在同步过来的sample仓库执行
cd
git clone git@192.168.10.1:/srv/sample.git
ls
cd sample
mkdir conf
cp -v /etc/*.conf conf/
git status
git add conf
git commit -m 'conf bak'
git remote -v
git branch
git push origin master
验证数据:
mkdir /a
cd /a
git clone git@192.168.10.1:/srv/sample.git
ls 发现有sample目录说明数据同步成功
cd sample
ls -R ./ 发现有conf目录,说明git服务器上的数据已经更新了。
github数据验证
验证数据:
mkdir /a
cd /a
19/28
git clone git@192.168.10.1:/srv/sample.git
ls 发现有sample目录说明数据同步成功
cd sample
ls -R ./ 发现有conf目录,说明git服务器上的数据已经更新了。
下面开始实战。
首先,我们创建dev分支,然后切换到dev分支:
$ git checkout -b dev
Switched to a new branch 'dev'
git checkout命令加上-b参数表示创建并切换,相当于以下两条命令:
$ git branch dev
$ git checkout dev
Switched to branch 'dev'
然后,用git branch命令查看当前分支:
$ git branch
* dev
master
然后提交:
$ git add readme.txt
$ git commit -m "branch test"[dev fec145a] branch test
1 file changed, 1 insertion(+)
现在,dev分支的工作完成,我们就可以切换回master分支:
$ git checkout master
Switched to branch 'master'
切换回master分支后,再查看一个readme.txt文件,刚才添加的内容不见了!因为那个提交是在dev分支
上,而master分支此刻的提交点并没有变:
现在,我们把dev分支的工作成果合并到master分支上:
$ git merge dev
Updating d17efd8..fec145a
fast-forward
readme.txt | 1 +
1 file changed, 1 insertion(+)
git merge命令用于合并指定分支到当前分支。合并后,再查看readme.txt的内容,就可以看到,和dev分
支的最新提交是完全一样的。
注意到上面的fast-forward信息,Git告诉我们,这次合并是“快进模式”,也就是直接把master指向dev的当
前提交,所以合并速度非常快。
当然,也不是每次合并都能fast-forward,我们后面会讲其他方式的合并。
20/28
合并完成后,就可以放心地删除dev分支了:
$ git branch -d dev
Deleted branch dev (was fec145a).
删除后,查看branch,就只剩下master分支了:
$ git branch
* master
添加远程仓库
现在的情景是,你已经在本地创建了一个Git仓库后,又想在GitHub创建一个Git仓库,并且让这两个仓库进
行远程同步,这样,GitHub上的仓库既可以作为备份,又可以让其他人通过该仓库来协作,真是一举多
得。
首先,登陆GitHub,然后,在右上角找到“Create a new repo”按钮,创建一个新的仓库:
在Repository name填入learngit,其他保持默认设置,点击“Create repository”按钮,就成功地创建了一个
新的Git仓库:
21/28
目前,在GitHub上的这个learngit仓库还是空的,GitHub告诉我们,可以从这个仓库克隆出新的仓库,也可
以把一个已有的本地仓库与之关联,然后,把本地仓库的内容推送到GitHub仓库。
现在,在本地的gittest仓库下运行命令:换掉用户名
[root@ansible gittest]# git remote add origin https://github.com/yanqiang20172017/test1.git
origin 远程库的名字,是Git默认的叫法,也可以改成别的
下一步,就可以把本地库的所有内容推送到远程库上:
[root@ansible gittest]# git push -u origin master
Username for 'https://github.com': yanqiang20172017
Password for 'https://yanqiang20172017@github.com':
Counting objects: 3, done.
Writing objects: 100% (3/3), 202 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To https://github.com/yanqiang20172017/test1.git
* [new branch] master -> master
分支 master 设置为跟踪来自 origin 的远程分支 master。
把本地库的内容推送到远程,用git push命令,实际上是把当前分支master推送到远程。
-u 我们第一次推送master分支时,Git不但会把本地的master分支内容推送的远程新的master分支,还会
把本地的master分支和远程的master分支关联起来,在以后的推送或者拉取时就可以简化命令。
查看远程add的库:
[root@ansible gittest]# git remote -v
删除远程add:
[root@ansible gittest]# git remote remove haha
推送成功后,可以立刻在GitHub页面中看到远程库的内容已经和本地一模一样:
从现在起,只要本地作了提交,就可以通过命令:
# git push origin master
22/28
把本地master分支的最新修改推送至GitHub
部署远程仓库
远程仓库实际上和本地仓库没啥不同,纯粹为了7x24小时开机并交换大家的修改。
GitHub就是一个免费托管开源代码的远程仓库。但是对于某些视源代码如生命的商业公司来说,既不想公
开源代码,又舍不得给GitHub交保护费,那就只能自己搭建一台Git服务器作为私有仓库使用。
搭建Git服务器需要准备一台运行Linux的机器
第一步,安装git:
#yum install git
第二步,创建一个git用户,用来运行git服务:
#adduser git
第三步,创建证书登录:
收集所有需要登录的用户的公钥,就是他们自己的id_rsa.pub文件,把所有公钥导入到/home/git/.ssh/
authorized_keys文件里,一行一个。
第四步,初始化Git仓库:
选定一个目录作为Git仓库,假定是/srv/sample.git,在/srv目录下输入命令:
# git init --bare sample.git
Git就会创建一个裸仓库,裸仓库没有工作区,因为服务器上的Git仓库纯粹是为了共享,所以不让用户直接
登录到服务器上去改工作区,并且服务器上的Git仓库通常都以.git结尾。然后,把owner改为git:
# chown -R git:git sample.git
第五步,禁用shell登录:
出于安全考虑,第二步创建的git用户不允许登录shell,这可以通过编辑/etc/passwd文件完成。找到类似
下面的一行:
git:x:1001:1001:,,,:/home/git:/bin/bash
改为:
git:x:1001:1001:,,,:/home/git:/usr/bin/git-shell
这样,git用户可以正常通过ssh使用git,但无法登录shell,因为我们为git用户指定的git-shell每次一登录就
自动退出。
第六步,克隆远程仓库:
现在,可以通过git clone命令克隆远程仓库了,在各自的电脑上运行:
# git clone git@server:/srv/sample.git
cloning into 'sample'...
warning: You appear to have cloned an empty repository.
剩下的推送就简单了。
[root@tomcat gittest4]# git push -u origin master
tesla@192.168.245.3's password:
Counting objects: 3, done.
Writing objects: 100% (3/3), 213 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To tesla@192.168.245.3:/gittest3/teslaProject.git
* [new branch] master -> master
23/28
分支 master 设置为跟踪来自 origin 的远程分支 master。
Git分支管理
git分支管理
在版本回退里,你已经知道,每次提交,Git都把它们串成一条时间线,这条时间线就是一个分支。截止到
目前,只有一条时间线,在Git里,这个分支叫主分支(即master)。HEAD严格来说不是指向提交,而是指
向master,master才是指向提交的,所以,HEAD指向的就是当前分支。
git branch命令会列出所有分支,当前分支前面会标一个*号。
查看分支:git branch
说明:默认主分支为master
创建分支:git branch 分支名
取出分支版本:git chkeckout -b 分支名
说明:git checkout -b表示创建并切换到分支,相当于以下两条命令
git branch dev
git checkout dev
分支管理实例
cd /a/test
git branch 查看分支
git branch dev 创建名称为dev的分支
git checkout dev 切换到dev分支
cp /etc/yum.conf ./
git add yum.conf
git commit -m 'yum.conf bak‘
git branch -a
git push origin dev 上传更新分支
验证:在码云平台查看test仓库中的master节点和dev分支的区别。
分支管理实例(合并分支)
git branch
git checkout master
git merge dev 合并dev分支到master主分支中
git push origin master
git push origin :dev 删除远程的dev分支
验证:在码云平台查看test仓库中的master节点。
删除本地git仓库中的dev分支:
git branch -d dev
git合并分支
合并完成后,删除dev分支
git branch -d dev
git branch
分支
分支是用来将特性开发绝缘开来的。在你创建仓库的时候,master 是“默认的”。在其他分支上进行开
发,完成后再将它们合并到主分支上。
24/28
创建一个叫做“feature_x”的分支,并切换过去:
#git checkout -b feature_x
查看分支:
[root@ansible gittest]# git branch -a
* feature_x //带*号的代表你当前工作目录所处的分支
master
remotes/origin/master
切换回主分支:
# git checkout master
再把新建的分支删掉:
# git branch -d feature_x
除非你将分支推送到远端仓库,不然该分支就是 不为他人所见的:
# git push origin <branch>
更新与合并
要更新你的本地仓库至最新改动,执行:
#git pull
以在你的工作目录中 获取(fetch) 并 合并(merge) 远端的改动。
要合并其他分支到你的当前分支(例如 master),执行:
git merge <branch>
两种情况下,git 都会尝试去自动合并改动。不幸的是,自动合并并非次次都能成功,并可能导致 冲突
(conflicts)。 这时候就需要你修改这些文件来人肉合并这些 冲突(conflicts) 了。改完之后,
你需要执行如下命令以将它们标记为合并成功:
git add <filename>
在合并改动之前,也可以使用如下命令查看:
git diff <source_branch> <target_branch>
标签
在软件发布时创建标签,是被推荐的。这是个旧有概念,在 SVN 中也有。
25/28
创建一个叫做 1.0.0 的标签:
# git tag 1.0.0 1b2e1d63ff
1b2e1d63ff 是你想要标记的提交 ID 的前 10 位字符。使用如下命令获取提交 ID:
# git log
显示的标签按字母顺序排列,所以标签的先后并不表示重要程度的轻重。
可以用特定的搜索模式列出符合条件的标签。在 Git 自身项目仓库中,有着超过 240 个标签,如果你只对
1.4.2 系列的版本感兴趣,可以运行下面的命令:
# git tag -l 'v1.4.2.*'
v1.4.2.1
v1.4.2.2
v1.4.2.3
v1.4.2.4
含附注的标签
创建一个含附注类型的标签非常简单,用 -a (译注:取 annotated 的首字母)指定标签名字即可:
-m 选项则指定了对应的标签说明,Git 会将此说明一同保存在标签对象中。如果没有给出该选项,Git 会
启动文本编辑软件供你输入标签说明。
# git tag -a v1.4 -m 'my version 1.4'
# git tag
v0.1
v1.3
v1.4
[root@ansible gittest]# git show 1.0.0
commit 5b83380e818f44c850dc4fe96a29148744903ff2
Author: wing <wing@wing.com>
Date: Sun Feb 25 23:09:09 2018 +0800
my version 1.4
diff --git a/a.txt b/a.txt
new file mode 100644
index 0000000..ce01362
--- /dev/null
+++ b/a.txt
@@ -0,0 +1 @@
+hello
分享标签
默认情况下,git push 并不会把标签传送到远端服务器上,只有通过显式命令才能分享标签到远端仓库。
其命令格式如同推送分支,运行 git push origin [tagname] 即可:
# git push origin v1.5
Counting objects: 50, done.
Compressing objects: 100% (38/38), done.
Writing objects: 100% (44/44), 4.56 KiB, done.
Total 44 (delta 18), reused 8 (delta 1)
To git@github.com:schacon/simplegit.git
* [new tag] v1.5 -> v1.5
如果要一次推送所有本地新增的标签上去,可以使用 --tags 选项:
# git push origin --tags
Counting objects: 50, done.
Compressing objects: 100% (38/38), done.
Writing objects: 100% (44/44), 4.56 KiB, done.
26/28
Total 44 (delta 18), reused 8 (delta 1)
To git@github.com:schacon/simplegit.git
* [new tag] v0.1 -> v0.1
* [new tag] v1.2 -> v1.2
* [new tag] v1.4 -> v1.4
* [new tag] v1.4-lw -> v1.4-lw
* [new tag] v1.5 -> v1.5
现在,其他人克隆共享仓库或拉取数据同步后,也会看到这些标签。
Git练习
测试
cd /mydoc
git init
git status
cp /etc/hosts ./cp
/etc/group ./git status
git add hosts group
git status
git commit -m ‘备注’
git log 查git日志
Git 更新文件,提交新版本
测试:cd /mydoc
git status
echo 127.0.0.5 ddd >> hosts
echo 127.0.0.6 kk >> hosts
git status
git add hosts
git commit -m 'hosts change1'
git status
git log
创建/mygit目录,并对此目录用git进行版本控制。复制/etc/yum.conf和/etc/sysctl.conf文件到/mygit目
录。用git status查状态,然后提交当前的版本,-m 的备注信息为’my conf file v1.’将lsblk、free命令的
结果覆盖写入到/mygit/sysctl.conf文件中。再次提交这个版本, -m 的备注信息为’my conf file v2.’用
git status查状态。查看当前的/mygit/sysctl.conf文件内容,然后checkout取出v1这个版本,再看/
mygit/sysctl.conf文件内容。
mkdir /mygit
cd /mygit
git init
cp -v /etc/yum.conf /etc/sysctl.conf ./
git status
git add *
git commit -m 'my conf file v1. '
git statuslsblk > sysctl.conf
free >> sysctl.conf
git status
27/28
git commit -a -m 'my conf file v2. '
git status
git log
cat sysctl.conf
git log
git checkout
Git总结
git小结
git版本控制系统
git安装、全局环境配置
rpm -q git
yum install -y git
git config --global user.email "tom@qq.com"
git config --global user.name "tom“
git config --list
git config push.default simple
Git checkout取所需的版本
git log 查看版本日志,复制其中的commit的MD5值的左边6个字符
git checkout 粘贴第1版本的commit的MD5值c
at hosts 发现内容为第1个版本的
git log 查看当前状态以前的的日志
git reflog 查看参考日志(即所有日志)
cat .git/logs/HEAD 查看所有日志
git checkout 用第2版的commit的MD5值cat hosts
Git删除文件
1、本地删除文件rm README
2、从git中删除文件 文件依然记录在git仓库历史中git rm README
3、提交操作git commit -m "delete README"
测试:cd /mydoc
git status
rm hosts
git rm hosts
git commit -m 'del hosts'
git status
git log 查看当前日志;
git reflog 查看所有日志
git分支管理小结
Git鼓励大量使用分支:
查看分支:git branch
创建分支:git branch <name>
切换分支:git checkout <name>
创建+切换分支:git checkout -b <name>
合并某分支到当前分支:git merge <name>
28/28
删除分支:git branch -d <name>
删除远程分支:git push origin :分支名