Git原理与用法系统总结
目录
- Reference
- 前言
- 版本控制系统
- Git的诞生
- 配置Git
- 配置用户名和邮件
- 配置颜色
- 配置`.gitignore`文件
- Git的基础用法
- 初始化仓库
- 克隆现有的仓库
- 添加暂存文件
- 提交变动到仓库
- 比较变动
- 查看日志
- Git回退
- Git重置
- 暂存区
- Git版本管理
- 重新提交
- 取消暂存
- 撤销对文件的修改
- Git分支
- Git分支的优势
- Git的数据结构
- 分支本质
- 基础指令
- 保留分支历史
- 分支的应用策略
- 开发策略
- bug分支
- feature分支
- 解决冲突
- Git多人协作
- 远程仓库
- 推送分支
- 抓取分支
- git rebase变基
- Git标签
- 标签的意义
- 创建标签
- 删除标签
- 推送标签到远程
Reference
简介 - Git教程 - 廖雪峰的官方网站 (liaoxuefeng.com)
前言
为什么突然对Git这么感兴趣?可能是因为在一次面试中,被问到了一个我答不上来的Git相关问题,那一刻我觉得,这技术债得还一还了。
用了这么久的GitHub和Gitee,我才意识到我对Git的理解还只是停留在表层。每天的push和pull,似乎成了例行公事,却很少深入思考它们背后的原理。
为什么要这么深入地研究Git?真相是,不论你是在日常开发中还是在技术面试中,一旦展示出对Git原理和操作的娴熟掌握,总能让你鹤立鸡群。想想看,当别人还在用图形界面点来点去时,你已经在终端里飞速敲出命令,这不仅仅是效率的提升,更是一种极客精神的体现。
而学习Git的过程,确实也让我发现,这不仅仅是一项技术,更像是一门艺术🎨,什么样的天才能够设计出这么巧妙的工具?原来是Linus啊,那没事了😇
版本控制系统
版本控制是一种记录一个或若干文件内容变化,以便将来查阅特定版本修订情况的系统。 有了它你就可以将选定的文件回溯到之前的状态,甚至将整个项目都回退到过去某个时间点的状态,你可以比较文件的变化细节,查出最后是谁修改了哪个地方,从而找出导致怪异问题出现的原因,又是谁在何时报告了某个功能缺陷等等。
版本控制系统发展可以分为三个阶段:
- 本地版本控制系统
- 集中式版本控制系统
- 分布式版本控制系统
Git属于分布式版本控制系统,客户端并不只提取最新版本的文件快照, 而是把代码仓库完整地镜像下来,包括完整的历史记录。 这么一来,任何一处协同工作用的服务器发生故障,事后都可以用任何一个镜像出来的本地仓库恢复。 因为每一次的克隆操作,实际上都是一次对代码仓库的完整备份。

