版本控制系统教程

版本控制系统教程_第1张图片

1.Git的基本介绍

1.1 Git的概念

Git是一个开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目.Git是Linus Torvalds为了帮助管理Linux内核开发而开发的一个开放源码的版本控制软件.Git与常用的版本控制工具CVS,Subversion等不同,它采用了分布式版本库的方式,不必用服务器端软件支持.

1.2 Git与SVN的区别

Git 不仅仅是个版本控制系统,它也是个内容管理系统(CMS),工作管理系统等。如果你是一个具有使用 SVN 背景的人,你需要做一定的思想转换,来适应 Git 提供的一些概念和特征。

Git 与 SVN 区别点:

  • 1.Git 是分布式的,SVN 不是:这是 Git 和其它非分布式的版本控制系统,例如 SVN,CVS 等,最核心的区别
  • 2.Git 把内容按元数据方式存储,而 SVN 是按文件:所有的资源控制系统都是把文件的元信息隐藏在一个类似 .svn、.cvs 等的文件夹里
  • 3.Git 分支和 SVN 的分支不同:分支在 SVN 中一点都不特别,其实它就是版本库中的另外一个目录
  • 4.Git 没有一个全局的版本号,而 SVN 有:目前为止这是跟 SVN 相比 Git 缺少的最大的一个特征
  • 5.Git 的内容完整性要优于 SVN:Git 的内容存储使用的是 SHA-1 哈希算法。这能确保代码内容的完整性,确保在遇到磁盘故障和网络问题时降低对版本库的破坏
    版本控制系统教程_第2张图片

1.1.3 Git学习友情链接

git 简明指南 (runoob.com)

Git完整命令手册地址:Git - Reference (git-scm.com)

PDF版命令手册:Git - Reference (git-scm.com)

1.2 Git的安装配置

`Git 各平台安装包下载地址为:http://git-scm.com/downloads

1.2.1 Linux平台上安装

`Git的工作需要调用curl,zlib,openssl,expat,libiconv等库的代码,所以需要先安装这些依赖工具
1.Debian/Ubuntu
`安装相关依赖
# apt-get install libcurl4-gnutls-dev libexpat1-dev gettext libz-dev libssl-dev
`安装git
# apt-get install git
`查看git的版本
#git --version
git version 1.8.1.2
2.Centos/RedHat
`安装相关依赖
# yum install curl-devel expat-devel gettext-devel openssl-devel zlib-devel
` 安装git
# yum -y install git-core
` 查看git的版本
# git --version
git version 1.8.1.2
3.源码安装
`安装相关依赖
########## Centos/RedHat ##########
# yum -y install curl-devel expat-devel gettext-devel openssl-devel zlib-devel
# yum -y install gcc-c++ perl-ExtUtils-MakeMaker
# yum -y install autoconf-2.69-11.el7.noarch 
# yum -y install automake-1.13.4-3.el7.noarch

########## Debian/Ubuntu ##########
# apt-get -y install libcurl4-gnutls-dev libexpat1-dev gettext libz-dev libssl-dev
# apt-get -y install gcc-c++ perl-ExtUtils-MakeMaker
# apt-get -y install autoconf-2.69-11.el7.noarch 
# apt-get -y install automake-1.13.4-3.el7.noarch
`下载相关二进制包
# cd /usr/src
# wget https://www.kernel.org/pub/software/scm/git/git-2.7.3.tar.gz
# tar xf git-2.7.3.tar.gz
# cd git-2.7.3
# make configure
# ./configure --prefix=/usr/git ##配置目录
# make profix=/usr/git
# make install
# echo 'export PATH=$PATH:/usr/git/bin' >> /etc/profile
# source /etc/profile
# git --version
git version 2.7.3

1.2.2 Windows平台上安装

`安装包下载地址:https://git-scm.com/downloads
`官网慢,可以用国内的镜像:https://npm.taobao.org/mirrors/git-for-windows/。

1.3 Git的配置

Git提供了一个叫做git config的工具,专门用来配置或读取相应的工作环境变量

这些环境变量,决定了Git在各个环节的具体工作方式和行为。这些变量存放在以下三个不同的地方:

  1. /etc/gitconfig文件:系统中对所有用户都普遍适用的配置.若使用git config时用 --system选项,读写的就是这个文件
  2. ~/.gitconfig文件:用户目录下的配置文件只适用于该用户。若使用git config时用--global选项,读写的就是这个文件
  3. 当前项目的Git目录中的配置文件(也就是工作目录中的.git/config文件):这里的配置仅仅针对当前项目有效。每一个级别的配置都会覆盖上层的相同配置,所以.git/config里的配置会覆盖/etc/gitconfig中的同名变量

在 Windows 系统上,Git 会找寻用户主目录下的 .gitconfig 文件。主目录即 $HOME 变量指定的目录,一般都是 C:\Documents and Settings$USER。

此外,Git 还会尝试找寻 /etc/gitconfig 文件,只不过看当初 Git 装在什么目录,就以此作为根目录来定位

1.4 用户信息

`配置个人的用户名称和电子邮件地址:
git config --global user.name "haohe"
git config --global user.email [email protected]

如果用了 --global选项,那么更改的配置文件就是位于你用户主目录下的哪个,以后你所有的项目默认使用这里配置的用户信息

如果要在某个特定的项目中使用其它名字或者电邮,只要去掉--global选项重新配置即可,新的设定保存在当前项目的.git/config文件里

1.5 文本编译器

设置Git默认使用的文本编译器,一般可能会是Vi或者Vim.可以重新设置为其它编译器

`语法格式:
# git config --global core.editor 文本编译器

1.6 差异分析工具

在解决合并冲突时使用那种差异分析工具

`语法格式:
# git config --global merge.tool vimdiff

# Git 可以理解 kdiff3,tkdiff,meld,xxdiff,emerge,vimdiff,gvimdiff,ecmerge,和 opendiff 等合并工具的输出信息。

1.7 查看配置信息

`检查已有的配置信息
# git config --list
user.name=haohe
user.email=[email protected]

