版本控制是指对软件开发过程中各种程序代码、配置文件及说明文档等文件变更的管理,是软件配置管理的核心思想之一。

版本控制最主要的功能就是追踪文件的变更。它将什么时候、什么人更改了文件的什么内容等信息忠实地了记录下来。每一次文件的改变,文件的版本号都将增加。除了记录版本变更外,版本控制的另一个重要功能是并行开发。软件开发往往是多人协同作业,版本控制可以有效地解决版本的同步以及不同开发者之间的开发通信问题,提高协同开发的效率。并行开发中最常见的不同版本软件的错误(Bug)修正问题也可以通过版本控制中分支与合并的方法有效地解决。
具体来说,在每一项开发任务中,都需要首先设定开发基线,确定各个配置项的开发初始版本,在开发过程中,开发人员基于开发基线的版本,开发出所需的目标版本。当发生需求变更时,通过对变更的评估,确定变更的影响范围,对被影响的配置项的版本进行修改,根据变更的性质使配置项的版本树继续延伸或产生新的分支,形成新的目标版本,而对于不受变更影响的配置项则不应发产生变动。同时,应能够将变更所产生的对版本的影响进行记录和跟踪。必要时还可以回退到以前的版本。例如当开发需求或需求变更被取消时,就需要有能力将版本回退到开发基线版本。在曾经出现过的季度升级包拆包和重新组包的过程中,其实就是将部分配置项的版本回退到开发基线,将对应不同需求的不同分支重新组合归并,形成新的升级包版本。
版本控制是软件配置管理的核心功能。所有置于配置库中的元素都应自动予以版本的标识,并保证版本命名的唯一性。版本在生成过程中,自动依照设定的使用模型自动分支、演进。除了系统自动记录的版本信息以外,为了配合软件开发流程的各个阶段。还需要定义、收集一些元数据来记录版本的辅助信息和规范开发流程,并为今后对软件过程的度量做好准备。当然如果选用的工具支持,这些辅助数据将能直接统计出过程数据,从而方便软件过程改进活动的进行。对于配置库中的各个基线控制项,应该根据其基线的位置和状态来设置相应的访问权限。一般来说,对于基线版本之前的各个版本都应处于被锁定的状态,如需要对它们进行变更,则应按照变更控制的流程来进行操作。

常用的版本控制工具:

  • gitlab
  • subversion

gitlab部署

//安装git
[root@localhost ~]# yum -y install epel-release git
安装过程略

//安装依赖包
[root@localhost ~]# yum -y install curl openssh-server openssh-clients postfix cronie  perl perl-devel autoconf libaio

[root@localhost ~]# wget  http://mirror.centos.org/centos/7/os/x86_64/Packages/policycoreutils-python-2.5-34.el7.x86_64.rpm
[root@localhost ~]# rpm -qa |grep policy
policycoreutils-2.9-19.el8.x86_64
selinux-policy-3.14.3-99.el8.noarch
selinux-policy-targeted-3.14.3-99.el8.noarch
[root@localhost ~]# rpm -e policycoreutils --nodeps 
[root@localhost ~]# rpm -qa |grep policy
selinux-policy-3.14.3-99.el8.noarch
selinux-policy-targeted-3.14.3-99.el8.noarch
[root@localhost ~]# rpm -ivh --nodeps policycoreutils-python-2.5-34.el7.x86_64.rpm 
warning: policycoreutils-python-2.5-34.el7.x86_64.rpm: Header V3 RSA/SHA256 Signature, key ID f4a80eb5: NOKEY
Verifying...                          ################################# [100%]
Preparing...                          ################################# [100%]
Updating / installing...
   1:policycoreutils-python-2.5-34.el7################################# [100%]


//启动postfix服务并设置开机自启
[root@localhost ~]# systemctl restart postfix
[root@localhost ~]# systemctl enable postfix

//下载gitlab的rpm包
[root@localhost ~]# cd /usr/src/
[root@localhost src]# wget https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/gitlab-ce-15.3.3-ce.0.el7.x86_64.rpm
[root@localhost src]# rpm -ivh gitlab-ce-15.3.3-ce.0.el7.x86_64.rpm 
warning: gitlab-ce-15.3.3-ce.0.el7.x86_64.rpm: Header V4 RSA/SHA1 Signature, key ID f27eab47: NOKEY
Verifying...                          ################################# [100%]
Preparing...                          ################################# [100%]
Updating / installing...
   1:gitlab-ce-15.3.3-ce.0.el7        ################################# [100%]