Git的诞生
到 2002 年,Linux 系统已经发展了十年了,代码库之大让 Linus 很难继续通过手工方式管理了,整个项目组开始启用一个专有的分布式版本控制系统 BitKeeper 来管理和维护代码,BitKeeper 的东家 BitMover 公司也免费授权 Linux 社区使用这个版本控制系统。后来 BitMover 公司发现社区有人试图破解 BitKeeper 的协议,于是 BitMover 公司收了回 Linux 社区的免费使用权。
所以Linus 花了两周时间自己用 C 写了一个分布式版本控制系统,也就是 Git。
不由得佩服人家的灵感和效率🫢
配置Git
配置用户名和邮件
安装完 Git 之后,要做的第一件事就是设置你的用户名和邮件地址。 这一点很重要,因为每一个 Git 提交都会使用这些信息,它们会写入到你的每一次提交中,不可更改:
$ git config --global user.name "R1ck"
$ git config --global user.email xxx@gmail.com
配置颜色
下面的命令让 Git 显示颜色,会让命令输出看起来更醒目:
$ git config --global color.ui true
配置.gitignore文件
有些时候,你必须把某些文件放到 Git 工作目录中,但又不能提交它们,比如保存了数据库密码的配置文件等等,就可以使用忽略特殊文件 .gitignore 来很方便的解决这个问题。
各种现成的种配置文件: https://github.com/github/gitignore
下面是一些例子
假设你在 Windows 下进行 Python 开发,Windows 会自动在有图片的目录下生成隐藏的缩略图文件,如果有自定义目录,目录下就会有Desktop.ini文件,因此你需要忽略 Windows 自动生成的垃圾文件:
# Windows:
Thumbs.db
ehthumbs.db
Desktop.ini
Python编译产生的.pyc、.pyo、dist等文件或目录也可以被忽略掉
# Python:
*.py[cod]
*.so
*.egg
*.egg-info
dist
build
当然我们也可以编写例外规则,例如避免.*这个规则把.gitignore也排除了
# 排除所有.开头的隐藏文件:
.*
# 排除所有.class文件:
*.class# 不排除.gitignore和App.class:
!.gitignore
!App.class
Git的基础用法
初始化仓库
通过git init命令可以把目录变成 Git 可以管理的仓库:
$ git init
同时在当前目录下多了一个.git的目录,这个目录是 Git 来跟踪管理版本库的
克隆现有的仓库
当你执行 git clone 命令的时候,默认配置下远程 Git 仓库中的每一个文件的每一个版本都将被拉取下来。
克隆仓库的命令是 git clone <url>
如果你想在克隆远程仓库的时候,自定义本地仓库的名字,可以通过额外的参数指定新的目录名:
例如下面这条命令,把目标目录名变成了mydocs
$ git clone https://github.com/xxx/xxx mydocs
添加暂存文件
用命令git add可以告诉 Git,把指定文件添加到暂存区域
$ git add readme.txt
我们可以通过git add .将当前目录下的所有文件添加到暂存区域
提交变动到仓库
用命令git commit告诉 Git,把文件提交到仓库:
$ git commit -m "wrote a readme file"
-m后面输入的是本次提交的说明,最好是有意义的
我们可以通过git add命令分多次暂存不同的文件,然后通过git commit一次性整合提交到仓库
在git commit之前,git add并不会向仓库中添加对象
git commit只会提交所有暂存区中的文件
比较变动
git status命令可以让我们时刻掌握仓库当前的状态,显示仓库中距离上一次提交后被修改过的文件
而使用git diff 文件名则可以查看该文件中的具体修改
一般来说我们在add完所有文件后,可以通过git status来确保仓库的状态、查看是否有修改错的文件
查看日志
git log会显示出每一个commit版本、作者以及说明
而git log --pretty=oneline则会显示得更简洁和整齐,只包含commit版本和说明
Git回退
在 Git 中,用HEAD表示当前版本,也就是最新的提交
上一个版本就是HEAD,上上一个版本就是HEAD^
往上n个版本可以写作HEAD~n
当我们希望将版本回退到上一个版本,则可以使用git reset命令:
$ git reset --hard HEAD^
Git重置
git reflog用来记录我们的每一次命令
当我们不希望再回退到上一个版本时,可以通过git reflog命令找到回退之前的的commit id,并使用git reset --hard 具体的id来恢复

暂存区

工作区有一个隐藏目录.git,其中存放了暂存区stage,以及版本库
git add命令实际上就是把要提交的所有修改放到暂存区(Stage),然后,执行git commit就可以一次性把暂存区的所有修改提交到分支。
Git版本管理
重新提交
如果你在最后一次提交后意识到忘记添加了某些更改,git commit --amend 允许你修正这个错误。这个命令会重新提交暂存区中的文件,更新上一次的提交。
新的提交将代替之前提交的内容
旧有的提交在git log分支提交历史中会被删除,不过仍然可以在 git reflog 中找到,方便撤销
取消暂存
git reset HEAD <file>可以用于取消暂存,将上一次通过add提交到暂存区的该文件撤销,这对你想进行独立的commit提交非常有用
撤销对文件的修改
git checkout -- <file>会将对文件在本地的任何修改都消除掉,即使该文件的修改还没有提交到暂存区