有时候可能会看到重复的变量名,那就说明它们来自不同的配置文件(比如:/etc/gitconfig和~/.gitconfig),不过最终Git实际采用的是最后一个
这些配置我们也可以在~/.gitconfig或/etc/gitconfig看到
[root@localhost ~]# cat ~/.gitconfig 
[user]
	name = haohe
	email = [email protected]

也可以直接查阅某个环境变量的设定,只要把特定的名字跟在后面即可
[root@localhost ~]# git config user.name
haohe

1.3 Git的工作流程

版本控制系统教程_第3张图片

  1. 克隆Git资源作为工作目录
  2. 在克隆的资源上添加或修改文件
  3. 如果其它人修改了文件,可以更新资源
  4. 在提交前查看修改
  5. 提交修改
  6. 在修改完成后,如果发现错误,可以撤回提交并再次修改并提交

1.2.1 Git工作区,暂存区和版本库

基本概念:

  • 工作区:就是你在PC上能看到的目录
  • 暂存区:英文叫stage或index.一般存放在.git目录下的index文件(.git/index)中,所以我们把暂存区有时也叫做索引(index)
  • 版本库:工作区有一个隐藏目录.git,这个不是工作区,而是Git的版本库

工作区,版本库中的暂存区和版本库之间的关系:

版本控制系统教程_第4张图片

`图中左侧为工作区,右侧为版本库。在版本库中标记为 "index" 的区域是暂存区(stage/index),标记为 "master" 的是 master 分支所代表的目录树。

`图中我们可以看出此时 "HEAD" 实际是指向 master 分支的一个"游标"。所以图示的命令中出现 HEAD 的地方可以用 master 来替换。

`图中的 objects 标识的区域为 Git 的对象库,实际位于 ".git/objects" 目录下,里面包含了创建的各种对象及内容。

`当对工作区修改(或新增)的文件执行 git add 命令时,暂存区的目录树被更新,同时工作区修改(或新增)的文件内容被写入到对象库中的一个新的对象中,而该对象的ID被记录在暂存区的文件索引中。

`当执行提交操作(git commit)时,暂存区的目录树写到版本库(对象库)中,master 分支会做相应的更新。即 master 指向的目录树就是提交时暂存区的目录树。

`当执行 git reset HEAD 命令时,暂存区的目录树会被重写,被 master 分支指向的目录树所替换,但是工作区不受影响。

`当执行 git rm --cached <file> 命令时,会直接从暂存区删除文件,工作区则不做出改变。

`当执行 git checkout . 或者 git checkout -- <file> 命令时,会用暂存区全部或指定的文件替换工作区的文件。这个操作很危险,会清除工作区中未添加到暂存区中的改动。

`当执行 git checkout HEAD . 或者 git checkout HEAD <file> 命令时,会用 HEAD 指向的 master 分支中的全部或者部分文件替换暂存区和以及工作区中的文件。这个命令也是极具危险性的,因为不但会清除工作区中未提交的改动,也会清除暂存区中未提交的改动。

1.2.2 Git创建仓库

1.git init
`语法格式:
git init #使用当前目录作为Git仓库
# 该命令执行完后会在当前目录生成一个.git目录

版本控制系统教程_第5张图片

`语法格式:
git init 目录名称
[root@localhost ~]# git init warehouse
初始化空的 Git 仓库于 /root/warehouse/.git/
[root@localhost ~]# 

`初始化后,会在 warehouse 目录下会出现一个名为 .git 的目录,所有 Git 需要的数据和资源都存放在这个目录中
`如果当前目录下有几个文件想要纳入版本控制,需要先用 git add 命令告诉 Git 开始对这些文件进行跟踪,然后提交:
[root@localhost ~]# git add *.txt
[root@localhost ~]# git add *.md
[root@localhost ~]# git commit -m '1001'
[master(根提交) 83709dd] 1001
 2 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 1.txt
 create mode 100644 2.md

# 以上命令讲目录下以.txt,.md结尾的文件提交到仓库中

注:在Linux系统中,commit信息使用单引号'',在Windows系统,Commit信息使用双引号" ".

2.git clone

可以使用git clone从现有Git仓库中拷贝项目

`语法格式:
git clone <repo>

git clone <repo> <directory>
# 参数说明
repo:Git仓库
directory:本地目录

​ 比如,要克隆 Ruby 语言的 Git 代码仓库 Grit,可以用下面的命令:

# git clone git://github.com/schacon/grit.git

​ 执行该命令后,会在当前目录下创建一个名为grit的目录,其中包含一个 .git 的目录,用于保存下载下来的所有版本记录。

如果要自己定义要新建的项目目录名称,可以在上面的命令末尾指定新的名字:

# git clone git://github.com/schacon/grit.git mygrit
3.配置

Git的设置使用git config命令

  1. 显示当前的git配置信息
# git config --list
# 凭证存储模式
credential.helper=osxkeychain 
# 用于未来能够兼容git版本,决定怎么处理git命令和文件
core.repositoryformatversion=0
# 是否提供文件权限的diff
core.filemode=true
# 决定当前仓库是中心仓库还是开发库
core.bare=false
#记录所有的ref更新:决定变更ref时,会不会被记录在`$GIT_DIR/logs/`目录下
core.logallrefupdates=true
core.ignorecase=true
core.precomposeunicode=true

详细解释:

repositoryformatversion仓库版本