It looks like GitLab has not been configured yet; skipping the upgrade script.

       *.                  *.
      ***                 ***
     *****               *****
    .******             *******
    ********            ********
   ,,,,,,,,,***********,,,,,,,,,
  ,,,,,,,,,,,*********,,,,,,,,,,,
  .,,,,,,,,,,,*******,,,,,,,,,,,,
      ,,,,,,,,,*****,,,,,,,,,.
         ,,,,,,,****,,,,,,
            .,,,***,,,,
                ,*,.
  


     _______ __  __          __
    / ____(_) /_/ /   ____ _/ /_
   / / __/ / __/ /   / __ `/ __ \
  / /_/ / / /_/ /___/ /_/ / /_/ /
  \____/_/\__/_____/\__,_/_.___/
  

Thank you for installing GitLab!
GitLab was unable to detect a valid hostname for your instance.
Please configure a URL for your GitLab instance by setting `external_url`
configuration in /etc/gitlab/gitlab.rb file.
Then, you can start your GitLab instance by running the following command:
  sudo gitlab-ctl reconfigure

For a comprehensive list of configuration options please see the Omnibus GitLab readme
https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/README.md

Help us improve the installation experience, let us know how we did with a 1 minute survey:
https://gitlab.fra1.qualtrics.com/jfe/form/SV_6kVqZANThUQ1bZb?installation=omnibus&release=15-3

//修改配置文件
[root@localhost ~]# vim /etc/gitlab/gitlab.rb
.....
external_url 'http://192.168.91.139'    //将此处设为gitlab的服务器ip地址亦或域名
.....

//重载配置文件并重启gitlab
[root@localhost ~]# gitlab-ctl reconfigure
[root@localhost ~]# gitlab-ctl restart
ok: run: alertmanager: (pid 121159) 0s
ok: run: gitaly: (pid 121252) 0s
ok: run: gitlab-exporter: (pid 121298) 0s
ok: run: gitlab-kas: (pid 121300) 0s
ok: run: gitlab-workhorse: (pid 121310) 1s
ok: run: logrotate: (pid 121349) 0s
ok: run: nginx: (pid 121359) 0s
ok: run: node-exporter: (pid 121426) 1s
ok: run: postgres-exporter: (pid 121461) 0s
ok: run: postgresql: (pid 121497) 0s
ok: run: prometheus: (pid 121506) 0s
ok: run: puma: (pid 121594) 1s
ok: run: redis: (pid 121626) 0s
ok: run: redis-exporter: (pid 121632) 0s
ok: run: sidekiq: (pid 121754) 0s

//查看当前的gitlab版本
[root@localhost ~]# head -1 /opt/gitlab/version-manifest.txt
gitlab-ce 15.3.3

//破解管理员密码
[root@localhost ~]# gitlab-rails console     //进入控制台
--------------------------------------------------------------------------------
 Ruby:         ruby 2.7.5p203 (2021-11-24 revision f69aeb8314) [x86_64-linux]
 GitLab:       15.3.3 (c629a47f87f) FOSS
 GitLab Shell: 14.10.0
 PostgreSQL:   13.6
------------------------------------------------------------[ booted in 17.10s ]
Loading production environment (Rails 6.1.6.1)
irb(main):001:0> u=User.find(1)              //查询root用户账号信息并赋值给u
=> #<User id:1 @root>
irb(main):002:0> 
irb(main):003:0> u.password='12345678'       //设置密码
=> "12345678"
irb(main):004:0> u.password_confirmation = '12345678'   //确认密码(非必须
=> "12345678" 
irb(main):005:0> u.save!                   //保存设置
=> true
irb(main):006:0> exit                     //退出控制台

gitlab管理

在浏览器中使用gitlab服务器的ip访问,页面如下图所示,用户root密码是刚破解的

image-1663896430602

image-1663896441014

Git命令行操作

3.1 本地库操作

3.1.1 本地库初始化

进入需要创建本地库的目录

	cd 目录名

初始化一个空仓库,会创建一个.git目录,目录中存放的是本地库相关的子目录和文件。

	git init 

3.1.2 设置签名

形式:

用户名:aaa

Email地址:aaa@gmail.com(可以不为真)

作用:区分不同开发人员的身份

此处设置的签名和登陆远程库的账号、密码没有任何关系。

命令:

项目级别/仓库级别:仅在当前本地库范围内有效(优先采用)。

	git config user.name aaa
	
	git config user.email aaa@gmail.com

保存在.git文件夹中config文件

系统用户级别:登录当前操作系统的用户范围。
	
	git config --global user.name aaa
	
	git config --global user.email aaa@gmail.com

保存在当前用户根文件夹中.gitconfig文件,通常设置一个系统用户级别就足够使用

3.1.3 Git提交命令

查看当前暂存区和本地库状态

	git status

提交文件至暂存区

	git add 文件名

从暂存区删除文件

	git rm --cached 文件名

将暂存区文件提交至本地库,需要写入对本次提交的解释。

	git commit -m "对本次提交的解释" 文件名 

以上指令文件名若为 . 则为所有文件
例:git add .			该指令为将当前目录所有文件添加至暂存区

3.1.4 Git版本控制命令

查看git库历史提交日志

git版本切换的原理就是将版本对应的指针指向不同的版本

查看提交日志,通过日志提供信息可以控制代码版本,可以附加--pretty=oneline一行显示。

可以缩写成--oneline,对应的哈希值会变为缩写。

	git log
	
	git log --pretty=oneline

	git log --oneline
	
若是多屏显示,可以通过 空格向下翻页,b 向上翻页,q 退出

git reflog 也是查看提交日志,会显示切换版本所需要移动的指针位置

git版本前进后退方式

1. 基于索引值操作[推荐]

   git reset --hard 索引值(哈希值,缩写也可以)

2. 使用^符号 (只能后退)

   git reset --hard HEAD^ 回退一次

   git reset --hard HEAD^^ 回退两次

3. 使用~符号(只能后退)
	
   git reset --hard HEAD~1 回退一次

   git reset --hard HEAD~2 回退两次

reset命令的三个参数对比

--soft

  不会碰暂存区与工作区,只会移动本地库指针

--mixed

  会在本地库移动指针,并且重置暂存区

--hard

  移动指针,重置暂存区,重置工作区

3.1.5 Git删除文件找回

前提是文件存在时的状态提交到了本地库

通常用git reset --hard 指针位置找回

文件提交至本地库后被删除

删除文件在本地库中也是一次提交申请,可以通过版本回退找回该文件。

删除文件指令在暂存区还未提交至本地库

git reset --hard HEAD(该指令会将暂存区和工作区刷新)

3.1.6 比较文件差异

	git diff 文件

不添加参数表示和暂存区进行比较

	git diff HEAD^ 文件名

表示和上一版本进行比较

	git diff 本地库中历史版本 文件名
表示和历史版本文件进行比较

3.1.7 分支管理

1.什么是分支?

在版本控制过程中,使用多条线同时推进多个任务。

2.分支的好处

	可以同时并行推荐多个功能开发,提高开发效率

	各个分支在开发过程中,如果某一个分支开发失败,直接删除即可,不会影响项目进行

3.分支操作

查看分支

	git branch -v

创建分支

	git branch 分支名

切换至对应分支

	git checkout 分支名

合并分支

   1.切换至接受修改的分支(增加新内容)

   2.执行merge命令(此处分支名为要合并的分支名)

 		git merge 分支名

解决冲突

   当两个分支同时修改同一个文件的同一个位置,就会产生冲突。

   当产生冲突时,会处于Merging状态,表示自动合并失败,处于正在合并的状态。

   文件中会增加特殊标记
	  
	   <<<<<<<<HEAD		当前分支内容
	   code
	   =========
	   another code
	   >>>>>>>> master		另一分支内容
	   
   直接对此文件进行修改,可以直接删除标记,当确定好修改内容后,再次提交结束合并即可。

   本次提交不能携带文件名,直接使用git commit -m “demo”提交即可。

3.2 远程库操作

3.2.1 创建远程库

选择喜欢的远程库网站创建即可,常用的远程库有github、gitlab、gitee。

创建好远程库后,选择对应的HTTPS地址复制以供后续操作使用。

远程库名称不必与本地库名称一致,但最好名称一致。

3.2.2 在本地为远程库定义别名

将远程库地址以别名形式保存,后续可以使用别名代替该远程库地址

查看地址别名

	git remote -v

为远程库地址定义别名origin

	git remote add origin 地址

例:git remote add origin https://xxxx.git

3.2.3 推送至远程库

	git push 别名 分支名

例:git push origin master

3.2.4 克隆至本地库

将远程库克隆至本地库

	git clone 地址

例:git clone https://xxxx.git

3.2.5 邀请其他成员加入团队

在所使用的远程库中将其他成员加入团队即可。

若非团队成员,将没有提交至远程库权限。

3.2.6 远程库修改内容的拉取

采用git pull指令进行拉取,拉取行为其实是fetch和merge的合并操作

方法一:

		git fetch origin 分支名
		
		该语句只是将远程库文件下载至本地,并没有进行合并
	
		下载下来的文件在"origin/分支名"目录中
	
	例:git fetch origin master
	
		git merge origin/分支名
		
		该语句将会将文件进行合并
	
	例:git merge origin/master

方法二:

	git pull origin 分支名
	
	该语句将会直接进行远程库的下载及合并

	例:git pull origin master

3.2.7 协同开发冲突解决

当同时用旧版本开发产生冲突时,需要先拉取服务器最新版本。
在本地解决冲突后,再次提交,解决冲突方法与本地库冲突相同。

3.2.8 跨团队协作

假定a团队要让b团队进行协作。

首先b团队使用fork复制一份a团队的项目,修改完之后发起pull request请求,
b团队对提交的请求进行审核,审核通过后进行合并

1.b团队在远程库项目页面点击fork进行fork操作,该操作远程库会自动进行。

2.b团队将项目clone到本地,在本地进行修改后,提交推送至b团队的项目库。

3.b团队发起pull request请求,在远程库项目页面进行该操作。

4.a团队接受到pull request请求后,在远程库项目页面对该请求进行审核,审核通过后进行合并即可。
可以在该请求界面进行对话。