我们可以理解为该操作是将版本库中的对应文件覆盖到本地
所以该命令也可以被用于恢复本地被错删的文件
Git分支
Git分支的优势
分支用于将工作从开发主线上分离开来,以免影响开发主线。在很多版本控制系统中,这是一个略微低效的过程——常常需要完全创建一个源代码目录的副本。
Git 处理分支的方式可谓是难以置信的轻量,创建新分支这一操作几乎能在瞬间完成,并且在不同分支之间的切换操作也是一样便捷。 与许多其它版本控制系统不同,Git 鼓励在工作流程中频繁地使用分支与合并,哪怕一天之内进行许多次。
Git的数据结构
Git在处理分支时之所以能做到轻量,与保存数据的方式有关。
在进行add暂存操作时,会为每一个文件计算校验和。然后会把当前版本的文件快照会以blob对象的形式保存到 Git 仓库中,而校验和则加入到暂存区域等待提交。
在进行commit提交操作时,Git会为每一个子目录生成树对象,该对象负责记录目录结构,并保存着指向各文件快照
(blob对象)的索引。

接下来生成一个提交对象(commit object),并保存指向根目录树对象的指针,当然,该提交对象还包含了作者的姓名和邮箱、提交时输入的信息以及指向它的父对象的指针。

这个父对象,指的就是上一次提交时产生的提交对象。下面这张图会比较直观,每一次提交产生的提交对象串成了一个链表,或者说一条时间线。

分支本质
Git 的分支,其实本质上仅仅是指向提交对象的可变指针。
Git 的默认分支名字是 master,master分支会在每次提交时自动向前移动。
一开始的时候,master分支是一条线,Git 用master指向最新的提交,再用HEAD指向master,就能确定当前分支,以及当前分支的提交点
当我们创建新的分支,例如v1.0时,Git 新建了一个指针叫v1.0,指向master相同的提交,再把HEAD指向v1.0,就表示当前分支在v1.0上

此时我们也可以看出,Git在创建分支时并不需要拷贝原本分支的文件,仅仅是添加了一个指针,工作区的文件没有任何变化
删除分支时,我们也只需要将指针给删掉就行
如果我们不考虑复杂的合并冲突问题,当两个分支在一条时间线上时,合并这两个分支要做的仅仅是将分支指针沿时间线移动
基础指令
我的git中的默认分支从master改为了main,所以后文中的默认分支均用main指代
我们可以使用git branch 分支名来创建分支
并使用git checkout 分支名来切换到指定分支
或者在checkout命令后使用-b参数,同时执行创建和切换
git checkout -b dev

使用git branch我们还能查看一共存在哪些分支,以及当前处在哪个分支,当前分支前面会标一个*号
我们在dev分支上进行文件修改后,如果想将dev上的修改合并到main分支,可以先切回main分支,并使用git merge指令
git merge指令用于合并指定分支到当前分支
git checkout main
git merge dev

合并完后如果不再需要dev分支,在git branch后加上-d参数即可删除指定分支
git branch -d dev

当然,如果我们容易将git checkout 分支名(切换分支)和git checkout -- <file>(撤销修改)弄混,也可以用git switch来切换分支
git switch也可以通过-c参数来同时完成创建和切换的操作

保留分支历史
当我们直接用Fast forward模式合并分支后,如果删除分支,则会丢掉分支信息
我们可以通过--no-ff参数,在合并时生成一个新的commit
这样相当于被合并的分支的指针会留在该分支的最后一个commit,而Head则会执行新的commit
此时当我们使用git log --graph展示分支和合并历史时,就能直观地看到时间线上有一个合并的点

分支的应用策略
开发策略
再日常开发中,分支管理的基本原则如下:
-
master分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活;
-
开发和更新代码都在dev分支上进行,也就是说,dev分支是不稳定的,到某个时候,比如1.0版本发布时,再把dev分支合并到master上,并在master分支发布1.0版本;
-
团队成员每个人都可以从dev分支上创建属于自己的分支,并将自己的修改合并到dev分支上。