`现在发布的版本号都是0,这个属性是为了未来的兼容性.当开发者认为有新的特性需要加入的时候,可以将这个版本号改为1,此时,新的Git版本可以正确执行功能,而老的版本会出现报错
"Expected git repo version <= 0, found 1. Please upgrade Git"

filemode文件权限

#diff时考虑文件权限为true,不考虑为false
core.filemode=true | fasle

我们通过这个参数来决定是否会diff文件的权限,如果是源代码,可以关闭这个选项,如果是脚本,二进制程序等需要权限认证之类的还是要开启该参数的

git config core.filemode false

bare裸仓库

我们可以使用git init来将我们的目录转换为一个Git本地仓库或者初始化为一个新仓库。在初始化的时候我们可以加上--bare参数来决定是否创建一个裸仓库。

裸仓库一般指的是远端的中心仓库,可以被clonepush更新,但不包含工作区,因此不能执行常规的git命令,也不能进行直接的提交和变更。而普通仓库却正好相反,用于我们常规协作开发时的修改和提交。

# 裸仓库为true,普通仓库为false
core.bare = true | false

logallrefupdates 记录引用更新

core.logallupdates = true | false | always

当值为true时,会将所有引用(ref)的更新记录到$GIT_DIR/logs/中,包括更新的编号、日期和原因等内容。的值根据分支的不同为refs/heads/refs/remotes/

当值为always时,的值为refs/reflog

当仓库为裸仓库时,值为false

2.编辑git配置文件

`语法格式:
git config -e #针对当前仓库
git config -e --global #针对系统上所有仓库

1.4 Git的基本操作

Git的工作就是创建和保存你项目的快照及之后的快照进行对比

版本控制系统教程_第6张图片

说明:

  1. workspace:工作区
  2. staging area:暂存区/缓存区
  3. local repository:版本库或本地仓库
  4. remote repository:远程仓库
# git init 初始化仓库
# git add . 添加文件到暂存区
# git commit 将暂存区内容添加到仓库中

1.4.1 创建仓库命令

# git init 初始化仓库
# git clone 拷贝一份远程仓库,也就是下载一个项目

1.4.2 提交和修改

# git add 添加文件到暂存区
# git status 查看仓库当前状态,显示有变更的文件
# git diff 比较文件的不同,即暂存区和工作区的差异
# git commit 提交暂存区到本地仓库
# git reset 回退版本
# git rm 将文件从暂存区和工作区中删除
# git mv 移动或重命名工作区文件

1.4.2.1 提交日志
# git log 查看历史提交记录
# git blame  以列表形式查看指定文件的历史修改记录
1.4.2.2 远程操作
# git remote 远程仓库操作
# git fetch  从远程获取代码库
# git pull   下载远程代码并合并
# git push   上传远程代码并合并
# git merge:是用于从指定的commit(s)合并到当前分支,用来合并两个分支
git merge -b  // 指将 b 分支合并到当前分支
# git pull 相当于 git fetch + git merge。

扩展:Git常用命令速查

版本控制系统教程_第7张图片

1.5 Git的分支管理

几乎每一种版本控制系统都以某种形式支持分支,一个分支代表一条独立的开发线。

使用分支意味着你可以从开发主线上分离开来,然后在不影响主线的同时继续工作。
版本控制系统教程_第8张图片

Git 分支实际上是指向更改快照的指针。

有人把 Git 的分支模型称为必杀技特性,而正是因为它,将 Git 从版本控制系统家族里区分出来。

创建分支命令:

# git branch (branchname)

切换分支命令:

# git checkout (branchname)
`当你切换分支的时候,Git会用该分支最后提交的快照替换你的工作目录的内容,所以多个分支不需要多个目录

合并分支命令:

# git merge
`你可以多次合并到统一分支,也可以选择再合并之后直接删除被并入的分支

删除分支命令:

# git branch -D (branchname)

从实例中学习分支管理

`1.创建测试目录
[root@localhost ~]# mkdir Git_Study
[root@localhost ~]# cd Git_Study/
[root@localhost Git_Study]# git init
初始化空的 Git 仓库于 /root/Git_Study/.git/
[root@localhost Git_Study]# echo "This is Study about Git" >> REDME
[root@localhost Git_Study]# git add REDME #跟踪改动过的文件
[root@localhost Git_Study]# git commit -m "第一次版本提交" #进行提交
[master(根提交) 57761b5] 第一次版本提交
 1 file changed, 1 insertion(+)
 create mode 100644 REDME
[root@localhost Git_Study]# 

`2.列出分支
[root@localhost Git_Study]# git branch
* master
# 我们有一个叫做master的分支,前面的*号表示该分支是当前分支

`3.创建一个新的分支
[root@localhost Git_Study]# git branch test
[root@localhost Git_Study]# git branch
* master
  test

`4.在master分支上创建文件后进行提交后切换分支
[root@localhost Git_Study]# bash /root/Shell/1.sh  #运行一个从远程备份的脚本
[root@localhost Git_Study]# ls
10.二进制安装Tomcat脚本.sh  13.进制转换脚本.sh  2.Shell执行远程主机命令.sh  5.expect的学习脚本.sh         8.MySQL8.0的安装脚本.sh  飞书调用接口
11.信号捕捉trap.sh          14.SMTP搭建脚本.sh  3.免密脚本.sh               6.expect进行多个参数传递.sh   9.PHP二进制安装脚本.sh
12.使用you-get下载视频.sh   1.备份脚本.sh       4.定期增量备份脚本.sh       7.利用expect批量做SSH互信.sh  REDME
[root@localhost Git_Study]# git add .
[root@localhost Git_Study]# git commit -m '第二次版本提交'
[master 941b221] 第二次版本提交
16 files changed, 816 insertions(+)
……
`切换分支后查看文件只有一个REDME
[root@localhost Git_Study]# git checkout test
切换到分支 'test'
[root@localhost Git_Study]# ls
REDME
[root@localhost Git_Study]# git checkout master
切换到分支 'master'
[root@localhost Git_Study]# ls
10.二进制安装Tomcat脚本.sh  13.进制转换脚本.sh  2.Shell执行远程主机命令.sh  5.expect的学习脚本.sh         8.MySQL8.0的安装脚本.sh  飞书调用接口
11.信号捕捉trap.sh          14.SMTP搭建脚本.sh  3.免密脚本.sh               6.expect进行多个参数传递.sh   9.PHP二进制安装脚本.sh
12.使用you-get下载视频.sh   1.备份脚本.sh       4.定期增量备份脚本.sh       7.利用expect批量做SSH互信.sh  REDME

`5.使用git checkout -b (branchname)命令创建新分支并立即切换到该分支下
[root@localhost Git_Study]# git checkout -b newtest
切换到一个新分支 'newtest'
[root@localhost Git_Study]# git rm REDME
rm 'REDME'
[root@localhost Git_Study]# touch REDME2
[root@localhost Git_Study]# git add .
[root@localhost Git_Study]# git commit -m '第三次提交'
[newtest a45dc89] 第三次提交
 2 files changed, 1 deletion(-)
 delete mode 100644 REDME
 create mode 100644 REDME2

