代码版本控制系统
背景:
- 当公司的服务器架构越来越复杂,需要频繁的发布新配置文件,以及新代码,需要确保多版本的存在,如果恢复到之前版本,那么就需要保留之前的版本。但是如果机器部署数量较多,发布的效率必然很低。
- 并且如果代码没有经过测试环境,预生产环境层层测试,最终才到生产环境,不经过测试的部署,会导致很严重的bug,因此必须要进行一定的代码测试。提交了一堆新的代码,构建系统,下载代码,自动化测试代码,扫描代码(大部分bug,可以通过代码质量检测),检查后,部署正式服务上!。
- 因此从devops部署理念来看,任何一家单位都必须实现CICD(持续集成、持续交付)的理念,实现自动化代码集成、自动化代码部署。
主流的方式:
- 采用git代码版本控制系统,jenkins代码构建系统,gitlab代码仓库(自建),sonarqube代码扫描工具。来实现CI/CD。
什么是devops开发流程:
- DevOps是一种实现Dev(开发)与Ops(运维)工作流有效联合的运维文化理念。DevOps是一种文化,一种理念,是一种把开发(Dev)、测试(Test)、运维(Ops)及最终发布(CR)工作流进行联合的思想。
- 越高级的运维,越是要了解开发与运维的有效工作的结合,推进运维自动化操作,提升运维的效率。
- 一个软件开发团队,会包括:项目经理,系统架构师、前端开发者,后端开发者,测试工程师,网络工程师,运维工程师等。
- 如何让软件在开发、测试、运维及最终发布之间进行有效的流动,这就是DevOps所要关注的重点。
devops如何实现:
- 所有环境和代码使用同一个仓库,将软件包纳入版本管理:git + gitlab
- 团队共同决定发布流程。
- 保持 DEV、TEST、PRODUCTION 环境的一致性:jenkins + shell
- 自动化回归测试,回归测试是指修改了旧代码后,重新进行测试以确认修改没有引入新的错误或导致其他代码产生错误。
- 当代码出现问题,怎么回归到上一个版本(没有出问题的版本),告知开发,这个版本存在问题,进行修复,在经历 测试,线上测试,正式环境部署,回归测试:提交bug,开发修复后,防止出现新的bug,又进入测试,才能进行线上部署(不可能修改完毕的代码,直接放在线上进行使用)。
- 小步提交,每日部署,而不是一次部署大量代码变更:只要代码变更,就需要上传代码,而不是将代码更新堆积到一定量在进行上传更新测试代码,这样出现一个问题,就需要推翻,检查,代码量大,检查复杂,无用功。
- 更快、更频繁发布:只要有更新,立马进行发布,测试,线上测试,正式上线。
1.版本控制
什么是版本控制:
- 版本控制是一种记录一个或若干文件内容变化,以便将来查阅特定版本修订情况的系统。方便的对文件进行管理,方便的回滚到之前的任何一个版本,同时对每一个版本进行记录说明。
- 例如在写毕业论文时(这也是一种版本控制的手法,只不过是,对文件进行了另存的操作,当你需要回到xx的版本的论文时,你怎么知道这个版本是xx的版本这是缺点。):
- 论文1.doc
- 论文2.doc
- .....
版本控制软件雏形:
- 对于文件使用版本号,日期的管理,这种方式比起没有版本管理好得多,但是也很臃肿,且他人不容易看得懂。
版本 文件名 用户 说明 日期 1 nginx1 小王 修改域名 17:10 2 nginx2 小李 修改端口 18:30 3 nginx3 小赵 修改url 20:30 新式版本控制:
- 现在的版本控制系统又是如何管理的,且还能实现快速回退功能。会进行记录每次提交的内容,进行存储,当需要时,可以查询版本,版本说明,以及回退到指定的版本。
2.什么是CI-持续集成
什么是持续集成:
- 公司的代码,是由多个子系统构成,将多个子系统合并到一起,这个步骤就叫做集成。
- 每个子系统,每天需要更新多次代码,合并到一起,这个步骤就是持续集成。
- 持续集成就是在于持续两字,频繁的(一天多次)的将代码集成到主干(master),重复如上的工作(每天上传代码到主干master 10次,这个过程就是持续集成的过程)。
- 说白了就是你公司要部署一套系统,能支持,让所有的开发人员,都可以快速、集中式的提交代码,整合到一个主干线。
- git本地仓库 → 远程仓库 → jenkins执行脚本(如对代码编译,测试,运行) → 通知集成结果。
软件开发的常见两种场景:
- 有一个电商平台需要开发,由于电商平台模块众多,此时就需要不同开发人员开发不同的模块,最红把所有人的代码都集中到一个系统中。(开发阶段)
- 随着时间的推移,无论是修复bug还是新功能开发,后续都要对系统进行不断的更新、迭代。(维护阶段)
简单理解持续集成:
- 频繁的将代码上传到远程仓库中,并自动进行构建和测试(开发一个功能只要完成就更新代码,不等待写的多了在更新)。
持续集成的优势:
- 可以快速发现问题,及时修正。
- 节省人力成本,省去手动反复部署操作,加快软件开发进程,进行实时交付。
- 防止大幅度偏离主干,如果不经常集成,主干也在更新,会导致后续集成难度增大,或是难以集成。
不做持续集成:
- 如果是一个小项目,就不需要做这种持续集成(开发人员少,进行持续集成的情况下会增加工作量),直接在本地进行测试完毕后,写一个部署脚本进行实现即可。
- 如果是一个大型的项目,就必须要做。因为复杂,而且需要不断的加新功能,升级产品。就需要这种CI持续集成,方便管理,加快项目的开发进程。
3.什么是CD-持续部署
持续部署是什么:
- Continuous Deployment,持续部署,产品从开始到结束诞生的产物,在服务器上健康运行。持续交付指的是在持续集成(CI)的环境基础之上,将代码自动化部署到预生产环境。持续集成,对代码进行集成测试,持续部署,对代码进行自动化部署。
过程:
- 部署了一套基于 git + gitlab + jenkins + shell 的持续集成、持续部署系统之后。就可以实现快速的代码快速更新,快速发布,且因为经过了测试,保证了代码质量。
- 如果开发李四,写的新功能代码有bug,当你基于jenkins对代码测试之后,定位bug、通知程序修复bug,最终再整合最新的代码到master主线上。
- 自动化流程能极大提高生产级别的开发、测试、运维效率了。
如何实现CD:
- 当有人提交了代码,就自动的通知jenkins对代码进行构建 > 测试 > 确认代码可运行 > 构建到生产服务器。
- 整个过程全自动化,但是有可能出现难以预料的问题,最好的是半自动化,使用持续交付(人工介入+jenkins发布),过于自动化可能会出现问题。
4.持续集成持续部署(CI/CD)
介绍:
- CI/CD 是持续集成(Continuous Integration)和持续交付/持续部署(Continuous Delivery/Continuous Deployment)的缩写。它们是现代软件开发中常用的两个实践,旨在提高软件开发的效率和质量。
- CI是CI/CD的第一步流程,强调频繁的代码提交与测试。
- CD包含只持续交付和持续部署,强调将代码自动部署到生产环境中。
- CI/CD 整体目标是提高软件开发的效率和质量,实现快速、可靠的软件交付。
持续集成:
- 开发者频繁的将代码变更合并到共享仓库中。
- 自动化构建代码,确保代码的质量,及时发现问题,并且进行整改。
持续交付/持续部署:
- 在持续集成的基础上,将经过测试的代码自动部署到生产环境。确保软件随时处于可发布状态。缩短开发到发布的周期,提高交付速度。
- 持续交付的一种形式,指将经过测试的代码自动部署到生产环境。无需人工干预,实现完全自动化的发布流程。
5.主流的版本控制软件
主流的版本控制工具:
- git与svn
SVN:
- 集中式版本控制系统。
- 集中式版本控制系统,版本库是集中存放在中央服务器的,而干活的时候,用的都是自己的电脑,所以要先从中央服务器取得最新的版本,然后开始干活,干完活了,再把自己的活推送给中央服务器。中央服务器就好比是一个图书馆,你要改一本书,必须先从图书馆借出来,然后回到家自己改,改完了,再放回图书馆。
- 集中式版本控制系统,最大的毛病就是必须联网才能工作,如果在局域网还好,如果在互联网上就比较慢了(带宽,网络波动等问题)。如果中央仓库服务器挂了,那么就无法再进行使用下载更新代码。
- 从中央服务器中下载最新的代码(多人协作),怕其他人上传了新的代码,自己没有下载最新的,导致自己写的代码与其他人的新代码出现冲突问题,出现bug,每一次都需要拉去最新的代码,然后进行编写,并且上传,中央服务器中进行合并。
Git:
- 分布式版本控制工具。
- 没有中央服务器的概念,每个人都有自己的版本库,因此每个人在工作时候,不需要联网,版本库本地即可管理。每个人都是一个完整的版本库,同事之间如果需要协作开发,就需要找一个用于“交换文件”的中央服务器,这个服务器不存在也不影响大家干活,只是用于交换文件内容。
Git特点:
- git是分布式的,特点是保存本地文件的元数据(meta data,文件属性等),将本地文件所有的的元信息,记录在git repo里的.git隐藏文件夹中。
- git的使用可以不用网络,因为本地版本控制仓库就在你自己机器上,每一个人就是一个完成的版本库。只不过是最终将你的本地仓库,作为一个分支,推送、合并到一个统一的线上代码仓库主干线即可,实现代码集成。
Git工具
1.下载安装
1.windows安装
https://git-scm.com/download/win
2.linux安装
yum install git -y
sudo apt install git -y
或者安装二进制包 https://git-scm.com/download/
git --version # 验证版本
2.配置命令相关
命令:
git config [--global | --local | --system] <key> <value>
参数:
- 读取顺序:
--local
(仓库级) >--global
(用户级) >--system
(系统级)- 推荐使用:
--global
参数 说明 --global
应用当前用户的全局配置(默认存储在 linux:~/.gitconfig
或Windows:%USERPROFILE%\.gitconfig
)。--local
仅应用于当前 Git 仓库,当前初始化的文件夹。(存储在 .git/config
)。--system
应用于整个系统的 Git 配置(存储在 Linux:/etc/gitconfig
,Windows:
C:\Program Files\Git\etc\gitconfig``,需管理员权限)。1.使用 --global # 在当前登录的账户生效 git config --global user.email "123@qq.com" git config --global user.name "123" 2.使用 --local # 只会在当前仓库中生效 sudo mkdir /test && cd /test && sudo git init # 初始化一个仓库 sudo git config --local user.email "456@qq.com" sudo git config --local user.name "456" 3.使用 --system # 全局生效,无论是哪个仓库那个账户 sudo git config --system user.email "789@qq.com" sudo git config --system user.name "789"
2-1.相关配置
# 用户身份:
user.email "设置邮箱"
user.name "设置名字"
# 初始化
init.defaultBranch "主分支名称一般为 mian或者master" # 默认分支名(避免使用 master)
# 别名
git config --global alias.st "status"
git config --global alias.ci "commit"
git config --global alias.co "checkout"
git config --global alias.br "branch"
git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset'"
设置别名时,在linux中可能会出现权限的问题,请注意权限(提示在项目发现可以所有权的提示)
git config --global --add safe.directory /仓库路径 # 添加到安全目录
# 分支拉去行为
git config --global pull.rebase "true" # 拉取时自动 rebase(避免多余 merge 提交)
git config --global push.default "simple" # 推送时仅推送当前分支(安全模式)
# 跨平台处理
git config --global core.autocrlf true # Windows(提交时转 LF,检出时转 CRLF)默认为true
git config --global core.autocrlf input # macOS/Linux(提交时保持 LF)
# 差异与合并工具
git config --global diff.tool "vscode" # 使用 VS Code 作为对比工具
git config --global difftool.vscode.cmd "code --wait --diff $LOCAL $REMOTE"
git config --global merge.tool "vscode" # 使用 VS Code 解决冲突
git config --global mergetool.vscode.cmd "code --wait $MERGED"
# 代理
git config --global http.proxy "http://127.0.0.1:7890" # 设置 HTTP/HTTPS 代理(如国内加速)
git config --global https.proxy "http://127.0.0.1:7890"
git config --global http.sslVerify false # 禁用 SSL 验证(仅内网测试用)
2-2.配置相关命令
git conifg --list # 查看全部配置
git config --get <key> # 获取单个配置值
例如:git config --get user.name
git config --get-all <key> # 获取配置项的所有值
例如:git config --get-all user.name
git config -get-regexp <key*> # 使用正则表达式方式
例如:git config --get-regexp ^alias
git config --add <key> <val> # 追加值,不覆盖原来的值
例如:git config --add user.name "6666"
git config --unset <key> # 删除单个值,如果有多个值无法删除,需要使用--unset-all
例如:git config --unset user.name
git config --unset-all <key> # 删除多个值
例如:git config --unset-all user.name
git config -e # 打开编辑模式对git配置进行编辑
git config --rename-section <旧节点> <新节点> # 重命名配置节点
例如:git config --rename-section user userabd
git config --remove-section <节点> # 删除整个配置节点,git配置是init格式的,直接删除整个节点下的全部配置
例如:git config --remove-section user
# 如果只配置中进行修改
sudo git config --local user.name "7778" # 修改当前仓库,如果没有这个key就添加
sudo git config --glocal user.name "7778" # 同理
sudo git config --system user.name "7778" # 同理
# 初始化仓库,需要进入目录中执行命令,就会在目录下创建一个.git的文件
git init
# 获取帮助
git help
3.常用相关命令
3-1.仓库初始化
1.对文件进行仓库初始化 # 会在文件中创建 .git的文件
git init
git init <project-name> # 指定初始化的目录
2.克隆现有仓库 # 对远程仓库进行克隆
git clone <repository-url>
3-2.基本操作
1.查看仓库状态
git status
2.将文件添加到暂存区
git add . # 将全部的变动的文件添加暂存区
git add <file-name> # 添加指定的文件到暂存区
3.提交暂存区 # 会生成一个版本,会有一个专门的版本号座位标识,根据这个版本号可以进行回滚
git commit -m "提交信息"
3-3.分支操作
# 注意
当对一个文件进行初始化时,可能没有分支,需要创建一个文件并且提交一个版本后就会自动创建一个默认分支。
1.查看分支
git branch # 查看本地分支
git branch -a # 查看分支包含远程分支
2.分支创建和切换
git branch <分支名称> # 创建
git checkout <分支名称> # 切换
git checkout -b <分支名称> # 创建分支并且切换
3.分支删除
git branch -d <分支名称> # 删除已合并的分支
git branch -D <分支名称> # 强制删除未合并的分支
git push origin --delete <分支名称> # 删除远程分支
4.推送分支到远程仓库
git push -u <远程仓库的别名> <本地分支> # -u 强制关联
3-4.远程操作
1.查看远程仓库
git remote -v
2.添加远程仓库
git remote add <远程仓库的别名> <远程仓库的地址> # 给远程仓库地址设置一个别名,使用别名进行推送
3.推送
git push <远程仓库的别名> <本地分支> # 推送远程仓库
git push -u <远程仓库的别名> <本地分支> # 设置上游分支并推送,
# -u参数说明:
将本地分支推送到远程,如果没有就会创建,在建立远程分支与本地分支的关联关系
第一次推送新分支使使用 -u ,后续在推送时不需要再使用。
git push <远程仓库的别名> <本地分支> --force # 强制推送
git push <远程仓库的别名> <本地分支名>:<远程分支名> # 本地分支名与远程不同名
4.拉去更新
git pull # 更新当前本地所在分支
git pull <远程仓库的别名> <本地分支> # 更新
git fetch # 拉去更改不合并
3-5.撤销操作
1.撤销操作(将文件内回到上一个提交版本)
git checkout -- <文件名称> # 某个文件
git checkout -- . # 全部
2.将暂存区文件回撤到工作区。# 暂存处 -> 工作区
git restore --staged . # 撤销全部
git restore --staged <文件名称> # 单个文件撤销
3.从提交的版本撤销到暂存区 # 版本(本地仓库) -> 工作区
git reset --soft <commit-hash>
git reset --soft HEAD~1 # 撤销最近一次提交,但保留修改到暂存区
# 注意:
1.git restore --staged . 解释:
当进行 git add . 是将修改的文件从 工作区(当前文件)提交到 暂存区(暂时)。
git restore --staged . 使用可以将 暂存区(暂时)回撤到 工作区(当前文件)
2.git checkout -- . 解释:
# 当前文件已经提交了一个版本
文件不在暂存区,可以使用 git checkout -- . 将文件的内容 回滚到上一次版本的文件内容。
# 当撤销时只有两种情况:(版本(本地仓库) -> 暂存区)
1.提交版本,那么git文件指针就会指向最新的提交版本HEAD
2.撤销暂存区的话,git文件指针指向原来版本的HEAD
3-6.标签管理
1.创建标签
git tag <标签名称> # 创建标签
git tag -a <标签名称> -m "标签信息" # # 创建附注标签
2.推送标签
git push <远程仓库的别名> <标签名称> # 推送指定标签
git push <远程仓库的别名> --tags # 推送全部标签
3.查看标签
git tag # 查看本地的标签
git ls-remote --tags origin # 查看远程的标签
git show <标签名称> # 查看标签的详情
4.删除标签
git tag -d <标签名称> # 删除标签
git push <远程仓库的别名> --delete <标签名称> # 删除远程标签
5.拉去远程标签到本地
git fetch --tags
3-7.查看历史
1.查看历史 # 简洁查看
git log --oneline
2.查看历史 # 图形查看
git log --graph
3.查看特定文件的提交历史
git log -p <文件名称>
3-8.查看差异
1.查看差异
git diff # 工作区与暂存区差异
git diff --cached # 暂存区与最新提交差异
git diff <分支1>..<分支2> # 两个分支间差异
3-9.回滚操作
作用:
可以将代码回滚到之前的代码
1.查看状态
git log --oneline # 是一个短的版本号
git log # 长的版本号
2.回滚 # 本地仓库
git reset --soft <版本号>
# 解释:
回退到<版本号>提交,但保留所有修改(版本号之后提交的版本修改文件)在暂存区。
存放区域:暂存区
作用:重新提交
git reset <版本号>
# 解释:
回退到<版本号>提交,将<版本号>之前提交的版本修改的文件存放到工作区。
存放区域:工作区
作用:选择性提交
git reset --hard <版本号>
# 解释:
完全放弃最新提交的所有更改(当前回滚版本之后提交的版本),放弃之前的修改。
作用:全部删除,重新提交。
3.提交到远程仓库
# 1.个人本地分支
1.回到到指定的版本 # 这三种方式,使用那种看需要
git reset --soft <版本号>
git reset <版本号>
git reset --hard <版本号>
2.修改内容
回滚到版本后,修改内容
3.强制与远程进行同步
git push --force origin master
# 2.团队协作,这种方式相当于生成一个新的版本号,并不能修改文件内容。
作用:通过生成一个新的提交来抵消历史提交的变更。
1. 撤销之前的revert提交。
git revert <版本号>
2. 查看结果(会新增一个提交)
git log --oneline
3. 正常推送
git push origin master
3-10.变基操作
作用:
- 是一种重写提交历史的操作,它可以将一个分支的提交“重新嫁接”到另一个分支的最新提交上。 它的核心作用是整理提交历史,使其更清晰、线性化,将你当前分支上的修改,"搬到"目标分支的最新提交后面。
为什么使用:
- 历史整合:没有多余的合并提交,看起来像是所有更改都在一个线性历史中完成。
- 避免复杂的合并冲突:如果你在本地先做了变基,再将变基后的分支推送到远程仓库,通常能够减少合并冲突的发生,尤其是在多人协作的项目中。
变基的过程:
- 在变基分支(当前分支),变基操作会丢弃变基分支(当前分支)包含在被变基的分支(目标分支)中的版本提交(将重复的版本剔除)。
- 变基后变基分支(当前分支)的分支版本会被重新提交到被变基的分支(目标分支)最后一个版本之后,形成新的提交,新的提交的hash值会有变化。
- 结果: 变基分支(当前分支)就像是 从被变基分支最后一个版本分出来的一样。
变基后的历史:
- 注意:
变基的分支(当前分支)历史会发生变化。被变基分支(目标分支)的历史版本不变
。- 变基的分支(当前分支)提交的版本(在从目标分支分离后提交版本),将会变成新的提交版本(hash值会变化)。
- 组成:被变基的分支(目标分支)提交的最后一个版本 + 变基的分支(当前分支)在从目标分支分离后提交版本 = 变基分支的版本。
变基的直观图解:
变基后推送远程仓库注意:
推送的到远程仓库的分支是当前分支(变基的分支),而不是目标分支(被变基的分支)。
变基操命令:
# 变基操作 1.变基操作 git checkout <当前分支(变基的分支)> # 先切换到某个分支 git rebase <目标分支(被变基分支)> # 变基目标分支 1.1.如果出现冲突,解决冲突 git add <conflicted_file> # 添加冲突文件 git rebase --continue # 解决冲突后继续变基 2.放弃分支: git rebase --abort # 放弃变基 3.提交远程分支: git push --force <远程仓库别名> <本地分支(切换的分支)> git push --force-with-lease <远程仓库别名> <本地分支(切换的分支)> # 参数说明: --force:无条件覆盖远程分支,不管是否有新提交 --force-with-lease:先检查远程分支是否变化,有变化则拒绝推送
操作案例:
# 分支结构: A---B---C1---C2 (master) # 被变基分支 \ F1---F2 (dev) # 变基分支 # 解释: 1.dev分支从B分支中产生的一个分支 2.master分支也在产生新的版本。 # 变基后: A---B---C1---C2 (master) A---B---C1---C2---F1'---F2' (dev) # 操作流程: 1.切换分支到dev分支 # 切换到当前分支(变基分支) git checkout dev 2.执行变基操作 # dev是变基分支(当前分支) master是被变基分支(目标分支) git rebase master # 解释:将 dev 分支的提交版本应用到 master 分支的最新提交 C2版本 上 3.处理冲突问题 # 在变基时会因为冲突导致变基终止,需要解决冲突后进行变基。 git add <conflicted_file> # 添加冲突文件到暂存区 git rebase --continue # 解决冲突后继续变基 4.推送到远程分支 # 推送变基的分支(当前分支) git push --force origin dev # 强制推送dev分支到远程,因为dev分支变基了。
3-11.合并操作
作用:
- 将两个分支或者多个分支的开发历史(提交版本)进行合并到一起的操作,git工具的核心。
- 合并时,会出现冲突的情况,需要进行解决(合并是将两个分支的修改历史整合在一起)。
合并命令:
1.基本命令 git merge <分支(合并目标分支也就是需要合并的分支)> 2.终止合并 git merge --abort 3.特定合并 git merge -s <参数> recursive (默认) octopus (合并多个分支) ours (总是使用当前分支版本) subtree (子树合并)
合并图解:
操作案例:
分支结构如下: A---B---C1---C2 (master) # 主分支 \ F1---F2 (dev) # 子分支(需要合并的分支) # 注意: 将dev合并到master分支,需要进去master分支执行git merge dev "把 dev 合并到 master" = 站在 master 家门口,让 dev 把代码送过来。 1.切换到master分支 # 确保分支是最新的 git checkout master 2.执行合并命令 # 合并dev分支,确保分支最新 git megre dev # 如果没有冲突,就会自动生成合并的版本 3.如果出现冲突,不想合并 git merge --abort # 完全取消本次合并,回到冲突前状态 4.如果出现冲突,想合并 解决冲突后 git add <冲突文件> git commit -m "自定义提交信息即可" # 完成合并操作 5.远程操作 # 删除分支 git push <远程仓库别名> master # 提交远程操作 git push origin --delete dev # 删除远程dev分支 git branch -d dev # 删除本地dev分支 5.远程仓库 # 保留分支,同时在这个分支上进行开发 git push <远程仓库别名> master # 提交远程操作 git checkout dev # 切换 git rebase master # 变基目标分支master git pull origin dev # 同步远程最新状态 合并后: A---B---C1---C2---M (master) \ / F1---F2 (dev)
合并后分支远程操作:
3-12.变基与合并的区别
特性 | 合并(merge) | 变基(rebase) |
---|---|---|
历史记录 | 保留分叉结构 | 强制线性历史 |
提交哈希 | 保留原提交 | 生成新提交(哈希改变) |
操作方向 | 把分支拉过来 | 把分支推过去 |
适用场景 | 公共分支(如 master) | 本地私有分支 |
风险 | 安全 | 可能破坏历史(需强制推送) |
3-13.补充
# 当不小心删除文件,但是并没有提交版本前,也就是在工作区操作删除是需要恢复的操作。
# 前提:当前文件已经提交过历史版本。
1.撤销暂存区的删除
git restore --staged <file>
2.恢复工作区的文件
git restore <file>
4.了解.get目录
.git
├── branches
├── config # 这个项目独有的配置
├── description
├── HEAD # head文件指示目前被检出的分支
├── hooks # hooks目录包含服务端和客户端的钩子脚本 hook scripts
│ ├── applypatch-msg.sample
│ ├── commit-msg.sample
│ ├── post-update.sample
│ ├── pre-applypatch.sample
│ ├── pre-commit.sample
│ ├── prepare-commit-msg.sample
│ ├── pre-push.sample
│ ├── pre-rebase.sample
│ └── update.sample
├── index # index文件保存暂存区的信息,只有git add之后才会生成,默认还没有这个文件
├── info # info目录是全局性排除文件,用于放置不想被记录在.gitignore文件中的忽略模式(ignored patterns)
│ └── exclude
├── objects # 存储所有数据内容
│ ├── info
│ └── pack
└── refs # refs目录存储指向数据(分支)的提交对象的指针
├── heads
└── tags
5.Git工作分区
分区说明:
1.工作区:就是当前文件(使用git init初始化)
2.暂存区:介于工作区和本地仓库之间的位置,记录git提交的内容,并不进行版本控制。(使用git add .)
3.本地仓库:将暂存区的内容提交为一个版本存储到本地仓库(使用 git commit -m "说明")。
4.远程仓库: 远程的仓库,比如 github gitee gitlad(私有仓库)
# 说明:
git 命令就是在3个分区之间进行切换使用。
6.Git的版本概念
解释:
git版本可以理解为每一打游戏的存档,在进入boos房间之前存档。去打boss,如果在打boss中死亡,那么就需要从新开始。与vmware的快照差不多。
7.Git的.gitignore文件
作用:
当前文件,可以设置git在将内容提交到暂存区时,可以进行忽略设置,不会被git进行管理。
1.在版本控制的文件夹中创建隐藏文件
touch .gitignore
2.语法
*.log # 忽略log的文件
*.sh # 忽略sh文件
123/ # 忽略123文件夹
.xml # 忽略xml文件
8.补充内容
1.当你在开源的仓库将你的本机秘钥添加到开源仓库的 ssh公钥上怎么验证。
ssh -T git@gitee.com # 进行验证
ssh -vT git@gitee.com
# 参数解释:
-v 显示 SSH 连接过程的 详细调试信息,帮助排查问题(如认证失败、网络不通等)。
-T 明确告诉 SSH 不要分配伪终端(PTY),仅用于传输数据。测试 SSH 连接(如 git@gitlab.com)时,服务器通常不提供交互式 Shell,用 -T 避免报错。
Git私有仓库
仓库的目的:
- 中小型公司:业务少,运维人员少,使用远程仓库就可以(gitlee或者github)。
- 大型公司:将自己的代码放在github或者gitee上,肯定不安全,大型公司的代码很值钱,比如淘宝,支付宝,腾讯等。 大公司都会买自己的服务器,在服务器上安装gitlab(自己的开发仓库软件),进行代码私有化,防止公司代码泄露。
git与(github/gitee)的区别:
- git是本地分布式仓库管理工具。
- github和gitlee是开源免费的远程仓库,就是一个存储中转站。部署时不可能从开发人员的本地电脑上拷贝代码,而是通过仓库下载到部署机器上进行操作。
Gitlab私有仓库:
- 官方网址:https://about.gitlab.com/
- 文档地址:https://docs.gitlab.com/
- 中文文档:https://gitlab.cn/docs/jh/
- Gitlab是一个开源分布式的版本控制系统,由Ruby语言开发,Gitlab主要实现的功能、管理项目源代码、对源代码进行版本控制,以及源代码的复用和查找。
Gitlab优势和应用场景:
- 开源免费,搭建简单,维护成本低,适合中小型公司。
- 权限管理,实现代码对部分人可见,确保醒目安全性。
- 离线同步,保证我们不需要依赖于网络环境进行代码提交(代码本地仓库管理然后推到远程仓库)
1.安装部署
# 使用的是centos7进行安装
采用软件包安装方式:
https://docs.gitlab.com/install/requirements/ # 安装要求
https://docs.gitlab.com/install/package/ # gitlab包的文档地址
https://packages.gitlab.com/gitlab/gitlab-ce # 社区版地址
注意:
先关闭 selinux 和 filewalld 防火墙。
1.安装依赖
sudo apt install -y curl openssh-server ca-certificates postfix # ubuntu
sudo yum install -y curl policycoreutils-python openssh-server postfix # centos7
2.下载仓库也可以 # 注意:需要只要自己的操作系统适合哪个版本,就安装哪个版本的
curl -s https://packages.gitlab.com/install/repositories/gitlab/gitlab-ee/script.rpm.sh | sudo bash
curl -s https://packages.gitlab.com/install/repositories/gitlab/gitlab-ee/script.deb.sh | sudo bash
3.或者使用其他源(清华源或者阿里源)
https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/ # 选择自己需要的版本
https://mirrors.aliyun.com/gitlab-ce/ # 阿里版本太老了
wget https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/gitlab-ce-12.0.3-ce.0.el7.x86_64.rpm
4.进行安装
rpm -ivh gitlab-ce-12.0.3-ce.0.el7.x86_64.rpm # 使用rpm命令安装
yum localinstall gitlab-ce-12.0.3-ce.0.el7.x86_64.rpm # 使用yam localinstall安装
2.配置文件
# 配置相关文档:
https://docs.gitlab.com/administration/configure/ # 没有老版本的配置,某些参数可能变动
# 配置文件位置:
/etc/gitlab/gitlab.rb
1.配置域名,启用证书
external_url 'https://gitlab.yourdomain.com' # 替换为你的域名或者ip地址
# 启用自动注册 Let's Encrypt 证书 证书默认有效期 90 天,GitLab 会自动续签
letsencrypt['enable'] = true # 自动注册
letsencrypt['contact_emails'] = ['admin@yourdomain.com'] # 通知邮箱,是否自动续签失败的通知。
2.邮箱配置
gitlab_rails['smtp_enable'] = true # 开启邮箱
gitlab_rails['smtp_address'] = "smtp.aliyun.com" # 邮箱服务器
gitlab_rails['smtp_port'] = 465 # 端口
gitlab_rails['smtp_user_name'] = "your_email@aliyun.com" # 邮箱
gitlab_rails['smtp_password'] = "your_password" # 授权码
gitlab_rails['smtp_tls'] = true # 使用那个邮箱,使用那个端口,配置端口和是否使用ssl配置配置,请查看对应的邮箱文档
gitlab_rails['gitlab_email_from'] = '565151759@qq.com' # 外发电子邮件显示的发件人电子邮件地址
gitlab_rails['gitlab_email_display_name'] = 'gitlab123' # 外发电子邮件显示的发件人名称
gitlab_rails['smtp_authentication'] = "login" # smtp邮箱服务的 认证方式
gitlab_rails['smtp_enable_starttls_auto'] = true # 启用 自动协商 TLS 加密。客户端会尝试通过 STARTTLS 命令将明文连接升级为加密连接(基于服务器支持情况)。如果端口已经强制加密请设置为 false
3.安全配置
gitlab_rails['backup_path'] = "/var/opt/gitlab/backups" # 备份保留位置
gitlab_rails['backup_keep_time'] = 604800 # 保留7天
# 手动备份命令:sudo gitlab-rake gitlab:backup:create
unicorn['worker_processes'] = 2 # 根据CPU核心数调整
sidekiq['concurrency'] = 5 # 减少后台任务线程
postgresql['shared_buffers'] = "256MB" # 根据内存调整(建议总内存的25%)
gitlab_rails['redis_cache_enabled'] = true # 启动缓存
unicorn['port'] = 8080 # 服务端口,这个端口会被nginx反向代理
4.时区设置
gitlab_rails['time_zone'] = 'Asia/Shanghai'
5.关于账户密码
账户默认:root
密码:第一次登录会让你创建密码
2-1.启动配置
1.配置 external_url 参数,没有域名设置ip
external_url 'http://192.168.85.149'
2.配置邮箱 # 配置全局邮箱时,无论是测试时还是实际使用时,ui界面或者后台日志提示错误,实际上邮件已经发出去了。换个全局邮箱解决
gitlab_rails['smtp_enable'] = true
gitlab_rails['smtp_port'] = 465
gitlab_rails['smtp_user_name'] = "xxx@qq.com"
gitlab_rails['smtp_password'] = "PDy9z32FVKgdNTzv"
gitlab_rails['smtp_address'] = "smtp.qq.com"
gitlab_rails['smtp_domain'] = "smtp.qq.com"
gitlab_rails['smtp_authentication'] = "login"
gitlab_rails['smtp_enable_starttls_auto'] = true
gitlab_rails['smtp_tls'] = false
gitlab_rails['gitlab_email_from'] = 'xxx@qq.com'
gitlab_rails['gitlab_email_display_name'] = 'gitlab123'
3.加载配置
gitlab-ctl reconfigure # 第一次重新加载速度特别慢
4.启动服务
gitlab-ctl start # 第一次登录需要设置root的密码,设置密码 123456789
2-2.启动的组件
[root@gitlab ~]# gitlab-ctl start
ok: run: alertmanager: (pid 14268) 1s
ok: run: gitaly: (pid 14278) 0s
ok: run: gitlab-monitor: (pid 14303) 1s
ok: run: gitlab-workhorse: (pid 14305) 0s
ok: run: grafana: (pid 14356) 1s
ok: run: logrotate: (pid 14404) 0s
ok: run: nginx: (pid 14410) 0s
ok: run: node-exporter: (pid 14416) 1s
ok: run: postgres-exporter: (pid 14421) 0s
ok: run: postgresql: (pid 14427) 1s
ok: run: prometheus: (pid 14436) 0s
ok: run: redis: (pid 14447) 1s
ok: run: redis-exporter: (pid 14451) 0s
ok: run: sidekiq: (pid 14457) 0s
ok: run: unicorn: (pid 14463) 1s
GitLab 由主要由以下服务构成,他们共同承担了 Gitlab 的运作需要
Nginx:静态 web 服务器。
gitlab-shell:用于处理 Git 命令和修改 authorized keys 列表。
gitlab-workhorse: 轻量级的反向代理服务器。 logrotate:日志文件管理工具。
postgresql:数据库。
redis:缓存数据库。
sidekiq:用于在后台执行队列任务(异步执行)。
unicorn:An HTTP server for Rack applications,GitLab Rails 应用是托管在这个
2-3.邮件测试发送
1.使用gitlab的控制台
gitlab-rails console
2.因为gitlab使用的时Ruby写的,需要使用Ruby的语法,发送邮件
# 注意配置文件的邮箱服务器的端口与是否开启ssl配置
Notify.test_email('邮箱','头部','正文').deliver_now
Notify.test_email('xxxx@163.com','gitlab','6666').deliver_now
Notify.test_email('wangkx0227@qq.com','gitlab','6666').deliver_now
3.退出控制台
exit
2-4.主要配置文件说明
/var/opt/gitlab/git-data/repositories/ :库默认存储目录
/opt/gitlab :应用代码和相应的依赖程序
/var/opt/gitlab/ : gitlab-ctl reconfigure生成的数据和配置
/etc/gitlab :配置文件目录
/var/log/gitlab:此目录下存放了gitlab各个组件产生的日志
/var/opt/gitlab/backups :备份文件生成的目录
2-5.命令行工具
1.重载配置
gitlab-ctl reconfigure
2.查看gitlab启动状态
gitlab-ctl status
3.命令大全
gitlab-ctl start # 启动
gitlab-ctl stop # 暂停
gitlab-ctl restart # 重启
gitlab-ctl status # 查看状态
gitlab-ctl tail # 查看全部日志
gitlab-ctl --help # 查看对应的说明
gitlab-ctl stop postgresql # 停止某个服务,比如postgresql
gitlab-ctl tail redis # 查看某个服务的日志,比如redis
# 备份与恢复
sudo gitlab-rake gitlab:backup:create # 备份
sudo gitlab-rake gitlab:backup:restore BACKUP=备份文件名 # 备份恢复
sudo gitlab-rake gitlab:check SANITIZE=true # 检查 GitLab 完整性
sudo gitlab-rake cache:clear # 清理缓存
# 具体请查看文档:
https://docs.gitlab.com/omnibus/maintenance/ # 关于命令行的文档地址
3.关于推送的两种协议
特性 | Git 协议 (git:// ) |
HTTP/HTTPS 协议 |
---|---|---|
速度 | 更快(优化协议) | 略慢(HTTP 开销) |
加密 | 无 | HTTPS 加密 |
认证方式 | 通常依赖 SSH 密钥 | 用户名/密码、PAT、OAuth |
防火墙兼容性 | 需开放 9418 端口 | 兼容性强(80/443 端口) |
读写权限 | 需配置 SSH 写权限 | 直接支持认证写操作 |
1.git协议 # 如果是公共仓库,需要提供邮箱的秘钥,就是远程仓库的个人设置ssh秘钥
适用场景:
1.源项目的克隆(如 Linux 内核仓库)。
2.内网高速访问且无需认证的仓库。
特点:
1.使用git原生协议(默认9418),转为git数据传输优化,通常基于ssh或者直接tcp传输。
2.默认不加密,适合公开仓库的只读访问(开源项目)。
3.虽然可以配置写权限,但通常需要配合 SSH 认证。
2.http或者https协议 # 如果是公共仓库,可以匿名访问直接拉去
适用场景:
1.需要身份验证的私有仓库。企业内网限制 SSH 或 Git 协议的环境
2.简单快速上手(如 GitHub 推荐 HTTPS 默认协议)。
特点:
1.走标准 HTTP/HTTPS 端口(80/443),穿透防火墙能力强。
2.可通过用户名/密码、Personal Access Token(PAT)或 OAuth 认证(适合私有仓库)。
3.HTTPS 提供加密,安全性更高。适合所有网络环境(尤其是企业代理限制严格的场景)。
4.操作设置
4-1.设置中文显示
4-2.设置关闭用户注册
4-3.配置邮箱认证
# 邮箱认证只是针对当前用户,与配置的邮箱不同(配置的邮箱属于全局邮箱,系统方发送邮件使用)。
1.进入用户设置
2.进去邮箱配置输入邮箱
3.进行邮箱认证
# 注意:
管理员也需要在对用户创建是,进行用户邮箱配置,这样,账户注册进行邮箱验证,合并分支修改密码等操作就会通过发邮件的形式通知用户。邮箱通知,是你在配置文件中设置的邮箱发送给用户的邮箱。
4-4.用户组管理
创建小组作用:
1.组中的成员,可以看到当前小组下的全部项目。
2.成员也可以针对性的设置权限。
3.针对小组也可以设置权限(只能下载,不能上传),用户也可以针对性的设置权限(只能下载,不能上传)
4-4-1.创建组操作
4-4-2.创建项目归属与群组
4-4-3.创建用户
# 注意:
1.创建用户是使用的邮箱必须是唯一的。# 会对邮箱发送一份邮件,进行初始化密码。
2.对创建用户,关闭创建组的权限,设置用户为普通用户。
# 登录新创建用户进行查看
账户:project_admin
密码:project_admin # 需要通过邮箱进行设置
4-4-5.将用户拉入到群组
4-4-6.关于用户组的总结
1.创建用户时存在权限
1.普通权限
2.管理员权限
2.在创建组或者创建项目时的权限
1.Private私有,只有组内成员可以看到
2.Internal内部公开,只要可以登录gitlab的用户都能看到
3.Public公开,不用登录的用户可以看到
3.将用户拉去组时的权限
# 这两个权限常用 Developer开发者和Owner所有者
1.访客(Guest)
仅能查看项目、代码和问题(Issue)。无法推送代码或修改仓库内容。适用于需要只读访问的外部人员。
2.报告者(Reporter)
包含Guest的所有权限。可以创建问题、查看CI/CD流水线、下载项目代码。适用于测试人员或需要反馈问题的用户。
3.开发者(Developer)
包含Developer的所有权限。可以管理分支保护、项目设置、CI/CD变量、部署环境。能添加/移除成员(仅限低于自己权限的用户)。适用于技术负责人或项目管理员。
4.Owner(所有者)
拥有组的最高权限。可以修改组设置(如名称、可见性)、删除组、管理所有成员权限。通常是团队负责人或系统管理员。
# 注意:
1.组权限是私有的,那么组内的项目也是私有。
2.组权限是内部公开,组内项目可以是公开和私有。
3.组权限是全部公开,组内项目可以公开,私有,全部公开。
4-5.秘钥设置设置
推送远程仓库代码的两种协议:
1.git :git@192.168.85.149:test/p-001.git
2.http或者https:http://192.168.85.149/test/p-001.git
流程:
1.进行克隆仓库到本地 # 拉去halo代码
git clone git@gitee.com:halo-dev/halo.git # 需要
git clone https://gitee.com/halo-dev/halo.git # 如果是公开不需要密码
git remote -v # 查看
2.设置秘钥 # 在当前机器执行
ssh-keygen
cat ~/.ssh/id_rsa.pub # 公钥的路径,将内容复制添加到秘钥配置中
3.创建文件进行推送,查看远程仓库
git remote set-url origin git@192.168.85.149:test/p-001.git
git remote -v # 查看
git push -u origin main
4-5-1.补充说明
1.仓库是私有的,只是设置了秘钥绑定,为什么可以推送,为什么不用验证账户密码。# 针对git@xxx.com
1.当你把公钥上传到 GitLab/GitHub/gitlee 的 账户设置 → SSH Keys 时,系统会将该密钥与你的账号绑定。
2.当你访问私有仓库时,服务器会检查:
1.密钥是否有效(是否由对应私钥签名)。
2.你的账号是否有该仓库的权限(如 read/write)。
3.Git 服务隐式完成身份认证
1.通过 SSH 协议访问仓库时(如 git@gitlab.com:user/repo.git),服务器会自动通过密钥识别你的身份,无需手动输入用户名/密码。
2.如果密钥匹配且你有权限,操作直接成功;否则返回 Permission denied。
# 核心就是验证你的公钥(你的机器或者其他机器)绑定用户有没有仓库的权限。
# 解释:SSH 密钥认证的本质是验证两件事:
1.公钥是否合法(是否由你上传到 GitLab/GitHub/Gitlee 账户)。
2.绑定的用户是否有目标仓库的权限(读/写/管理员)。
2.仓库是私有的,设置了秘钥绑定,为什么通过http或者https时还需要输入账户密码验证。
1.git@与http的认证机制是独立分开的。
2.HTTP(S) 协议走的是 用户名/密码或 Token 认证,与 SSH 密钥完全无关。即使你配置了 SSH 公钥,也不会影响 HTTP(S) 的认证流程。
3.git通过公钥验证,http(s)通过账密验证或者 Personal Access Token (PAT) 验证。
# 如何解决这个问题:我就想使用http(s)方式,但是我不想输入账密。
1.运行命令 # 临时方案
1.配置临时缓存 # 开启凭证缓存 15分钟
git config --global credential.helper cache
git config --get credential.helper # 确认配置的参数
2.克隆仓库,输入账户密码
git clone http://192.168.85.149/test/p-001.git # 克隆输入账户密码
2.运行命令 # 持久方案
1.配置明文存储到 ~/.git-credentials # 永久存储
git config --global credential.helper store
git config --get credential.helper # 确认配置的参数
2.克隆仓库
git clone http://192.168.85.149/test/p-001.git # 输入账户与密码
3.查看 ~/.git-credentials
# 注意:git 配置完毕公钥,不代表http不用输入账户密码验证,两个不是同一个认证方式。
5.推送实战
注意问题:
1.身份校验(看你使用的是http还是git)私有仓库建议使用建议使用 ssh协议的远程仓库地址配置,只需要设置ssh-key的本地机器的公钥,推送代码不用这么麻烦。
2.关于仓库的共有与私有的问题,如果是gitlab组中得远程项目仓库,需要注意这个组属于公开还是私有的,如果是私有的,通过用户验证,也是无法克隆的。
5-1.推送案例一
5-1-1.设置分支保护
# 拉去创建的仓库,然后在进行推送。
1.进入仓库设置。
2.设置对master分支进行保护(设置相应的权限)。
3.设置master分支只能维护者才能推送。
5-1-2.开发用户推送保护分支
开发者用户:
账户:project_admin
密码:project_admin
1.克隆
git clone http://192.168.85.149/test/p-001.git
2.推送master分支测试
git add .
git commit -m "推送"
git push origin master
5-1-3.开发者用户推送合并
1.克隆仓库
git clone http://192.168.85.149/test/p-001.git
2.创建分支
git branch dev
git checkout dev
3.编写代码,并提交版本
git add .
git commit -m "推送dev分支填写的新代码"
git push origin master
4.提交分支到远程仓库
git push -u origin dev
5.将代码合并到主分支 MR ,通过推送申请的url操作
MR的url:http://192.168.85.149/test/p-001/merge_requests/new?merge_request%5Bsource_branch%5D=dev
6.拉去新代码
git pull origin master
5-2.推送案例二
5-2-1.创建仓库准备代码
# 创建仓库,不拉去,而是本地进行推送远程分支
1.创建一个gitlab仓库 # 注意:是创建个人的还是组的
2.python源码
vim app.py
from flask import Flask
app=Flask(__file__)
@app.route('/')
def index():
return '我是python flask框架项目'
if __name__ == '__main__':
app.run(HOST='0.0.0.0')
3.进行推送远程仓库 <图-3 图-4>
git add .
git commit -m '这是python flask框架项目'
git remote add origin git@192.168.85.149:root/python_flask_test.git
git push -u origin master
6.备份设置
# 备份流程:
1.备份操作,修改数据库配置,添加备份目录,执行备份命令
2.恢复,关闭一些服务,防止用户在进行写入数据,恢复,重启gitlab服务
6-1.备份操作
1.修改备份的配置路径
vim /etc/gitlab/gitlab.rb
gitlab_rails['backup_path'] = "/gitlab_backup/" # 备份的目录,需要创建
gitlab_rails['backup_keep_time'] = 604800 # 保留备份的时间戳
2.重新读取配置
gitlab-ctl reconfigure
3.给配置目录设置权限
chown git.git /gitlab_backup
4.开始备份
gitlab-rake gitlab:backup:create # 手动备份
0 2 * * * /usr/bin/gitlab-rake gitlab:backup:create &>/dev/null # 定时备份
6-2.恢复备份
1.停止相关的服务
sudo gitlab-ctl stop unicorn
sudo gitlab-ctl stop sidekiq
sudo gitlab-ctl stop nginx
gitlab-ctl status # 查看状态
2.进行恢复备份
gitlab-rake gitlab:backup:restore BACKUP=备份文件名称 # 会读取备份目录下的你指定的文件名
# 文件路径:/gitlab_backup/1751812435_2025_07_06_12.0.3_gitlab_backup
gitlab-rake gitlab:backup:restore BACKUP=/gitlab_backup/1751812435_2025_07_06_12.0.3 # 不要加 _gitlab_backup 这个后缀,系统会自动加
在备份恢复过程中,会提示的信息:
1.提示需要先删除原来库表,在进行恢复
2.此任务现在将重建authorized_keys 文件。您将丢失authorized_keys 文件中存储的所有数据。
3.重启并且检查
sudo gitlab-ctl restart
sudo gitlab-rake gitlab:check SANITIZE=true