bug分支
当我们需要修复bug时,也可以开一个临时的分支,修复完在合并并删除临时分支
当然如果手头分支的开发还没做完,我们可以使用git stash将当前的工作进度存起来
等我们在主分支修完bug,可以再回到自己的分支
使用git stash apply可以将工作区恢复到之前保存的工作进度,当然stash里的内容还需要使用git stash drop来删除;或者使用git stash pop,恢复的同时把stash内容也删了
而如果我们想将主分支修复的bug补丁复制到当前分支(通常自己的分支也存在同样的bug),那么可以使用git cherry-pick bug分支名,将修bug所做的补丁复制到当前分支,而不需要merge整个主分支
当然我们也可以在自己的分支修完bug再将改动复制到主分支
feature分支
添加新功能时,也可以新建一个feature分支
如果这个功能分支开发到一半,不想要了,可以使用git branch -D强制删除分支,而不需要像-d参数只能在合并后删除分支
解决冲突

在工作中,经常会出现团队成员与自己修改了dev分支的同一处文件,并且改动不一致。

而且如果此时团队成员开发更快,已经提前合并到dev分支上,那么自己再进行合并时就会出现冲突

此时我们需要手动解决冲突后才能提交
使用git status查看出现冲突的文件

查看具体冲突文件,会发现git已经自动将冲突位置标出,以及冲突分支间的差异

修改完冲突即可使用commit提交并合并