如你所见,我们创建了一个分支,在该分支上移除了一些文件 REDME,并添加了 REDME2 文件,然后切换回我们的主分支,删除的 REDME 文件又回来了,且新增加的 REDME2 不存在主分支中。

使用分支将工作切分开来,从而让我们能够在不同开发环境中做事,并来回切换

`一旦分支有了独立内容,你终究会希望将他合并回到你的主分支.你可以使用以下命令将任何分支合并到当前分支中去
[root@localhost Git_Study]# git checkout test
切换到分支 'test'
[root@localhost Git_Study]# ls
REDME
[root@localhost Git_Study]# touch info.php
[root@localhost Git_Study]# git checkout master
切换到分支 'master'
[root@localhost Git_Study]# git merge test
Already up-to-date.
`合并不仅仅是简单的文件添加,移除的操作,Git也会合并修改
[root@localhost Git_Study]# git checkout test
切换到分支 'test'
[root@localhost Git_Study]# vim info.php 
[root@localhost Git_Study]# cat info.php 
<?phpphpinfo;?>
[root@localhost Git_Study]# git checkout master
切换到分支 'master'
[root@localhost Git_Study]# git merge test
Already up-to-date.
[root@localhost Git_Study]# cat info.php 
<?phpphpinfo;?>
[root@localhost Git_Study]# 

1.6 Git的提交历史

Git的提交历史一般常用两个命令:

  1. git log --查看历史提交记录
  2. git blame --以列表形式查看指定文件的历史修改记录

1.6.1 git log

1.语法格式

`语法格式:
git log [<options>] [<revision-range>] [[--] <path>]

2.常见使用

`git log 列出历史提交记录

`git log --oneline 查看历史记录的简介版

`git log --graph  --all 查看历史中什么时候出现了分支,合并

`git log --author 查看指定用户提交的部分
# git log --author=haohe
`git log --since--before 和 --until和--after 查看指定日志
# git log --oneline --before={3.weeks.ago} --after={2010-04-18}

`git log --no-merges 隐藏合并提交

1.6.2 git blame

`查看指定文件的修改记录
# git blame 

1.7 Git的标签

1.7.1 标签介绍

​ 发布一个版本时,我们通常先在版本库中打一个标签(tag),这样就唯一确定了打标签时刻的版本。将来无论什么时候,取某个标签的版本,就是把那个打标签的时刻的历史版本取出来。

所以,标签也是版本库的一个快照。

​ Git 的标签虽然是版本库的快照,但其实它就是指向某个 commit 的指针(跟分支很像对不对?但是分支可以移动,标签不能移动),所以,创建和删除标签都是瞬间完成的

`便于理解的故事:
"请把上周一的那个版本打包发布,commit号是6a5819e…"
"一串乱七八糟的数字不好找!"
如果换一个办法:
"请把上周一的那个版本打包发布,版本号是v1.2"
"好的,按照tag v1.2查找commit就行!"
所以,tag就是一个让人容易记住的有意义的名字,它跟某个commit绑在一起。

​ 同大多数 VCS 一样,Git 也可以对某一时间点上的版本打上标签。人们在发布某个软件版本(比如 v1.0 等等)的时候,经常这么做。

1.7.2 新建标签

Git 使用的标签有两种类型:轻量级的(lightweight)含附注的(annotated)

轻量级标签就像是个不会变化的分支,实际上它就是个指向特定提交对象的引用。

而含附注标签,实际上是存储在仓库中的一个独立对象,它有自身的校验和信息,包含着标签的名字,电子邮件地址和日期,以及标签说明,标签本身也允许使用 GNU Privacy Guard (GPG) 来签署或验证。

一般我们都建议使用含附注型的标签,以便保留相关信息;

当然,如果只是临时性加注标签,或者不需要旁注额外信息,用轻量级标签也没问题。

# git tag v1.0 创建标签
# git tag      查看标签
# git tag v1.1 
# git tag -d v1.1 删除标签
# git show v1.0 查看此版本所修改的内容

1.8 Git 与Github

1.8.1 添加远程库

# git remote add [shortname] [url]

由于你的本地 Git 仓库和 GitHub 仓库之间的传输是通过SSH加密的,所以我们需要配置验证信息:

使用以下命令生成 SSH Key:

# ssh-keygen -t rsa -C "[email protected]"

版本控制系统教程_第9张图片

版本控制系统教程_第10张图片

`使用命令测试:
ssh -T [email protected]

# 如果出现Permission denied (publickey). 的情况,就重新生成一个密钥和重新添加Github

版本控制系统教程_第11张图片

`以下命令说明我们已成功连上了Github
`之后登录后点击"Nes repository"

版本控制系统教程_第12张图片

