小阿轩yx-案例:代码管理系统简介与部署
前言
- 开发一个项目时,如果只有几十行代码或几百行代码时维护还算简单,但是代码数量达到一定程度或两三个人共同开发一个项目时,就很容易会出现代码混乱、冲突、排错难等问题。
- 代码编写完成以后发现整个项目运行不了时,提交的代码也无法确认到责任人,导致维护项目时需要花费数倍的时间。
- 版本控制系统就是解决上述问题应运而生。
版本控制
- 指对软件开发过程中各种程序代码、配置文件及说明文档等文件变更的管理,是软件配置管理的核心思想之一。
版本控制
版本控制概念
- 最主要的功能就是追踪文件的变更。
- 它将什么时候、什么人更改了文件的什么内容等信息忠实地了记录下来。
- 每一次文件的改变,文件的版本号都将增加。
- 除了记录版本变更外,版本控制的另一个重要功能是并行开发。
- 软件开发往往是多人协同作业,版本控制可以有效地解决版本的同步以及不同开发者之间的开发通信问题,提高协同开发的效率。
并行开发
- 最常见的不同版本软件的错误(Bug)修正问题也可以通过版本控制中分支与合并的方法有效地解决。
具体来说
- 每一项开发任务中,都需要首先设定开发基线,确定各个配置项的开发初始版本,在开发过程中,开发人员基于开发基线的版本,开发出所需的目标版本。
- 当发生需求变更时,通过对变更的评估,确定变更的影响范围,对被影响的配置项的版本进行修改,根据变更的性质使配置项的版本树继续延伸或产生新的分支,形成新的目标版本,而对于不受变更影响的配置项则不应发产生变动。
- 同时,应能够将变更所产生的对版本的影响进行记录和跟踪。
- 必要时还可以回退到以前的版本。
版本控制
- 是软件配置管理的核心功能。
- 所有置于配置库中的元素都应自动予以版本的标识,并保证版本命名的唯一性。
- 版本在生成过程中,自动依照设定的使用模型自动分支、演进。
- 除了系统自动记录的版本信息以外,为了配合软件开发流程的各个阶段。还需要定义、收集一些元数据来记录版本的辅助信息和规范开发流程,并为今后对软件过程的度量做好准备。
- 当然如果选用的工具支持,这些辅助数据将能直接统计出过程数据,从而方便软件过程改进活动的进行。
- 对于配置库中的各个基线控制项,应该根据其基线的位置和状态来设置相应的访问权限。
- 一般来说,对于基线版本之前的各个版本都应处于被锁定的状态,如需要对它们进行变更,则应按照变更控制的流程来进行操作。
版本控制(Revision control)
- 是一种在开发的过程中用于管理我们对文件、目录或工程等内容的修改历史,方便查看更改历史记录,备份以便恢复以前的版本的软件工程技术。
- 简单来说就是用于管理多人协同开发项目的技术。
- 没有进行版本控制或者版本控制本身就缺乏正确的流程管理,在软件开发过程中将会引入很多问题
如下面这些问题
- 软件代码的一致性
- 软件内容的冗余
- 软件过程的事物性
- 软件开发过程中的并发性
- 软件源代码的安全性
- 软件的整合
- 无论是工作还是学习,或者是自己做笔记,都有这样一个阶段!
- 我们就迫切需要一个版本控制工具。(多人开发就必须要使用版本控制)
版本控制的功能
检入检出控制
- 软件开发人员对源文件的修改不能在软件配置管理库中进行,对源文件的修改依赖于基本的文件系统并在各自的工作空间下进行。
- 为方便软件开发,需要不同的软件开发人员组织各自的工作空间。
一般说来,不同的工作空间由不同的目录表示,而对工作空间的访问,由文件系统提供的文件访问权限加以控制。
访问控制
- 需要管理各个人员存取或修改一个特定软件配置对象的权限。
- 开发人员能够从库中取出对应项目的配置项进行修改,并检入到软件配置库中,对版本进行 “升级”;
- 配置管理人员可以确定多余配置项并删除。
同步控制的实质
- 是版本的检入检出控制。
检入
- 就是把软件配置项从用户的工作环境存入到软件配置库的过程
检出
- 就是把软件配置项从软件配置库中取出的过程。
检入是检出的逆过程。
同步控制可用来确保由不同的人并发执行的修改不会产生混乱。
分支和合并
版本分支(以一个已有分支的特定版本为起点,但是独立发展的版本序列)的人工方法
- 就是从主版本——称为主干上拷贝一份,并做上标记。
- 实行了版本控制后,版本的分支也是一份拷贝,这时的拷贝过程和标记动作由版本控制系统完成。
版本合并(来自不同分支的两个版本合并为其中一个分支的新版本)有两种途径
- 一是将版本A的内容附加到版本B中;
- 另一种是合并版本 A 和版本 B 的内容,形成新的版本 C。
历史记录
- 版本的历史记录有助于对软件配置项进行审核,有助于追踪问题的来源。
- 包括版本号、版本修改时间、版本修改者、版本修改描述等最基本的内容,还可以有其他一些辅助性内容,比如版本的文件大小和读写属性。
版本控制的流程
创建配置项
- 项目成员依据《配置管理计划》,在配置库中创建属于其任务范围内的配置项。
- 此时配置项的状态为“草稿”,其版本号格式为 0.YZ。
修改状态为 “草稿” 的配置项目
- 项目成员使用配置管理软件的 Check in/check out 功能,可以自由修改处于 “草稿” 状态的配置项,版本号格式为 0.YZ。
技术评审或领导审批
- 如果配置项是技术文档,则需要接受技术评审。
- 如果配置项是 “计划” 这类文件,则需要项目经理(或上级领导)的审批。
- 若配置项通过了技术评审或领导审批,则转向下一步·否则转回上一步。
正式发布
- 配置项通过技术评审或领导审批之后。
- 则配置项的状态从 “草稿” 变为 “正式发布”,版本号格式为 X.Y。
变更
- 修改处于 “正式发布” 状态的配置项,必须按照 “变更控制流程” 执行。
版本控制的优势
- 实现跨区域多人协同开发
- 追踪和记载一个或者多个文件的历史记录
- 组织和保护你的源代码和文档
- 统计工作量
- 并行开发、提高开发效率
- 跟踪记录整个软件的开发过程减轻开发人员的负担,节省时间,同时降低人为错误
版本控制的分类
本地版本控制
- 许多人习惯用复制整个项目目录的方式来保存不同的版本,或许还会改名加上备份时间以示区别。
- 这么做唯一的好处就是简单,但是特别容易犯错。
- 有时候会混淆所在的工作目录,一不小心会写错文件或者覆盖意想外的文件。
为了解决这个问题,在很久以前就开发了许多种本地版本控制系统,大多都是采用某种简单的数据库来记录文件的历次更新差异。
- 但是最大的弊端就是无法让位于不同系统上的开发者协同工作。
集中化的版本控制
- (centralized Version ControlSystems,简称 CVCS)应运而生解决不同开发者之间的协同工作。
- 这类系统,诸如 CVS、Subversion 以及 Perforce 等,都有一个单一的集中管理的服务器,保存所有文件的修订版本,而协同工作的人们都通过客户端连到这台服务器,取出最新的文件或者提交更新。
好处
- 特别是相较于老式的本地 VCS 来说。
- 每个人都可以在一定程度上看到项目中的其他人正在做些什么。
- 而管理员也可以轻松掌控每个开发者的权限,并且管理一个 CVCS 要远比在各个客户端上维护本地数据库来得轻松容易。
事分两面,有好有坏
缺点
- 中央服务器的单点故障。
- 如果宕机一小时,那么在这一小时内,谁都无法提交更新,也就无法协同工作。
- 如果中心数据库所在的磁盘发生损坏,又没有做恰当备份,毫无疑问你将丢失所有数据一包括项目的整个变更历史,只剩下人们在各自机器上保留的单独快照。
- 本地版本控制系统也存在类似问题,只要整个项目的历史记录被保存在单一位置,就有丢失所有历史更新记录的风险。
分布式版本控制
- 分布式版本控制系统(Distributed Version Control system,简称 DVCS)面世避免了中央服务器的单点故障。
- 这类系统中像 Git、Mercurial、Bazaar 以及 Darcs 等,客户端并不只提取最新版本的文件快照,而是把代码仓库完整地镜像下来,包括完整的历史记录。
- 这样任何一处协同工作用的服务器发生故障,事后都可以用任何一个镜像出来的本地仓库恢复。每一次的克隆操作,实际上都是一次对代码仓库的完整备份。
更进一步,许多这类系统都可以指定和若干不同的远端代码仓库进行交互。
籍此,就可以在同一个项目中,分别和不同工作小组的人相互协作。
优势
- 可以根据需要设定不同的协作流程
- 比如层次模型式的工作流,而这在以前的集中式系统中是无法实现的。
常见的版本控制系统介绍
Git
- (读音为 /gIt/)是一个开源的分布式版本控制系统,可以有效、高速地处理从很小到非常大的项目版本管理。
- 也是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。
-
没有中央服务器,每个人的电脑就是一个完整的版本库,工作的时候不需要联网了,因为版本都在自己电脑上。
协同的方法
- 比如自己在电脑上改了文件 A,其他人也在电脑上改了文件 A,这时,你们两之间只需把各自的修改推送给对方,就可以互相看到对方的修改了。
- Git 可以直接看到更新了哪些代码和文件!
优势
- 每个人都拥有全部的代码,可以避免一些安全隐患。
- 不会因为服务器损坏或者网络问题,造成不能工作的情况。
- 所有版本信息仓库全部同步到本地的每个用户,这样就可以在本地查看所有版本历史,可以离线在本地提交,只需在连网时 push 到相应的服务器或其他用户那里。
GitHub
- 是一个面向开源及私有软件项目的托管平台,因为只支持 Git 作为唯一的版本库格式进行托管,故名 GitHub。
- 可以提供给用户空间创建 Git 仓储,保存用户的一些数据文档或者代码等。
- 作为开源代码库以及版本控制系统,目前拥有 140 多万开发者用户。
- 随着越来越多的应用程序转移到了云上,GitHub 已经成为了管理软件开发以及发现已有代码的首选方法。
- 可以托管各种Git 库,并提供一个 web 界面,但与其它像 SourceForge 或 Google code 这样的服务不同
独特卖点
- 在于从另外一个项目进行分支的简易性。
GitLab
- 是一个基于 Git 的项目管理软件,用于仓库管理系统的开源项目。
- 使用 Git 作为代码管理工具,并在此基础上搭建起来 web 服务。
Git、Gitlab、Github 都是基于 Git 的,可以说是 Git 的衍生品。
- 是一款自由和免费的开源软件,因此不需要编写许可证或购买许可证。
- 它允许开发者将源代码托管到自有服务器或者像 Gitlab.com 这样的云端服务器上。
- 这个免费的模式非常适合中小型企业开发者,可以获得许多强大的功能
- 如代码分枝、分支合并、查看历史变更等者
- 非常易于使用和管理。
- 它提供了一个友好的 web 界面,可以让开发者在浏览器中完成 Git 的核心操作
- 它为用户提供了许多简单易用的功能
- 如 API、集成、安全,以及其他一些其他的托管服务功能。
- 管理界面也很直观,可以方便的管理用户权限和代码基础设施的其他方面。
其它版本控制系统
工具还有很多
- Concurrent Versions system(csV)
- subversion(SVN)
- Vesta
- Revision control system(Rcs)
- Source code control system(sccs)
比较常用的两个工具
- CVS
- SVN
CVS
- 是 Dick Grune 在 1984年~1985 年基于 RCS 开发的一个客户一服务器架构的版本控制软件,长久以来一直是免费版本控制软件的主要选择。
SVN
- 一个重要开发目标是修正 CVS 中广为人知的缺点,提供一个新的版本控制软件。
- 对于中小规模团队,SVN 是一个比较好的开源版本控制工具
- SVN 常用客户端工具为 TortoisesVN
Git 的工作原理
Git 的核心概念
- 是一个分布式版本控制系统
核心是三个概念
- Git 对象
- Git 树
- 提交(快照)历史链
Git 原理的核心可以概括为以下几点
Git 对象
- Git 中的所有数据都存储在 Git对象中。
- 每个 Git 对象都由一个 SHA-1 校验和作为唯一的标识符,可以是文件内容、目录结构或者版本历史等。
Git 树
- 由 Git 对象组成的一个目录结构,保存了文件夹、文件和子树的信息,每个树对象都包含一个或多个子对象的引用。
提交历史链
- 每个提交对象都可以有一个或多个父对象,形成一个提交历史链。
- 通过提交历史链,Git 可以跟踪每个文件的修改历史,也可以方便地进行版本回滚、分支合并等操作。
Git 分支
- 是指向 Git 仓库中某一次提交的一个指针,也就是一个指向 Git 提交历史的引用。
- 每个分支都包含了 Git 仓库中的一个提交对象,这个提交对象指向了你项目的一个特定状态。
Git 工作区
- 工作区是文件的实际工作目录,是你在电脑上看到的目录。
- 在执行 “git add” 命令前,工作区的文件修改和添加不会被 Git 跟踪。
Git 暂存区
- 是一个临时的存储区域,用于存储将要提交的文件和修改。
- 在执行 “git add” 命令时,修改的文件会被保存到暂存区中。
Git 远程仓库
- 是指存储在远程服务器上的 Git 仓库,用于多人协作开发、备份和共享代码。
- Git 支持多种协议,如 HTTPS、SSH 等,可以通过、git remote、命令管理远程仓库。
Git 的强大之处在于它的分布式特性和提交历史链的设计,使得团队协作和代码管理更加方便和高效
git 的存储
Git 的工作流程可以简单概括为
- 将工作目录(working directory)的修改提交到暂存区(stagingarea),再将暂存区的修改提交到本地仓库(local repository),最后将本地仓库的修改推送到远程仓库(remote repository)
Git 中对象分为三种类型
- blob
- tree
- commit
blob 对象
- 表示文件内容;
tree 对象
- 表示文件夹或目录结构;
commit 对象
- 表示一个提交或快照
- 包含作者、时间戳、提交信息等版本信息。
git add 添加文件到暂存区,并且创建数据对象添加到 tree 对象中且记录到 git 数据库
git commit 然后把以上的 tree 对象添加到 commit 对象中记录到 git 数据库中。
其它相关概念
Git 的标签(Tag)管理
- Git 支持标签管理,可以给代码库中的某个版本打上标签,方便以后查找和回滚到指定版本。
Git 的远程仓库管理
- Git 可以将本地仓库推送到远程仓库进行备份或共享。
- 常用的远程仓库有 GitHub、GitLab、Bitbucket 等,Git 支持多种协议进行远程仓库之间的数据传输,如 HTTPS、SSH 等。
Git 的钩子(Hook)
- Git 的钩子是一种脚本,可以在 Git 命令执行前或执行后自动触发,用于实现自定义的功能。
- 支持多种钩子,如提交钩子、合并钩子等。
Git 的子模块(submodule)
- 是一种管理外部代码库的方式,可以将外部代码库嵌入到主代码库中,方便管理和维护。
Git的工作流(Workflow)
- Git 支持多种工作流,如集中式工作流、功能分支工作流、Gitflow 工作流等,可以根据项目需求选择不同的工作流进行代码管理和版本控制。
部署 Git 服务器
系统环境准备
主机 | 主机名 | 主机名/IP地址 | 软件包 | 备注 |
服务器 | git | master:192.168.10.105 | Git | 内存4G |
客户端 | client | client:192.168.10.101 | Git |
修改主机名
主机一
[root@localhost ~]# hostnamectl set-hostname client
[root@localhost ~]# bash
主机二
[root@localhost ~]# hostnamectl set-hostname git
[root@localhost ~]# bash
开启会话同步
关闭防火墙、内核机制和网络管理器
[root@git ~]# systemctl stop firewalld
[root@git ~]# systemctl disable firewalld
[root@git ~]# systemctl stop NetworkManager
[root@git ~]# systemctl disable NetworkManager
[root@git ~]# setenforce 0
[root@git ~]# vim /etc/sysconfig/selinux
##修改为
SELINUX=disabled
使用 YUM 安装 Git
主机一
[root@git ~]# yum -y install git
主机二
[root@client ~]# yum -y install git
- 无论是代码仓库,还是开发者的计算机,都需要安装
关闭会话同步
Git 的常用操作
git 有六个常用命令
- 第一次初始化
- 初始化仓库
- 加到缓存区
- 提交至本地仓库
- 推送本地仓库信息至远程仓库
- 拉取远程仓库最新文件
服务器端基本设置
创建仓库目录
[root@git ~]# mkdir /opt/linuxprobe.git
进入目录
[root@git ~]# cd /opt/linuxprobe.git
在服务器端初始化 Git 仓库
[root@git linuxprobe.git]# git --bare init
初始化空的 Git 版本库于 /opt/linuxprobe.git/
- 本案例中,要将该服务器初始化为远程仓库,提供给其他开发人员用来提交项目,在初始化的时候,需要加上--bare 的选项。
- git init:建立一个标准的 git 仓库,它将我们所在的目录转换为一个 Git 本地仓库。
- 建立一个标准的 Git 仓库,这样的仓库初始化后,其项目目录为工作空间,其下的.git 目录是版本控制器。git init 命令执行后会在本地生成一个·git 的文件夹,用来追踪仓库的所有变更。
- git init --bare:它将我们所在的目录指定为远程服务器仓库。
- 这样的仓库初始化后,其项目目录下就是标准仓库 .git 目录里的内容,没有工作空间。这个仓库只保存 git 历史提交的版本信息,而不允许用户在上面进行各种 git 操作()(如:push、commit 操作)。但是,依旧可以使用 git show 命令查看提交内容。
客户端基本信息设置
在客户端设置 ssh 密钥对
- 有了 ssh 免密后,客户端向 git 仓库推送代码时,就不需要输入用户密码
[root@client ~]# ssh-keygen
用 IP 远程连接拷贝
[root@client ~]# ssh-copy-id 192.168.10.105
从 Git 服务器中克隆版本仓库到客户端本地
[root@client ~]# git clone root@192.168.10.105:/opt/linuxprobe.git
正在克隆 'linuxprobe'...
warning: 您似乎克隆了一个空版本库。
- 此时会在当前目录下生成一个名为 “linuxprobe” 的空目录,这个步骤的目的是将服务器端的项目(空项目)克隆到本地,这样就在本地建立了一个代码库,开发者就可以基于此代码库进行程序开发。
- 之后就可以将代码从本地提交到远程的代码库了。
进入目录
[root@client ~]# cd linuxprobe/
客户端配置用户信息
[root@client linuxprobe]# git config --global user.name "zhangsan"
[root@client linuxprobe]# git config --global user.email "zhangsan@linuxprobe.com"
设置 vim 为默认的文本编辑器
- 当 git 需要输入消息的时候会调用这个编辑器,如果没有设置,将使用系统默认的编辑器。
[root@client linuxprobe]# git config --global core.editor vim
查看 Git 工作环境信息
[root@client linuxprobe]# git config --list
user.name=zhangsan
user.email=zhangsan@linuxprobe.com
core.editor=vim
core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true
remote.origin.url=root@192.168.10.105:/opt/linuxprobe.git
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
branch.master.remote=origin
branch.master.merge=refs/heads/master
代码提交操作
在客户端编写代码
[root@client linuxprobe]# echo "Hello World" > readme.txt
将文件添加到暂存区
[root@client linuxprobe]# git add readme.txt
- “git add.” 命令可以将当前目录中的所有文件添加到暂存区。
将暂存区内容添加到本地仓库中
[root@client linuxprobe]# git commit -m "my info01"
[master(根提交) 47b8cf6] my info01
1 file changed, 1 insertion(+)
create mode 100644 readme.txt
- -m:m 指的是 message,可以是一些备注信息
- -a:用于先将所有工作区的变动文件,提交到暂存区,再运行 git commit。用了 -a 参数,就不用执行“git add .”
- git commit -m 只是 git add 之后文件放在在暂存区之后的提交,如果暂存区没有 add,是没有效果的。
- git commit -am 是之前提交过到工作区的日志信息已经存在(git commit -m “日志信息” 文件名)已经执行过,再执行同样的日志信息可以不用 add,一步到位。
为当前版本库设置标签
[root@client linuxprobe]# git tag v1.1 -m "mytag01"
查看标签
[root@client linuxprobe]# git show v1.1
tag v1.1
Tagger: zhangsan <zhangsan@linuxprobe.com>
Date: Fri Sep 27 18:04:36 2024 +0800
mytag01
commit 47b8cf612cfbf0c4340c550160c134444ed67fc7
Author: zhangsan <zhangsan@linuxprobe.com>
Date: Fri Sep 27 18:02:22 2024 +0800
my info01
diff --git a/readme.txt b/readme.txt
new file mode 100644
index 0000000..557db03
--- /dev/null
+++ b/readme.txt
@@ -0,0 +1 @@
+Hello World
查看 master
[root@client linuxprobe]# git show master
commit 47b8cf612cfbf0c4340c550160c134444ed67fc7
Author: zhangsan <zhangsan@linuxprobe.com>
Date: Fri Sep 27 18:02:22 2024 +0800
my info01
diff --git a/readme.txt b/readme.txt
new file mode 100644
index 0000000..557db03
--- /dev/null
+++ b/readme.txt
@@ -0,0 +1 @@
+Hello World
- master 分支是当前主分支的最新版本,上一步中为代码版本打过标签后没有再提交过新的代码,所以查看到的是相同的内容。
修改文件内容
[root@client linuxprobe]# echo "Hello kgc" >> readme.txt
将新修订的文件添加到暂存区,并添加到本地仓库
[root@client linuxprobe]# git add readme.txt
[root@client linuxprobe]# git commit -m "my info02"
[master 763ecf5] my info02
1 file changed, 1 insertion(+)
为当前版本库设置标签,并查看标签
[root@client linuxprobe]# git tag v1.2 -m "mytag02"
[root@client linuxprobe]# git show v1.2
tag v1.2
Tagger: zhangsan <zhangsan@linuxprobe.com>
Date: Fri Sep 27 18:07:55 2024 +0800
mytag02
commit 763ecf5288322878308a9298a9ea06b25b3cc44d
Author: zhangsan <zhangsan@linuxprobe.com>
Date: Fri Sep 27 18:07:38 2024 +0800
my info02
diff --git a/readme.txt b/readme.txt
index 557db03..7860215 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1 +1,2 @@
Hello World
+Hello kgc
显示 master
[root@client linuxprobe]# git show master
commit 763ecf5288322878308a9298a9ea06b25b3cc44d
Author: zhangsan <zhangsan@linuxprobe.com>
Date: Fri Sep 27 18:07:38 2024 +0800
my info02
diff --git a/readme.txt b/readme.txt
index 557db03..7860215 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1 +1,2 @@
Hello World
+Hello kgc
查看当前工作目录的状态
[root@client linuxprobe]# git status
# 位于分支 master
无文件要提交,干净的工作区
- 表示项目已经全部提交,当前没有可提交的项目
查看当前文件内容与 Git 版本数据库中的差别
[root@client linuxprobe]# git diff -b v1.1 readme.txt
diff --git a/readme.txt b/readme.txt
index 557db03..7860215 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1 +1,2 @@
Hello World
+Hello kgc
添加远程版本库
[root@client linuxprobe]# git remote add gitserver root@192.168.10.105:/opt/linuxprobe.git
- 在克隆了一个远程仓库到本地的时候,已经在本地自动添加了名称为 origin 的远程仓库,如果想设置其他的仓库名称,可以使用 git remote add 的命令进行添加。
如果要删除一个远程仓库,可以使用命令
- git remote remove gitserver
上传代码
- 上传主分支当前版本
[root@client linuxprobe]# git push -u gitserver master
Counting objects: 6, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (6/6), 452 bytes | 0 bytes/s, done.
Total 6 (delta 0), reused 0 (delta 0)
To root@192.168.10.105:/opt/linuxprobe.git
* [new branch] master -> master
分支 master 设置为跟踪来自 gitserver 的远程分支 master。
上传主分支的 v1.1 版本
[root@client linuxprobe]# git push -u gitserver v1.1
Counting objects: 1, done.
Writing objects: 100% (1/1), 157 bytes | 0 bytes/s, done.
Total 1 (delta 0), reused 0 (delta 0)
To root@192.168.10.105:/opt/linuxprobe.git
* [new tag] v1.1 -> v1.1
上传主分支的 v1.2 版本
[root@client linuxprobe]# git push -u gitserver v1.2
Counting objects: 1, done.
Writing objects: 100% (1/1), 158 bytes | 0 bytes/s, done.
Total 1 (delta 0), reused 0 (delta 0)
To root@192.168.10.105:/opt/linuxprobe.git
* [new tag] v1.2 -> v1.2
- -u 参数其实就相当于记录了 push 到远端分支的默认值,这样当下次我们还想要继续 push 的这个远端分支的时候推送命令就可以简写成 git push 即可
创建目录
[root@client linuxprobe]# mkdir /opt/test
进入目录
[root@client linuxprobe]# cd /opt/test/
克隆代码
- 为了验证文件是否推送到远程的 Git 服务,可以换个目录(或主机)再次克隆一份版本仓库
[root@client test]# git clone root@192.168.10.105:/opt/linuxprobe.git
正克隆到 'linuxprobe'...
remote: Counting objects: 8, done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 8 (delta 0), reused 0 (delta 0)
接收对象中: 100% (8/8), done.
切换目录
[root@client test]# cd /opt/test/linuxprobe/
查看文本
[root@client linuxprobe]# cat readme.txt
Hello World
Hello kgc
- 指定标签下载对应的版本
- 不指定版本默认下载的最新的版本
- git clone -b v1.1 root@192.168.10.105:/opt/linuxprobe.git
- git clone -b v1.2 root@192.168.10.105:/opt/linuxprobe.git
- git clone -b master root@192.168.10.105:/opt/linuxprobe.git
- -b:指定分支名称
- v1.1 是上一个版本,read.txt 中的内容是 aaa
- v1.2 是当前的最新版本,read.txt 中的内容是 aaa、bbb
- -b master 的参数可以省去,默认就是克隆 master 分支的当前版本
至此,我们就完成了一个完整的项目流程,包含远程代码仓库的创建与初始化,并且站在开发者的角度克隆项目、开发代码并提交项目代码。
部署 GitLab 服务器
系统环境准备
主机 | 主机名 | 主机名/IP地址 | 软件包 | 备注 |
服务器 | gitlab | master:192.168.10.105 | Gitlab | 内存4G |
客户端 | client | client:192.168.10.101 | Git |
修改主机名
主机一
[root@localhost ~]# hostnamectl set-hostname client
[root@localhost ~]# bash
主机二
[root@localhost ~]# hostnamectl set-hostname gitlab
[root@localhost ~]# bash
开启会话同步
关闭防火墙、内核机制和网络管理器
[root@gitlab ~]# systemctl stop firewalld
[root@gitlab ~]# systemctl disable firewalld
[root@gitlab ~]# setenforce 0
[root@gitlab ~]# systemctl stop NetworkManager
[root@gitlab ~]# systemctl disable NetworkManager
[root@gitlab ~]# vim /etc/sysconfig/selinux
##修改为
SELINUX=disabled
[root@client ~]# systemctl stop firewalld
[root@client ~]# systemctl disable firewalld
[root@client ~]# setenforce 0
[root@client ~]# systemctl stop NetworkManager
[root@client ~]# systemctl disable NetworkManager
[root@client ~]# vim /etc/sysconfig/selinux
##修改为
SELINUX=disabled
关闭会话同步
安装 GItLab
下载依赖包
[root@gitlab ~]# yum -y install policycoreutils-python
将所需的 GitLab 安装包通过 Xftp 上传到服务器端(105)
使用 rpm 进行安装
[root@gitlab ~]# rpm -ivh gitlab-ce-15.5.1-ce.0.el7.x86_64.rpm
修改配置文件
- 修改仓库 URL 的显示地址
[root@gitlab ~]# vim /etc/gitlab/gitlab.rb
##32行
##修改为
external_url 'http://192.168.10.105'
- 本案例没有修改端口,直接用了 80端口,注意不要有冲突。
- 如果不修改,在克隆项目的时候,给出的仓库链接使用的是 gitlab.example.com,在局域网中使用起来不方便,还要修改成 gitlab 的 ip 地址。修改后就直接是 gitlab 的 ip 地址了。
加载配置文件并启动
(前提是 80 端口没有被占用)
[root@gitlab ~]# gitlab-ctl reconfigure
下载 lsof
[root@gitlab ~]# yum -y install lsof
查看端口
[root@gitlab ~]# lsof -i:80
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
nginx 3058 root 7u IPv4 20579 0t0 TCP *:http (LISTEN)
nginx 3059 gitlab-www 7u IPv4 20579 0t0 TCP *:http (LISTEN)
nginx 3060 gitlab-www 7u IPv4 20579 0t0 TCP *:http (LISTEN)
- 重启:gitlab-ctl restart
- 关闭:gitlab-ctl stop
- 启动:gitlab-ctl start
- 状态:gitlab-ctl status
- 帮助:gitlab-ctl --help
在浏览器中输入 http://服务器 IP 地址,服务 GitLab
默认账号:root
默认密码:
- cat /etc/gitlab/initial_root_password
修改 root 登录密码
- 点击右上角用户头像,在下拉菜单中点 Preferences,在左侧列表中找打 password。
- 本案例中使用的 root 密码为 pwd12345,注意密码长度至少8位。
- 在此处做一个快照
GitLab 创建空项目
- 点击 “Create project” 按钮,创建新项目 kgc-demo
填写项目参数,并点击创建按钮
下载 git
[root@client ~]# yum -y install git
如果不下载 git,克隆项目就会提示报错
- bash: git: 未找到命令
在客户机克隆空项目
[root@client ~]# git clone http://192.168.10.105/root/kgc-demo.git
正克隆到 'kgc-demo'...
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), done.
切换目录
[root@client ~]# cd kgc-demo/
为客户端设置 GitLab 为远程仓库
[root@client kgc-demo]# git remote add origin01 http://192.168.10.105:/root/kgc-demo.git
为客户端创建本地代码
[root@client kgc-demo]# echo "test web">index.html
初始化
[root@client kgc-demo]# git init
重新初始化现存的 Git 版本库于 /root/kgc-demo/.git/
提交至暂存区
[root@client kgc-demo]# git add .
从暂存区提交到本地仓库
[root@client kgc-demo]# git commit -m“my info'
[main 6d518b1] my info
1 file changed, 1 insertion(+)
create mode 100644 index.html
为分支命名为 main
[root@client kgc-demo]# git branch -M main
推送代码
[root@client kgc-demo]# git push -u origin01 main
Username for 'http://192.168.10.105:': root
Password for 'http://root@192.168.10.105:':
分支 main 设置为跟踪来自 origin01 的远程分支 main。
Everything up-to-date
- 此处需要输入账号密码,是 GitLab 的登录账号密码
- -u:相当于记录了 push 到远端分支的默认值,这样当下次我们还想要继续 push 的这个远端分支的时候推送命令就可以简写成 git push 即可
- -f:强制更新,需要 gitlab 权限允许。
gitlab 设置权限,允许强制更新
- 添加用户权限,去掉保护分支,这样能让用户提交强制的操作。
- 项目目录 --> 左侧栏 --> settings --> Repository,右侧目录栏找到 Protected Branches。
- 然后启用 “Allowed to force push”
创建新用户
添加组
- 点 “main menu” --> “Admin”
点 “Group” --> “New group”,添加新的项目组
填写组信息,并创建组
添加用户
- 点 “Users” --> “New user”,创建新的用户
设置用户信息并创建
- 填写如下信息,并点击 create user 按钮创建此账户
access level:用户地访问级别。
- Regular:普通用户,只能访问属于他自己的组和项目
- Admin:管理员,可以访问所有的组合项目
设置用户密码
- 点击 “Edit ”进入修改密码界面。
- 填写密码并保存,注意密码需要至少8位字符。(此处设置为 pwd12345)
将用户加入组
- 点 “main menu” --> “Groups”,进入组界面
添加成员
- 鼠标放在 “Group information” 选项,向后选 “Members”,点 “Invite members” 添加成员。
在下图界面填写用户名,并选择一个角色
Gitlab 用户在组里面有5 种不同权限
- Guest:可以创建 issue、发表评论,不能读写版本库。
- Reporter:可以克隆代码,不能提交,QA、PM可以赋子这个权限。
- Developer:可以克隆代码、开发、提交、push,普通开发可以赋予这个权限。
- Maintainer:可以创建项目、添加 tag、保护分支、添加项目成员、编辑项目,核心开发可以赋
- 予这个权限。
- Owner:可以设置项目访问权限 -Visibility Level、删除项目、迁移项目、管理组成员,开发组组长可以赋予这个权限。
在用户组中创建项目
用 zhangsan 用户的身份重新登录 GitLab
- 第一次使用新用户登录,需要重新设置密码,此处还设置为 pwd12345
在主面板页面点击 “create a project”,添加项目
导入一个项目
- 此次我们用导入的方式,导入一个现成的项目。
点击 “Repository by URL” 按钮添加项目
添加仓库的 URL
此处,我们选择一个 gitee 上的开源项目 mall,其连接如下
https://gitee.com/kgc-wjq/league.git
- 此处设置的访问级别为 Private,在客户端进行克隆的时候,就需要输入 zhangsan 的账号密码进行身份认证后才能克隆下来。
- 如果选择Public,在克隆的时候就不需要身份验证了。
验证导入结果
在客户端克隆
[root@client kgc-demo]# git clone http://192.168.10.105/zhangsan/league.git
正克隆到 'league'...
Username for 'http://192.168.10.105':zhangsan
Password for 'http://zhangsan@192.168.10.105':
remote:Enumerating objects: 41, done.
remote:counting objects: 100% (41/41),done.
remote:compressing objects: 100% (35/35),done.
remote: Total 41 (delta 4),reused 41 (delta 4), pack-reused 0
Unpacking objects: 100% (41/41),done.
Git 分支管理
分支概述
什么是分支
- 分支就是科幻电影里面的平行宇宙,当你正在电脑前努力学习++的时候,另一个你正在另一个平行宇宙里努力学习 JAVA。
- 如果两个平行宇宙互不干扰,那对现在的你也没啥影响。
- 不过,在某个时间点,两个平行宇宙合并了,结果:你既学会了C++又学会了 JAVA!
- 版本库中是有一个 HEAD 指针,它指向了一个 master 分支。
- master 里面存储的就是我们的最新的一次提交,而最新的一次提交对应的就是 commit id,对应的是对象库中的一个对象的索引,我们可以使用 log 命令进行査看。
main 分支(master 分支)
- 版本回退里,每次提交,Git 都把它们串成一条时间线,这条时间线就可以理解为是一个分支。
- 截止到目前,只有一条时间线,在 Git 里,这个分支叫主分支,即 master 分支。
再来理解一下 HEAD
- HEAD 严格来说不是指向提交,而是指向 master,master 才是指向提交的,所以,HEAD 指向的就是当前分支。
- 每次提交,master 分支都会向前移动一步,这样随着我们不断提交,master 分支的线也越来越长,而 HEAD 只要一直指向 master 分支即可指向当前分支。
创建代码仓库
创建一个空项目
- 在 gitlab 上创建一个名为 mypro 的空项目
创建测试文件
- 删除文件 “README.md”,并在该项目中添加文本 readme.txt
客户端克隆项目
将项目克隆到本地
[root@client ~]# git clone http://192.168.10.105/root/mypro.git
进入目录
[root@client ~]# cd mypro/
查看文本内容
[root@localhost mypro]# cat readme.txt
This is my first project
设置用户信息
[root@client ~]# git config --global user.name "zhangsan"
[root@client ~]# git config --global user.email "zhangsan@mypro.com"
[root@client ~]# git config --global core.editor vim
[root@client ~]# git remote add gitserver http://192.168.10.105/root/mypro.git
列出用户信息
[root@client ~]# git config --list
user.name=zhangsan
user.email=zhangsan@mypro.com
core.editor=vim
core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true
remote.origin.url=http://192.168.10.105/root/mypro.git
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
branch.main.remote=origin
branch.main.merge=refs/heads/main
remote.gitserver.url=http://192.168.10.105/root/mypro.git
remote.gitserver.fetch=+refs/heads/*:refs/remotes/gitserver/*
提交 main 分支
定义一个文本
[root@client mypro]# echo "master-pro-01" >> readme.txt
添加文本
[root@client mypro]# git add readme.txt
客户端提交 main 分支的第一次代码
[root@client mypro]# git commit -m "master-01"
[main 05e471a] master-01
1 file changed, 1 insertion(+)
查看当前分支信息
[root@client mypro]# git branch
* main
- 其实创建本地仓库的时候,git 会为我们自动创建出来一个 main 主分支,所以此处只有一个 main 分支,而前面有一个 * 号,就是因为 main 前面存在一个 HEAD 指针。
- HEAD 是不止可以指向 main 分支,还可以指向其他的任意分支的,而被 HEAD 指向的分支其实才是当前的工作分支。
- 所以 main 前面有一个 * 号,其实是因为当前我们正在 main 上工作。
提交 main 分支到 gitlab
[root@client mypro]# git push -u gitserver main
Username for 'http://192.168.10.105': root
Password for 'http://root@192.168.10.105':
Counting objects:5,done.
Writing objects:100%(3/3),279 bytes0 bytes/s, done.
Total 3(delta 0),reused 0(delta 0)
To http://192.168.10.105/root/mypro.git
965f9a4..0e873c0 main->main
分支 main 设置为跟踪来自 gitserver 的远程分支 main。
gitlab 查看提交信息
创建分支
创建本地分支
[root@client mypro]# git branch dev
[root@client mypro]# git branch
dev
* main
- 通过 * 号我们可以知道,HEAD 指针还是指向 master 分支的
查看验证
[root@client mypro]# cat .git/HEAD
ref: refs/heads/main
下载树
[root@client mypro]# yum -y install tree
查看 .git 的目录树结构
[root@client mypro]# tree .git/refs/
.git/refs/
├── heads
│ ├── dev
│ └── main
├── remotes
│ └── origin
│ └──HEAD
└── tags
4 directories, 3 files
查看当前的 commit id
- 其里面也是一个 commit id ,并且其里面放的内容与 master 里面放的内容是一摸一样的,指向的是最新的一次提交。
- 原因就是因为:我们创建 dev 分支的时候,是基于最新的一次的提交创建出来的,即我们在 git branch dev 的时候是站在当前最新的一个版本上去创建的。
[root@client mypro]# cat .git/refs/heads/dev
ff5eadf47f4ae98cea92612168257e4a67058d40
[root@client mypro]# cat .git/refs/heads/main
ff5eadf47f4ae98cea92612168257e4a67058d40
切换分支
切换到 dev 分支
- 如果想在对应的分支下进行操作,即切换到 dev 分支下进行开发,使用 git checkout 命令即可完成切换。
[root@client mypro]# git checkout dev
A readme.txt
切换到分支 'dev'
查看当前分支
[root@client mypro]# git branch
* dev
main
添加代码
- 我们发现 HEAD 已经指向了 dev,就表示我们已经成功的切换到了 dev 上了。
- 在 dev 分支 下修改 ReadMe 文件,新增一行内容,并进行一次提交操作。
定义文本
[root@client mypro]# echo "dev-branch01">>readme.txt
查看文本内容
[root@client mypro]# cat readme.txt
This is my first project
master-pro-01
dev-branch01
添加文本
[root@client mypro]# git add readme.txt
提交到暂存区
[root@client mypro]# git commit -m "dev-branch01"
[dev-cla9906] dev-branch01
1 file changed, 1 insertion(+)
提交到 gitlab
[root@client mypro]# git push -u gitserver dev
Username for 'http://192.168.10.105':root
Password for 'http://root@192.168.10.105':
Counting objects:5,done.
Compressing objects:100%(2/2),done.
Writing objects:100%(3/3),293 bytes|0 bytes/s, done.
Total 3(delta 1),reused 0(delta 0)
remote:
remote: To create a merge request for dev, visit:
remote:
http://gitlab.example.com/root/mypro/-/merge _requests/new?merge _request%5Bsource_branch%5D=dev
remote:
To http://192.168.10.105/root/mypro.git
* [new branch] dev ->dev
分支 dev 设置为跟踪来自 gitserver 的远程分支 dev。
gitlab 查看提交的 dev 分支的结果
- 将代码提交到 gitlab 后,在 gitlab 中会发现多了一个分支 dev。
gitlab 查看 main 分支信息
也可以用命令再切回 master 分支,进行查看我们在dev分支下进行修改并提交
的 readme.txt 文件
[root@client mypro]# git checkout main
A readme.txt
切换到分支 'main'
[root@client mypro]# git branch
dev
* main
[root@client mypro]# cat readme.txt
This is my first project
master-pro-01
dev-branch01
- 可以发现在 dev上的修改并没有在 master 上体现出来。
- 并且这个时候我们再打印 dev 里面的内容,可以发现发生了改变。
- 并且对应的分支 ID 也和原来的不同了
[root@client mypro]# cat .git/refs/heads/dev
ff5eadf47f4ae98cea92612168257e4a67058d40
[root@client mypro]# git cat-file -p ff5eadf47f4ae98cea92612168257e4a67058d40
tree e97946f45dcdd86b2cc4b07b4c67d47b9ee5934b
parent 0e873c0d51aace883c74a3252cc14932c42c76e7
author Administrator <admin@example.com> 1727504320 +0000
committer Administrator <admin@example.com> 1727504320 +0000
dev-branch01
- 可以发现,是创建完 dev 分支的时候里面保存的内容。
- 也就是说我们在 dev 分支上,实现了一次的提交。
- 所以,当切换到 master 分支之时,HEAD 就指向了 master,当然看不到 dev 的提交的代码了。
合并分支
- 为了在 master 主分支上能看到新的提交,就需要将 dev 分支合并到 master 分支,合并后,master 就能看到 dev 分文提交的内容了,首先如果是想让 master 分支来合并 dev 分支,必须要先切到 master 分支上。
切换到 main 分支
[root@client mypro]# git branch
dev
* main
将 dev 分支合并给 main 分支
[root@client mypro]# git merge dev
更新 0e873c0..c1a9906
Fast-forward
readme.txt 1 +
1 file changed, 1 insertion(+)
- Fast-forward 代表 “快进模式”,也就是直接把 master 指向 dev 的当前提交,所以合并速度
- 非常快。
将合并后的 main 分支提交到 gitlab
[root@client mypro]# git push -u gitserver main
Username for 'http://192.168.10.105':root
Password for 'http://root@192.168.10.105':
fatal: Authentication failed for 'http://192.168.10.105/root/mypro.git/'
[root@localhost mypro]# git push -u gitserver main
Username for 'http://192.168.10.105': root
Password for 'http://root@192.168.10.105':
Total 0(delta 0),reused 0(delta 0)
To http://192.168.10.105/root/mypro.git
0e873c0..c1a9906 main->main
分支 main 设置为跟踪来自 gitserver 的远程分支 main。
查看 gitlab 中的 main 分支的代码
也可以在命令行査看 readme.txt 文件,可以发现 master 分支下的文件确实发生了改变。
并且 master 中存的 commit id 也变为了 dev 中的最新提交。
[root@client mypro]# cat readme.txt
master-pro-01
dev-branch01
[root@client mypro]# cat .git/refs/heads/main
ff5eadf47f4ae98cea92612168257e4a67058d40
[root@client mypro]# cat .git/refs/heads/dev
ff5eadf47f4ae98cea92612168257e4a67058d40
删除分支
- 合并完成后,dev 分支对于我们来说就没用了,因为 dev 分支所需要达到的目标已经做到了,并且已经将结果交付给了 master 主分支,那么 dev 分支就需要被删除掉(荒废的分支会占用一定的资源,并且不利于管理)。
- 如果当前正处于某分支下,就不能删除当前分支。
- 所以要想删除 dev 分支,必须切换到其他分支。
查看当前分支
[root@client mypro]# git branch
dev
* main
删除分支
- 删除本地分支和删除远程分支不是同一回事。
- 两种删除不会相互影响
[root@client mypro]# git branch -d dev
已删除分支 dev(曾为 ff5eadf)。
[root@client mypro]# git branch
* main
删除远程 gitlab 上的 dev 分支
[root@client mypro]# git push gitserver --delete dev
Username for 'http://192.168.10.105': root
Password for 'http://root@192.168.10.105':
To http://192.168.10.105/root/mypro.git
- [deleted] dev
gitlab 上查看分支,发现 dev 分支已经不存在
小阿轩yx-案例:代码管理系统简介与部署