当我们使用git cherry-pick命令复制提交时,也可能出现代码冲突
当我们解决完冲突,可以使用--continue参数让Cherry pick 过程继续执行
git cherry-pick --continue
Git多人协作
远程仓库
我们使用到最多的Gir远程仓库即github,它不仅仅是开源社区,也通过远程仓库功能连接起不同团队成员的本地Git,让团队协作变得方便
一般来说远程仓库的默认名称是origin
使用git remote -v可以查看自己绑定的远程仓库的详细信息
推送分支
推送分支使用git push指令,先指定远程分支,然后是被merged的本地分支
例如git push origin master
抓取分支
当我们进行推送时,如果发现远程仓库已经有最新提交,且存在冲突,则需要先用git pull把最新的提交抓取下来,在本地合并
在本地解决完冲突,再使用git push origin <branch-name>推送
即可成功
git rebase变基
git base能通过挪动提交的位置,使得分叉的提交历史整理成一条直线
Git标签
标签的意义
发布一个版本时,通常先在版本库中打一个标签(tag)
标签与分支类似,就是指向某个commit的指针
而标签的引入则是给某个commit设置一个有意义的别名,方便人们根据版本快速查询commit
创建标签
首先切换到要打标签的分支上
使用git tag <name>就可以打一个新标签,默认该标签是打在最新提交的commit上的
当然一个可以在最后指定commit id,将标签打在指定commit上
例如
git tag v0.9 fb8b190
用命令git tag可以查看所有标签
删除标签
使用-d参数可以删除指定标签
git tag -d <name>
推送标签到远程
要将特定的标签推送到远程仓库,使用命令 git push origin <tagname>。如果你想一次性推送所有本地标签,可以使用 git push origin --tags。
相关文章:
Git原理与用法系统总结
目录 Reference前言版本控制系统Git的诞生配置Git配置用户名和邮件配置颜色配置.gitignore文件 Git的基础用法初始化仓库克隆现有的仓库添加暂存文件提交变动到仓库比较变动查看日志Git回退Git重置暂存区 Git版本管理重新提交取消暂存撤销对文件的修改 Git分支Git分支的优势Git…...
连载|浅谈红队中的权限维持(六)-Linux 主机后门与Linux 隐藏文件
本文来源无问社区,更多实战内容,渗透思路可前往查看http://www.wwlib.cn/index.php/artread/artid/11584.html 0x01 Linux 主机后门 1、添加用户 一句话添加用户 useradd test;echo -e "123456n123456n" |passwd test 或者使用 openssl …...
tomato-靶机渗透
tomato-靶机 一、安装靶机环境 下载双击.ova文件,写文件名路径导入 打开虚拟机用NAT模式 编辑–>虚拟网络编辑器查看IP段 二、信息收集 1.御剑端口扫描查找该虚拟机的IP 访问网站 扫目录 dirb http://192.168.30.130 收集到目录 /server-status /antibot_im…...
git的配置使用
第三周 Tursday 早 git日志的安装使用 [rootweb ~]# yum -y install git.x86_64 //安装软件包 [rootweb ~]# rpm -ql git //查看git的包 [rootweb ~]# mkdir /yy000 //创建新目录 [rootweb ~]# cd /yy000/ [rootweb yy000]# git init //将当前目录做为仓库…...
【1.0】drf初识
【1.0】drf初识 【一】前后端开发模式 【1】前后端混合开发 【示例】flask混合、django混合【案例】bbs项目 模板:dtl语法(django template language)模板语法 {{}} /{% %}后端渲染 qs对象–遍历循环到模板中–使用模板语法渲染渲染完成后 得到纯粹的…...
SparkSQL---编程模型的操作,数据加载与落地及自定义函数的使用
一、SparkSQL编程模型的创建与转化 1、DataFrame的构建 people.txt数据: 1 zhangsan 20 2 lisi 29 3 wangwu 25 4 zhaoliu 30 5 tianqi 35 6 kobe 40 people.json数据:在SparkSQL—简介及RDD V.S DataFrame V.S Dataset编程模型详解里 1、从Spark数据…...
文件解析漏洞--IIS--Vulhub
文件解析漏洞 一、IIS解析漏洞 用windowserver2003安装IIS测试 1.1 IIS6.X 方法一:目录解析 在网站下建立文件夹的名字为.asp/.asa的文件夹,其目录内的任何扩展名的文件都被IIS当作asp文件来解析并执行。 1.txt文件里是asp文件的语法查看当前时间 方…...
你知道缓存的这个问题到底把多少程序员坑惨了吗?
在现代系统中,缓存可以极大地提升性能,减少数据库的压力。 然而,一旦缓存和数据库的数据不一致,就会引发各种诡异的问题。 我们来看看几种常见的解决缓存与数据库不一致的方案,每种方案都有各自的优缺点 先更新缓存&…...
飞创直线模组桁架机械手优势及应用领域
随着工业自动化和智能制造的发展,直线模组桁架机械手极大地减轻了人类的体力劳动负担,在危险性、重复性高的作业环境中展现出了非凡的替代能力,引领着工业生产向自动化、智能化方向迈进。 一、飞创直线模组桁架机械手优势 飞创直线模组桁架…...
TongHttpServer 简介
1. 概述 随着网络技术的飞速发展,高并发大用户场景越来越普遍,单一应用服务节点已经不能满足并发需求,为了提高整个系统可靠性,扩展性,吞吐率,通常将多个应用服务器通过硬负载/软负载组成集群,负载均衡器根据不同负载算法将请求分发到各个应用服务器节点。 Tong…...
回溯法---组合总和
题目: 给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。 candidates 中的 同一个 数字可以 无限…...
将Android Library项目发布到JitPack仓库
将项目代码导入Github 1.将本地项目目录初始化为 Git 仓库。 默认情况下,初始分支称为 main; 如果使用 Git 2.28.0 或更高版本,则可以使用 -b 设置默认分支的名称。 git init -b main 如果使用 Git 2.27.1 或更低版本,则可以使用 git symbo…...
JAVAWeb实战(后端篇)
因为前后端代码内容过多,这篇只写后端的代码,前端的在另一篇写 项目实战一: 1.创建数据库,表等数据 创建数据库 create database schedule_system 创建表,并添加内容 SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS 0;-- ---------…...
【vs】实用调试技巧——学会写优秀的代码!
🦄个人主页:小米里的大麦-CSDN博客 🎏所属专栏:https://blog.csdn.net/huangcancan666/category_12718530.html ⚙️操作环境:Visual Studio 2022 目录 一、前言 二、什么是BUG? 三、调试是什么?有多重要? 一名优秀…...
数组声明方式
数组声明方式 一、 一维数组 元素数据类型[] 数组名; // 推荐元素数据类型 数组名[]; 二、 二维数组 元素数据类型[][] 数组名称; // 推荐元素数据类型 数组名称[][];元素数据类型[] 数组名称[]; 注: 对于第三种方式元素数据类型[] 数组名称[];,可…...
Docker中Docker网络-理解Docker0与自定义网络的使用示例
场景 CentOS7中Docker的安装与配置: CentOS7中Docker的安装与配置_centos docker sock-CSDN博客 在上面安装好Docker之后。 关于对Docker中默认docker0以及自定义网络的使用进行学习。 注: 博客:霸道流氓气质-CSDN博客 实现 理解dock…...
领域驱动大型结构之SYSTEM METAPHOR(系统隐喻)
在领域驱动设计(Domain-Driven Design, DDD)中,"System Metaphor" 是一种用于帮助开发团队和业务人员在理解和沟通系统时使用的概念模型。虽然 "System Metaphor" 并不是 DDD 的核心概念,但它在敏捷开发方法&…...
web前端开发一、VScode环境搭建
1、VScode安装live server插件,写完代码后,保存就会在浏览器自动更新,不需要再去浏览器点击刷新了 2、创建html文件 3、在文件中输入感叹号 ! 4、选择第一个,然后回车,就会自动输入html的标准程序 5、…...
DiAD代码use_checkpoint
目录 1、梯度检查点理解2、 torch.utils.checkpoint.checkpoint函数 1、梯度检查点理解 梯度检查点(Gradient Checkpointing)是一种深度学习优化技术,它的目的是减少在神经网络训练过程中的内存占用。在训练深度学习模型时,我们需…...
nginx出现Refused to apply inline style because it violates
Content Security Policy的错误。根据错误提示,nginx拒绝应用内联样式,因为它违反了内容安全策略(Content Security Policy)。内容安全策略是一种浏览器机制,用于防止潜在的安全漏洞,通过限制从外部来源加载…...
基于算法竞赛的c++编程(28)结构体的进阶应用
结构体的嵌套与复杂数据组织 在C中,结构体可以嵌套使用,形成更复杂的数据结构。例如,可以通过嵌套结构体描述多层级数据关系: struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...
Spark 之 入门讲解详细版(1)
1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室(Algorithms, Machines, and People Lab)开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目,8个月后成为Apache顶级项目,速度之快足见过人之处&…...
Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动
一、前言说明 在2011版本的gb28181协议中,拉取视频流只要求udp方式,从2016开始要求新增支持tcp被动和tcp主动两种方式,udp理论上会丢包的,所以实际使用过程可能会出现画面花屏的情况,而tcp肯定不丢包,起码…...
汇编常见指令
汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX(不访问内存)XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...
使用 SymPy 进行向量和矩阵的高级操作
在科学计算和工程领域,向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能,能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作,并通过具体…...
零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)
本期内容并不是很难,相信大家会学的很愉快,当然对于有后端基础的朋友来说,本期内容更加容易了解,当然没有基础的也别担心,本期内容会详细解释有关内容 本期用到的软件:yakit(因为经过之前好多期…...
云原生玩法三问:构建自定义开发环境
云原生玩法三问:构建自定义开发环境 引言 临时运维一个古董项目,无文档,无环境,无交接人,俗称三无。 运行设备的环境老,本地环境版本高,ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...
苹果AI眼镜:从“工具”到“社交姿态”的范式革命——重新定义AI交互入口的未来机会
在2025年的AI硬件浪潮中,苹果AI眼镜(Apple Glasses)正在引发一场关于“人机交互形态”的深度思考。它并非简单地替代AirPods或Apple Watch,而是开辟了一个全新的、日常可接受的AI入口。其核心价值不在于功能的堆叠,而在于如何通过形态设计打破社交壁垒,成为用户“全天佩戴…...
深入理解Optional:处理空指针异常
1. 使用Optional处理可能为空的集合 在Java开发中,集合判空是一个常见但容易出错的场景。传统方式虽然可行,但存在一些潜在问题: // 传统判空方式 if (!CollectionUtils.isEmpty(userInfoList)) {for (UserInfo userInfo : userInfoList) {…...
0x-3-Oracle 23 ai-sqlcl 25.1 集成安装-配置和优化
是不是受够了安装了oracle database之后sqlplus的简陋,无法删除无法上下翻页的苦恼。 可以安装readline和rlwrap插件的话,配置.bahs_profile后也能解决上下翻页这些,但是很多生产环境无法安装rpm包。 oracle提供了sqlcl免费许可,…...