`以上信息告诉我们可以从这个仓库克隆出新的仓库,也可以把本地仓库的内容推送到GitHub仓库.现在根据GitHub的提示,在本地仓库下运行命令
[root@localhost ~]# cd Git_Study/
[root@localhost Git_Study]# echo "常用的Shell脚本" >> REDME.md
[root@localhost Git_Study]# git commit -m "添加README.md文件"
[root@localhost Git_Study]# git remote add origin [email protected]:HH17740639615/Git_Study.git
[root@localhost Git_Study]# git push -u origin master
对象计数中: 25, 完成.
Delta compression using up to 8 threads.
压缩对象中: 100% (22/22), 完成.
写入对象中: 100% (25/25), 13.11 KiB | 0 bytes/s, 完成.
Total 25 (delta 2), reused 0 (delta 0)
remote: Resolving deltas: 100% (2/2), done.
To [email protected]:HH17740639615/Git_Study.git
 * [new branch]      master -> master
分支 master 设置为跟踪来自 origin 的远程分支 master。

1.8.2 查看当前的远程库

`git remote
[root@localhost Git_Study]# git remote -v
origin	[email protected]:HH17740639615/Git_Study.git (fetch)
origin	[email protected]:HH17740639615/Git_Study.git (push)
[root@localhost Git_Study]# 
"执行时加上 -v 参数,你还可以看到每个别名的实际链接地址"

1.8.3 提取远程仓库

Git有两个命令用来提取远程仓库的更新

1.从远程仓库下载新分支与数据

# git fetch
该命令执行完后需要执行 git merge 远程分支到你所在的分支

2.从远端仓库提取数据并尝试合并到当前分支:

# git merge
该命令就是在执行 git fetch 之后紧接着执行 git merge 远程分支到你所在的任意分支

版本控制系统教程_第13张图片
假设你配置好了一个远程仓库,并且你想要提取更新的数据,你可以首先执行 git fetch [alias] 告诉 Git 去获取它有你没有的数据,然后你可以执行 git merge [alias]/[branch] 以将服务器上的任何更新(假设有人这时候推送到服务器了)合并到你的当前分支。

接下来我们在 Github 上点击" README" 并在线修改它:

版本控制系统教程_第14张图片

[root@localhost Git_Study]# git fetch origin  本地更新修改
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
展开对象中: 100% (3/3), 完成.
来自 github.com:HH17740639615/Git_Study
   bafd5c1..a1c75b6  master     -> origin/master
[root@localhost Git_Study]# git merge origin/master  更新同步到本地
更新 bafd5c1..a1c75b6
Fast-forward
 REDME | 1 +
 1 file changed, 1 insertion(+)
[root@localhost Git_Study]# cat REDME  查看文本内容
This is Study about Git
这是一个Shell脚本的仓库
[root@localhost Git_Study]# 

1.8.4 推送到远程仓库

`推送你的新分支与数据到某个远端仓库命令:
git push [alias] [branch]
`以上命令将你的[branch]分支推送成为[alias]远程仓库上的[brach]分支
[root@localhost Git_Study]# touch runoob_test.txt  #新建文件
[root@localhost Git_Study]# git add runoob_test.txt 
[root@localhost Git_Study]# git commit -m "添加到远程"
[master da15ba7] 添加到远程
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 runoob_test.txt
[root@localhost Git_Study]# git push origin master  #推送到GitHub

版本控制系统教程_第15张图片

1.8.5 删除远程仓库

git remote rm [别名]

# git remote -v
origin    [email protected]:tianqixin/runoob-git-test.git (fetch)
origin    [email protected]:tianqixin/runoob-git-test.git (push)

# 添加仓库 origin2
# git remote add origin2 [email protected]:tianqixin/runoob-git-test.git

# git remote -v
origin    [email protected]:tianqixin/runoob-git-test.git (fetch)
origin    [email protected]:tianqixin/runoob-git-test.git (push)
origin2    [email protected]:tianqixin/runoob-git-test.git (fetch)
origin2    [email protected]:tianqixin/runoob-git-test.git (push)

# 删除仓库 origin2
# git remote rm origin2
# git remote -v
origin    [email protected]:tianqixin/runoob-git-test.git (fetch)
origin    [email protected]:tianqixin/runoob-git-test.git (push)

1.9 Git服务器搭建

1.安装Git

[root@localhost ~]# yum -y install curl-devel expat-devel gettext-devel openssl-devel zlib-devel perl-devel
[root@localhost ~]# yum -y install git
`创建一个git用户组和用户,用来运行git服务
[root@localhost ~]# groupadd git
[root@localhost ~]# useradd -g git git

2.创建证书登录

[root@localhost ~]# cd /home/git/
[root@localhost git]# mkdir .ssh
[root@localhost git]# chmod 755 .ssh
[root@localhost git]# touch .ssh/authorized_keys
[root@localhost git]# chmod 644 .ssh/authorized_keys

3.初始化Git仓库

`首先选定一个目录作为Git仓库,假定是/home/gitrepo/runoob.git
[root@localhost home]# mkdir gitrepo
[root@localhost home]# chown git:git gitrepo/
[root@localhost home]# cd gitrepo/
[root@localhost gitrepo]# git init --bare runoob.git
Initialized empty Git repository in /home/gitrepo/runoob.git/
`以上命令Git创建一个空仓库,服务器上的Git仓库通常都以.git结尾。然后,把仓库所属用户改为git
[root@localhost gitrepo]# chown -R git:git runoob.git
[root@localhost gitrepo]# echo "centos" | passwd --stdin git

4.克隆仓库

[root@localhost ~]# git clone [email protected]:/home/git/gitrepo/runoob.git/
正克隆到 'runoob'...
[email protected]'s password: 
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0)
接收对象中: 100% (3/3), 完成.
检查连接... 完成。

1.10 Gitlab的安装

版本控制系统教程_第16张图片

1.10.1 在Centos7上安装

1.安装前的准备
`安装相关依赖文件
yum install -y curl policycoreutils-python openssh-server perl
`配置ssh开机自启动
systemctl enable sshd && systemctl start sshd
`关闭防火墙或者放行HTTP/HTTPS
systemctl stop firewalld
firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=https
`安装 Postfix 以发送电子邮件通知。如果您想使用其他解决方案发送电子邮件,请跳过此步骤并在安装极狐GitLab 后配置外部 SMTP 服务器
yum -y install postfix
systemctl enable postfix && systemctl restart postfix
2.下载/安装极狐GitLab
curl -fsSL https://packages.gitlab.cn/repository/raw/scripts/setup.sh | /bin/bash

yum -y install gitlab-jh
3.访问极狐GitLab 实例并登录
除非您在安装过程中指定了自定义密码,否则将随机生成一个密码并存储在 /etc/gitlab/initial_root_password 文件中(出于安全原因,24 小时后,此文件会被第一次 `gitlab-ctl reconfigure` 自动删除,因此若使用随机密码登录,建议安装成功初始登录成功之后,立即修改初始密码)。使用此密码和用户名 `root` 登录

1.11 TortoiseGit(大乌龟)教程

1.安装教程

1. 下载TortoiseGit

官方下载地址:https://tortoisegit.org/download/
版本控制系统教程_第17张图片

第一个选项基于PuTTY,做了一些优化,第二个选项为Git默认的SSH客户端

版本控制系统教程_第18张图片

选择安装路径

版本控制系统教程_第19张图片

2.安装中文语言包

版本控制系统教程_第20张图片

安装好中文语言包后,点击Refresh就会出现中文简体语言

版本控制系统教程_第21张图片

2.配置教程

1.新建一个空白文件夹

2.修改大乌龟的右键菜单
版本控制系统教程_第22张图片
3.拉取远程代码
版本控制系统教程_第23张图片

推荐使用SSH模式进行拉取,提前配置免密

2.Svn

2.1 Svn的基本介绍

2.1.1 SVN 简介


​ Subversion(SVN) 是一个开源的版本控制系統, 也就是说 Subversion 管理着随时间改变的数据。 这些数据放置在一个中央资料档案库(repository) 中。 这个档案库很像一个普通的文件服务器, 不过它会记住每一次文件的变动。 这样你就可以把档案恢复到旧的版本, 或是浏览文件的变动历史。


2.1.2 SVN 的一些概念

  • **repository(源代码库)*源代码统一存放的地方
  • **Checkout(提取)*当你手上没有源代码的时候,你需要从 repository checkout 一份
  • **Commit(提交)*当你已经修改了代码,你就需要Commit到repository
  • **Update (更新) *当你已经 checkout 了一份源代码, update 一下你就可以和Repository上的源代码同步,你手上的代码就会有最新的变更

​ 日常开发过程其实就是这样的(假设你已经Checkout并且已经工作了几天):Update(获得最新的代码) -->作出自己的修改并调试成功 --> Commit(大家就可以看到你的修改了) 。

​ 如果两个程序员同时修改了同一个文件呢, SVN 可以合并这两个程序员的改动,实际上 SVN 管理源代码是以行为单位的,就是说两个程序员只要不是修改了同一行程序,SVN 都会自动合并两种修改。如果是同一行,SVN 会提示文件 Conflict, 冲突,需要手动确认。

2.1.3 SVN 的主要功能

  • 目录版本控制

    ​ CVS 只能跟踪单个文件的历史, 不过 Subversion 实作了一个 “虚拟” 的版本控管文件系统, 能够依时间跟踪整个目录的变动。 目录和文件都能进行版本控制

  • 真实的版本历史

    ​ 自从 CVS 限制了文件的版本记录,CVS 并不支持那些可能发生在文件上,但会影响所在目录内容的操作,如同复制和重命名。除此之外,在 CVS 里你不能用拥有同样名字但是没有继承老版本历史或者根本没有关系的文件替换一个已经纳入系统的文件。在 Subversion 中,你可以增加(add)、删除(delete)、复制(copy)和重命名(rename),无论是文件还是目录。所有的新加的文件都从一个新的、干净的版本开始

  • 自动提交

    ​ 一个提交动作,不是全部更新到了档案库中,就是不完全更新。这允许开发人员以逻辑区间建立并提交变动,以防止当部分提交成功时出现的问题

  • 纳入版本控管的元数据

    ​ 每一个文件与目录都附有一組属性关键字并和属性值相关联。你可以创建, 并儲存任何你想要的Key/Value对。 属性是随着时间来作版本控管的,就像文件內容一样

  • 选择不同的网络层

    ​ Subversion 有抽象的档案库存取概念, 可以让人很容易地实作新的网络机制。 Subversion 可以作为一个扩展模块嵌入到 Apache HTTP 服务器中。这个为 Subversion 提供了非常先进的稳定性和协同工作能力,除此之外还提供了许多重要功能: 举例来说, 有身份认证, 授权, 在线压缩, 以及文件库浏览等等。还有一个轻量级的独立 Subversion 服务器, 使用的是自定义的通信协议, 可以很容易地通过 ssh 以 tunnel 方式使用

  • 一致的数据处理方式

    ​ Subversion 使用二进制差异算法来异表示文件的差异, 它对文字(人类可理解的)与二进制文件(人类无法理解的) 两类的文件都一视同仁。 这两类的文件都同样地以压缩形式储存在档案库中, 而且文件差异是以两个方向在网络上传输的

  • 有效的分支(branch)与标签(tag)

    ​ 在分支与标签上的消耗并不必一定要与项目大小成正比。 Subversion 建立分支与标签的方法, 就只是复制该项目, 使用的方法就类似于硬连接(hard-link).所以这些操作只会花费很小, 而且是固定的时间

  • Hackability

    ​ Subversion没有任何的历史包袱; 它主要是一群共用的 C 程序库, 具有定义完善的API。这使得 Subversion 便于维护, 并且可被其它应用程序与程序语言使用

2.1.4 优于 CVS 之处

  • 1、原子提交:一次提交不管是单个还是多个文件,都是作为一个整体提交的,所以要么全部提交成功,要么就是全部不成功,这样就不会引起数据库的不完整和数据损坏
  • 2、重命名、复制、删除文件等动作都保存在版本历史记录当中
  • 3、对于二进制文件,使用了节省空间的保存方法。(简单的理解,就是只保存和上一版本不同之处)
  • 4、目录也有版本历史。整个目录树可以被移动或者复制,操作很简单,而且能够保留全部版本记录
  • 5、分支的开销非常小
  • 6、优化过的数据库访问,使得一些操作不必访问数据库就可以做到。这样减少了很多不必要的和数据库主机之间的网络流量

2.2 Svn的安装配置

2.2.1 在Windows上安装SVN

2.2.2 在Linux上安装SVN

`Centos
[root@localhost ~]# yum -y insatll subversion

`Ubuntu/Debain
[root@localhost ~]# apt-get -y insatll sunversion

2.3 SVN生命周期

2.3.1 创建版本库

​ 版本库相当于一个集中的空间,用于存放开发者所有的工作成果。版本库不仅能存放文件,还包括了每次修改的历史,即每个文件的变动历史

Create操作是用来创建一个新的版本库。大多数情况下这个操作只会执行一次。当你创建一个新的版本库的时候,你的版本控制系统会让你提供一些信息来标识版本库,例如创建的位置和版本库的名字

2.3.2 检出

Checkout 操作是用来从版本库创建一个工作副本。工作副本是开发者私人的工作空间,可以进行内容的修改,然后提交到版本库中

2.3.3 更新

update操作是用来更新版本库的。这个操作将工作副本与版本库进行同步。由于版本库是由整个团队共用的,当其他人提交了他们的改动之后,你的工作副本就会过期

​ 让我们假设 Tom 和 Jerry 是一个项目的两个开发者。他们同时从版本库中检出了最新的版本并开始工作。此时,工作副本是与版本库完全同步的。然后,Jerry 很高效的完成了他的工作并提交了更改到版本库中

​ 此时 Tom 的工作副本就过期了。更新操作将会从版本库中拉取 Jerry 的最新改动并将 Tom 的工作副本进行更新

2.3.4 执行变更

​ 当检出之后,你就可以做很多操作来执行变更。编辑是最常用的操作。你可以编辑已存在的文件,例如进行文件的添加/删除操作

​ 你可以添加文件/目录。但是这些添加的文件目录不会立刻成为版本库的一部分,而是被添加进待变更列表中,直到执行了 commit 操作后才会成为版本库的一部分。

​ 同样地你可以删除文件/目录。删除操作立刻将文件从工作副本中删除掉,但该文件的实际删除只是被添加到了待变更列表中,直到执行了 commit 操作后才会真正删除。

Rename 操作可以更改文件/目录的名字。"移动"操作用来将文件/目录从一处移动到版本库中的另一处

2.3.5 复查变化

​ 当你检出工作副本或者更新工作副本后,你的工作副本就跟版本库完全同步了。但是当你对工作副本进行一些修改之后,你的工作副本会比版本库要新。在 commit 操作之前复查下你的修改是一个很好的习惯。

​ Status 操作列出了工作副本中所进行的变动。正如我们之前提到的,你对工作副本的任何改动都会成为待变更列表的一部分。Status 操作就是用来查看这个待变更列表。

​ Status 操作只是提供了一个变动列表,但并不提供变动的详细信息。你可以用 diff 操作来查看这些变动的详细信息。


2.3.6 修复错误

​ 我们来假设你对工作副本做了许多修改,但是现在你不想要这些修改了,这时候 revert 操作将会帮助你。

​ Revert 操作重置了对工作副本的修改。它可以重置一个或多个文件/目录。当然它也可以重置整个工作副本。在这种情况下,revert 操作将会销毁待变更列表并将工作副本恢复到原始状态。


2.3.7 解决冲突

​ 合并的时候可能会发生冲突。Merge 操作会自动处理可以安全合并的东西。其它的会被当做冲突。例如,“hello.c” 文件在一个分支上被修改,在另一个分支上被删除了。这种情况就需要人为处理。Resolve 操作就是用来帮助用户找出冲突并告诉版本库如何处理这些冲突。


2.3.8 提交更改

​ Commit 操作是用来将更改从工作副本到版本库。这个操作会修改版本库的内容,其它开发者可以通过更新他们的工作副本来查看这些修改。

​ 在提交之前,你必须将文件/目录添加到待变更列表中。列表中记录了将会被提交的改动。当提交的时候,我们通常会提供一个注释来说明为什么会进行这些改动。这个注释也会成为版本库历史记录的一部分。Commit 是一个原子操作,也就是说要么完全 提交成功,要么失败回滚。用户不会看到成功提交一半的情况

2.4 SVN启动模式

`首先,在服务器端进行SVN版本库的相关配置
# 手动新建版本库目录
[root@localhost ~]# mkdir /opt/svn
# 使用svnadmin 创建版本库
[root@localhost ~]# svnadmin create /opt/svn/runoob
# 使用svnserve启动服务
[root@localhost ~]# svnserve -d -r 目录 --listen-port 端口号
--- -r:配置方式决定了版本库访问方式
--- --listen-port:指定SVN监听端口,不加此参数,SVN默认监听3690
[root@localhost ~]# svnserve -d -r /opt/svn/runoob/ --listen-port 3691

由于-r配置方式不一样,SVN启动就可以有两种不同的访问方式

  1. -r直接指定到版本库(称之为单库svnserve方式)

    svnserve -d -r /opt/svn/runoob/ --listen-port 3691
    
    # 在这种情况下,一个svnserve只能为一个版本库工作
    `authz配置文件种对版本库权限的配置应该这样写
    [groups]
    admin=user1
    dev=user2
    [/]
    @admin=rw
    user2=r
    
    # 使用类似这样的URL:svn://127.0.01:3691/即可访问runoob版本库
    
  2. 指定到版本库的上级目录(称之为多库svnserve方式)

    svnserve -d -r /opt/svn --listen-port 3691
    
    # 这种情况下,一个svnserve可以为多个版本库工作
    `authz配置文件种对版本库权限应这样写
    [groups]
    admin=user1
    dev=user2
    [runoob:/]
    @admin=rw
    user2=r
    
    [runoob01:/]
    @admin=rw
    user2=r
    
    # 如果此时你还用[/],则表示所有库的根目录,同理,[/src]表示所有库的根目录下的src目录。
    使用类似这样的URL:svn://192.168.0.1/runoob 即可访问runoob版本库。
    

2.5 SVN 创建版本库

使用svn命令创建资源库

[root@localhost ~]# svnadmin create /opt/svn/runoob
[root@localhost ~]# ll /opt/svn/runoob/
total 24K
drwxr-xr-x 2 root root 4.0K Jun 14 16:33 conf
drwxr-sr-x 6 root root 4.0K Jun 14 16:33 db
-r--r--r-- 1 root root    2 Jun 14 16:33 format
drwxr-xr-x 2 root root 4.0K Jun 14 16:33 hooks
drwxr-xr-x 2 root root 4.0K Jun 14 16:33 locks
-rw-r--r-- 1 root root  229 Jun 14 16:33 README.txt
[root@localhost svn]# 

进入/opt/svn/runoob/conf目录,修改默认配置文件配置,包括svnserve.conf,passwd,authz配置相关用户和权限

  1. svn 服务配置文件 svnserve.conf

    svn 服务配置文件为版本库目录中的文件 conf/svnserve.conf.该文件仅由一个 [general] 配置段组成
    
    [root@localhost conf]# cat svnserve.conf
    [general]
    anon-access = none
    auth-access = write
    password-db = /home/svn/passwd
    authz-db = /home/svn/authz
    realm = tiku 
    
    ---参数介绍:
    anon-access: 控制非鉴权用户访问版本库的权限,取值范围为 "write""read""none"。 即 "write" 为可读可写,"read" 为只读,"none" 表示无访问权限,默认值:read
    auth-access: 控制鉴权用户访问版本库的权限。取值范围为 "write""read""none"。 即"write"为可读可写,"read"为只读,"none"表示无访问权限,默认值:write
    authz-db: 指定权限配置文件名,通过该文件可以实现以路径为基础的访问控制。 除非指定绝对路径,否则文件位置为相对conf目录的相对路径,默认值:authz
    realm: 指定版本库的认证域,即在登录时提示的认证域名称。若两个版本库的认证域相同,建议使用相同的用户名口令数据文件。默认值:一个UUID(Universal Unique IDentifier,全局唯一标示)
    
  2. 用户名口令文件passwd

        用户名口令文件由 svnserve.conf 的配置项 password-db 指定,默认为 conf 目录中的passwd。该文件仅由一个 [users] 配置段组成。
    
    [users] 配置段的配置行格式如下:
    <用户名> = <口令>
    
    [users]
    admin = admin
    thinker = 123456
    
  3. 权限配置文件

       权限配置文件由 svnserve.conf 的配置项 authz-db 指定,默认为 conf 目录中的 authz。该配置文件由一个 [groups] 配置段和若干个版本库路径权限段组成。
    
    [groups]配置段中配置行格式如下:
    
    <用户组> = <用户列表>
    版本库路径权限段的段名格式如下:
    [<版本库名>:<路径>] 
    
    [groups]
    g_admin = admin,thinker
    
    [admintools:/]
    @g_admin = rw
    * =
    
    [test:/home/thinker]
    thinker = rw
    * = r
    
  4. svn 服务配置文件 svnserve.conf

    svn 服务配置文件为版本库目录中的文件 conf/svnserve.conf.该文件仅由一个 [general] 配置段组成
    
    [root@localhost conf]# cat svnserve.conf
    [general]
    anon-access = none
    auth-access = write
    password-db = /home/svn/passwd
    authz-db = /home/svn/authz
    realm = tiku 
    
    ---参数介绍:
    anon-access: 控制非鉴权用户访问版本库的权限,取值范围为 "write""read""none"。 即 "write" 为可读可写,"read" 为只读,"none" 表示无访问权限,默认值:read
    auth-access: 控制鉴权用户访问版本库的权限。取值范围为 "write""read""none"。 即"write"为可读可写,"read"为只读,"none"表示无访问权限,默认值:write
    authz-db: 指定权限配置文件名,通过该文件可以实现以路径为基础的访问控制。 除非指定绝对路径,否则文件位置为相对conf目录的相对路径,默认值:authz
    realm: 指定版本库的认证域,即在登录时提示的认证域名称。若两个版本库的认证域相同,建议使用相同的用户名口令数据文件。默认值:一个UUID(Universal Unique IDentifier,全局唯一标示)
    
  5. 用户名口令文件passwd

        用户名口令文件由 svnserve.conf 的配置项 password-db 指定,默认为 conf 目录中的passwd。该文件仅由一个 [users] 配置段组成。
    
    [users] 配置段的配置行格式如下:
    <用户名> = <口令>
    
    [users]
    admin = admin
    thinker = 123456
    
  6. 权限配置文件

       权限配置文件由 svnserve.conf 的配置项 authz-db 指定,默认为 conf 目录中的 authz。该配置文件由一个 [groups] 配置段和若干个版本库路径权限段组成。
    
    [groups]配置段中配置行格式如下:
    
    <用户组> = <用户列表>
    版本库路径权限段的段名格式如下:
    [<版本库名>:<路径>] 
    
    [groups]
    g_admin = admin,thinker
    
    [admintools:/]
    @g_admin = rw
    * =
    
    [test:/home/thinker]
    thinker = rw
    * = r
    

你可能感兴趣的:(运维)