Git 与 GitLab、Jenkins 自动化部署实战指南
git使用[rootserver1 ~]# yum install -y git[rootserver1 ~]# mkdir demo[rootserver1 ~]# cd demo/[rootserver1 demo]# git inithint: Using master as the name for the initial branch. This default branch namehint: will change to main in Git 3.0. To configure the initial branch namehint: to use in all of your new repositories, which will suppress this warning,hint: call:hint:hint: git config --global init.defaultBranch namehint:hint: Names commonly chosen instead of master are main, trunk andhint: development. The just-created branch can be renamed via this command:hint:hint: git branch -m namehint:hint: Disable this message with git config set advice.defaultBranchName falseInitialized empty Git repository in /root/demo/.git/[rootserver1 demo]# git statusOn branch masterNo commits yetnothing to commit (create/copy files and use git add to track)[rootserver1 demo]# git status -s[rootserver1 demo]# echo test README.md[rootserver1 demo]#[rootserver1 demo]# lsREADME.md[rootserver1 demo]# git status -s?? README.md[rootserver1 demo]# git add README.md[rootserver1 demo]# git status -sA README.md[rootserver1 demo]# git config --global user.email user_uuwestos.org[rootserver1 demo]# git config --global user.name user_uu[rootserver1 demo]# git commit -m add README.md[master (root-commit) fc209da] add README.md1 file changed, 1 insertion()create mode 100644 README.md[rootserver1 demo]# echo hello README.md[rootserver1 demo]# git status -sM README.md[rootserver1 demo]# git add README.md[rootserver1 demo]# git status -sM README.md[rootserver1 demo]# echo world README.md[rootserver1 demo]# git status -sMM README.md[rootserver1 demo]# git commit -m v1[master 6c356af] v11 file changed, 1 insertion()[rootserver1 demo]# git status -sM README.md[rootserver1 demo]# git add .[rootserver1 demo]# git status -sM README.md[rootserver1 demo]# git commit -m v2[master 31e4e11] v21 file changed, 1 insertion()[rootserver1 demo]# git status -s查看日志[rootserver1 demo]# git reflog31e4e11 (HEAD - master) HEAD{0}: commit: v26c356af HEAD{1}: commit: v1fc209da HEAD{2}: commit (initial): add README.md更详细地查看[rootserver1 demo]# git log --oneline忽略隐藏文件[rootserver1 demo]# touch .a[rootserver1 demo]#[rootserver1 demo]# git status -s?? .a[rootserver1 demo]# vim .gitignore[rootserver1 demo]# cat .gitignore.*[rootserver1 demo]# git status -s[rootserver1 demo]# echo helloworld test.txt[rootserver1 demo]# git add test.txt[rootserver1 demo]# git commit -m add test.txt[master ac4b79d] add test.txt1 file changed, 1 insertion()create mode 100644 test.txt撤销文件修改[rootserver1 demo]# rm -f test.txt[rootserver1 demo]# git status -sD test.txt[rootserver1 demo]# git checkout -- test.txt取消暂存区文件[rootserver1 demo]# git rm test.txtrm test.txt[rootserver1 demo]# git status -sD test.txt[rootserver1 demo]# git reset HEAD test.txtUnstaged changes after reset:D test.txt[rootserver1 demo]# git status -sD test.txt[rootserver1 demo]# git checkout -- test.txt版本回退[rootserver1 demo]# git rm test.txtrm test.txt[rootserver1 demo]# git commit -m delete test.txt[master 7b3bb7e] delete test.txt1 file changed, 1 deletion(-)delete mode 100644 test.txt[rootserver1 demo]# git reflog7b3bb7e (HEAD - master) HEAD{0}: commit: delete test.txtac4b79d HEAD{1}: commit: add test.txt31e4e11 HEAD{2}: commit: v26c356af HEAD{3}: commit: v1fc209da HEAD{4}: commit (initial): add README.md[rootserver1 demo]# git reset --hard ac4b79dHEAD is now at ac4b79d add test.txt注意log不能查看而reflog中保存有记录[rootserver1 demo]# git log --onelineac4b79d (HEAD - master) add test.txt31e4e11 v26c356af v1fc209da add README.mdgitee远程代码仓库上传公钥[rootserver1 ~]# ssh-keygen[rootserver1 ~]# cd .ssh[rootserver1 .ssh]# lsid_rsa id_rsa.pub[rootserver1 .ssh]# cat id_rsa.pub测试连通性Rocky 虚拟机执行首次连接会提示主机指纹输入yes出现欢迎文字代表 ssh 认证成功[rootserver1 ~]# ssh -T gitgitee.com新建仓库按照gitee建议设置git全局[rootserver1 ~]# cd demo[rootserver1 demo]# git config --global user.name uu[rootserver1 demo]# git config --global user.email 17456376uu_2026user.noreply.gitee.com删除旧# origin git remote remove origin添加gitee远程# git remote add origin gitgitee.com:uu_2026/demo.git查看远程确认# git remote -v推送master分支# git push -u origin master测试克隆仓库[rootserver1 demo]# cd[rootserver1 ~]# rm -fr demo[rootserver1 ~]# git clone gitgitee.com:uu_2026/demo.gitCloning into demo...remote: Enumerating objects: 12, done.remote: Counting objects: 100% (12/12), done.remote: Compressing objects: 100% (5/5), done.remote: Total 12 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)Receiving objects: 100% (12/12), done.[rootserver1 ~]# cd demo[rootserver1 demo]# lsREADME.md test.txtgitlab部署rocky9虚拟机最小需求8G内存Index of /gitlab-ce/yum/el9/Packages/g/ | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror安装依赖[rootserver1 ~]# dnf install -y curl policycoreutils-python-utils openssh-server perl安装本地 gitlab rpm 包[rootserver1 ~]# dnf install -y gitlab-ce-18.11.12-ce.0.el9.x86_64.rpm修改 GitLab 配置文件 gitlab.rb[rootserver1 ~]# vim /etc/gitlab/gitlab.rbexternal_url http://192.168.164.171重新配置并初始化 gitLab[rootserver1 ~]# gitlab-ctl reconfigure查看初始 root 密码密码文件24 小时后自动删除[rootserver1 ~]# cat /etc/gitlab/initial_root_password查看 GitLab 所有组件状态所有服务全部显示run代表正常。[rootserver1 ~]# gitlab-ctl status浏览器访问 登录浏览器打开http://192.168.164.171登录后立刻修改 root 密码初始密码 24h 过期改成简体中文新建项目添加密钥测试连通性[rootserver1 ~]# ssh -T git192.168.164.171克隆项目[rootserver1 ~]# git clone git192.168.164.171:root/demo.gitCloning into 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 (from 0)Receiving objects: 100% (3/3), done.[rootserver1 ~]# lsdemo[rootserver1 ~]# cd demo/[rootserver1 demo]# echo www.westos.org index.html[rootserver1 demo]# lsREADME.md index.html[rootserver1 demo]# git add index.html[rootserver1 demo]# git commit -m add index.html[main eeb0cd4] add index.html1 file changed, 1 insertion()create mode 100644 index.html[rootserver1 demo]# git push -u origin mainEnumerating objects: 4, done.Counting objects: 100% (4/4), done.Delta compression using up to 4 threadsCompressing objects: 100% (2/2), done.Writing objects: 100% (3/3), 305 bytes | 305.00 KiB/s, done.Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)To 192.168.164.171:root/demo.git8785cab..eeb0cd4 main - mainbranch main set up to track origin/main.jenkins部署官网Linux注意另开一台虚拟机[rootserver1 ~]# dnf install java-21-openjdk-devel -y[rootserver1 ~]# yum install -y fontconfig[rootserver1 ~]# lsjenkins-2.580.1-1.noarch.rpm[rootserver1 ~]# rpm -ivh jenkins-2.580.1-1.noarch.rpmwarning: jenkins-2.580.1-1.noarch.rpm: Header V4 RSA/SHA512 Signature, key ID 14abfc68: NOKEYVerifying... ################################# [100%]Preparing... ################################# [100%]Updating / installing...1:jenkins-2.580.1-1 ################################# [100%]启动服务[rootserver2 ~]# systemctl enable --now jenkins.serviceCreated symlink /etc/systemd/system/multi-user.target.wants/jenkins.service → /usr/lib/systemd/system/jenkins.service.[rootserver2 ~]# netstat -antlp|grep :8080tcp6 0 0 :::8080 :::* LISTEN 12904/java登录192.168.164.172:8080[rootserver2 ~]# cat /var/lib/jenkins/secrets/initialAdminPassworde5e158591df04549adbefb247a3243e7替换国内插件源cd /var/lib/jenkins# 全局替换下载地址把国外地址换成清华镜像sed -i s|https://updates.jenkins.io/download|https://mirrors.tuna.tsinghua.edu.cn/jenkins|g updates/default.json# 重启jenkins生效systemctl restart jenkins安装推荐插件无需新建用户直接使用admin账户配置修改密码新建项目# dnf install git -y# ssh-keygen[rootserver2 ~]# cat /etc/password[rootserver2 ~]# usermod -s /bin/bash jenkins[rootserver2 ~]# su - jenkins[jenkinsserver2 ~]$ pwd/var/lib/jenkins[jenkinsserver2 ~]$ ssh-keygen[jenkinsserver2 ~]$ cd .ssh/[jenkinsserver2 .ssh]$ lsid_rsa id_rsa.pub[jenkinsserver2 .ssh]$ cat id_rsa.pub将公钥上传到gitlab私钥上传到jenkins[rootserver2 ~]# vim /etc/ssh/ssh_configInclude /etc/ssh/ssh_config.d/*.confHost *StrictHostKeyChecking no查看控制台输出安装插件Gitlab设置项目Triggers注意URL用于gitlab中的URL生成Secret token用于gitlab中的secret令牌设置项目中的webhooks打开webhooks出站请求测试推送返回绿色200通信成功触发自动构建自动化构建docker镜像在server2上安装docker-ce[rootserver2 ~]# cd /etc/yum.repos.d/[rootserver2 yum.repos.d]# vim /etc/yum.repos.d/docker.repo[docker]namedocker-cebaseurlhttps://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/rhel/9/x86_64/stable/gpgcheck0[rootserver2 yum.repos.d]# dnf install -y docker-ce修改内核参数[rootserver2 ~]# vim /etc/sysctl.d/docker.confnet.bridge.bridge-nf-call-iptables 1net.bridge.bridge-nf-call-ip6tables 1net.ipv4.ip_forward 1[rootserver2 ~]# sysctl --system[rootserver2 ~]# systemctl enable --now docker配置docker默认仓库[rootserver2 ~]# vim /etc/docker/daemon.json{registry-mirrors: [https://reg.westos.org]}[rootserver2 ~]# systemctl restart docker拷贝仓库证书[rootdocker1 ~]# cd docker[rootdocker1 docker]# scp -r certs.d/ 192.168.164.172:/etc/docker/[rootserver2 ~]# ls /etc/docker/certs.d/reg.westos.org/ca.crt/etc/docker/certs.d/reg.westos.org/ca.crt注意添加解析登录私有harbor仓库[rootserver2]# docker login reg.westos.org测试[rootserver2 ~]# docker pull reg.westos.org/nginx/nginx:1.29安装CloudBees Docker Build and Publish插件配置项目构建注意取消勾选Force Pull在server1上提交Dockerfile[rootserver1 ~]# cd demo[rootserver1 demo]# vim DockerfileFROM nginxCOPY index.html /usr/share/nginx/html[rootserver1 demo]# git status -s?? Dockerfile[rootserver1 demo]# git add Dockerfile[rootserver1 demo]# git commit -m add Dockerfile[main a1d22b2] add Dockerfile1 file changed, 3 insertions()create mode 100644 Dockerfile[rootserver1 demo]# git push -u origin main此时gitlab会主动触发jenkins构建任务观察jenkins的任务输出注意这是报错权限不足将jenkins系统用户加入docker组即可[rootserver2 ~]# usermod -aG docker jenkins[rootserver2 ~]# systemctl restart jenkins[rootserver2 ~]# id jenkinsuid993(jenkins) gid993(jenkins) groups993(jenkins),992(docker)通过ssh插件交付任务在server3上安装docker-ce[rootserver3 ~]# cd /etc/yum.repos.d/[rootserver3 yum.repos.d]# vim /etc/yum.repos.d/docker.repo[docker]namedocker-cebaseurlhttps://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/rhel/9/x86_64/stable/gpgcheck0[rootserver3 yum.repos.d]# dnf install -y docker-ce修改内核参数[rootserver3 ~]# vim /etc/sysctl.d/docker.confnet.bridge.bridge-nf-call-iptables 1net.bridge.bridge-nf-call-ip6tables 1net.ipv4.ip_forward 1[rootserver3 ~]# sysctl --system[rootserver3 ~]# systemctl enable --now docker配置docker默认仓库[rootserver3 ~]# vim /etc/docker/daemon.json{registry-mirrors: [https://reg.westos.org]}[rootserver3 ~]# systemctl restart docker拷贝仓库证书[rootdocker1 ~]# cd docker[rootdocker1 docker]# scp -r certs.d/ 192.168.164.173:/etc/docker/[rootserver3 ~]# ls /etc/docker/certs.d/reg.westos.org/ca.crt/etc/docker/certs.d/reg.westos.org/ca.crtjenkins安装ssh插件进入系统配置添加ssh主机新建docker_test项目构建后控制台查看输出安装RABC插件基于角色的访问控制Jenkins 这个插件名字就叫Role-based Authorization Strategy不直接给用户分配权限先定义角色、给角色分配权限再把用户加入角色。修改默认授权策略新建测试用户新建角色管理用户登入用户uu测试只有read权限jenkins结合ansible参数化构建server2上安装ansible新建gitlab项目克隆项目[rootserver1 ~]# git clone git192.168.164.171:root/playbook.gitCloning into playbook...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 (from 0)Receiving objects: 100% (3/3), done.[rootserver1 ~]# cd playbook/[rootserver1 playbook]# vim ansible.cfg[defaults]command_warningsFalseremote_userdevops[privilege_escalation]becomeTruebecome_methodsudobecome_userrootbecome_ask_passFalse[rootserver1 inventory]# vim test[test]192.168.164.173 http_port8000[rootserver1 inventory]# vim prod[prod]192.168.164.174 http_port8080[rootserver1 inventory]# cd ..[rootserver1 playbook]# vim playbook.yaml---- hosts: alltasks:- name: install the latest version of Apacheyum:name: httpdstate: latest- name: configure apachetemplate:src: httpd.conf.j2dest: /etc/httpd/conf/httpd.confnotify: restart apache- name: Start service httpd, if not startedservice:name: httpdstate: startedenabled: yeshandlers:- name: restart apacheservice:name: httpdstate: restarted[rootserver1 playbook]# yum install -y httpd[rootserver1 playbook]# cp /etc/httpd/conf/httpd.conf .[rootserver1 playbook]# mv httpd.conf httpd.conf.j2[rootserver1 playbook]# vim httpd.conf.j2Listen {{ http_port }}推送项目[rootserver1 playbook]# git add .[rootserver1 playbook]# git status -sA ansible.cfgA httpd.conf.j2A inventory/prodA inventory/testA playbook.yaml[rootserver1 playbook]# git commit -m add playbook.yaml[main 8060206] add playbook.yaml5 files changed, 400 insertions()create mode 100644 ansible.cfgcreate mode 100644 httpd.conf.j2create mode 100644 inventory/prodcreate mode 100644 inventory/testcreate mode 100644 playbook.yaml[rootserver1 playbook]# git push -u origin mainEnumerating objects: 9, done.Counting objects: 100% (9/9), done.Delta compression using up to 4 threadsCompressing objects: 100% (6/6), done.Writing objects: 100% (8/8), 5.38 KiB | 5.38 MiB/s, done.Total 8 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)To 192.168.164.171:root/playbook.git1449385..8060206 main - mainbranch main set up to track origin/main.jenkins新建项目playbookGeneral源码管理Build Steps选择参数构建

相关新闻

前端安全之王:XSS攻击原理、防御与实战排查

前端安全之王:XSS攻击原理、防御与实战排查

1. 从一个真实场景认识XSS:它凭什么被称为"前端安全之王"1.1 一个让我通宵的线上事故XSS漏洞攻击,跨站脚本攻击,这两个词放在一起,每次看到都会让我想起几年前那次差点让我彻夜失眠的生产事故。当时我负责一个To B的管理…

2026/10/18 11:09:26 阅读更多 →
爸妈也开始需要远程帮手了!?

爸妈也开始需要远程帮手了!?

以前总觉得,电脑、手机、各种软件这些东西是我们年轻人的世界。现在再看看,好像早就不是了。线上挂号、移动支付、视频通话、智能电视、各种智能设备……现在很多老一辈人的生活,也已经和一堆电子设备绑在一起了。这其实挺有意思的。以前是人…

2026/10/17 7:29:10 阅读更多 →
本地RAG系统实战:基于LangChain、bge-m3与Chroma搭建离线知识库问答

本地RAG系统实战:基于LangChain、bge-m3与Chroma搭建离线知识库问答

做本地RAG这件事,我是被一个很朴素的问题逼上路的:团队里的产品文档、项目记录、技术方案散落在各个目录里,想找一个半年前的结论,翻聊天记录和共享盘翻到怀疑人生。数据传到在线问答平台又始终绕不开隐私这一关,于是决…

2026/10/17 7:29:10 阅读更多 →

最新新闻

Flink实时计算三要素:Window、State与Checkpoint深度解析

Flink实时计算三要素:Window、State与Checkpoint深度解析

做实时计算绕不开这几个词:Window、State、Checkpoint。不管你是刚接触Flink,还是已经写了一段时间作业,总会遇到数据算不准、重启后状态丢了、窗口边界对不齐这类问题。我见过很多新手一上来就写业务代码,结果窗口和状态混在一起…

2026/10/18 11:32:06 阅读更多 →
YOLOv12即插即用模块化改进:注意力机制与跨尺度融合实战

YOLOv12即插即用模块化改进:注意力机制与跨尺度融合实战

1. 模块即插即用的整体设计思路1.1 为什么我坚持用模块替换而不是重构整个网络YOLOv12 的改进工作做到第三部分,先说一下我的总体判断:如果你不是做学术研究、不是想发论文,而是手上有一个实际项目要落地,最好的做法不是把网络结构…

2026/10/18 11:32:06 阅读更多 →
AI信息源清单与100美元低成本训练:一份可落地的技术路径指南

AI信息源清单与100美元低成本训练:一份可落地的技术路径指南

最近在 GitHub 上扒到一份挺有意思的开源收藏:92 个 AI 信息源被整理成一份清单,论文、开源仓库、Newsletter、播客、社区讨论全都收进去了。我第一次刷完这份清单的感觉是“这也太干了”,但真正用了一段时间后,我意识到值钱的不是…

2026/10/18 11:32:06 阅读更多 →
高校统一身份认证系统设计:CAS单点登录与安全实现指南

高校统一身份认证系统设计:CAS单点登录与安全实现指南

1. 为什么要做高校统一身份认证前阵子有个A同学抱着毕设题目来问我:“Java写一个高校统一身份认证系统,到底怎么做才是对的?”我一看题目就明白了,这几乎是每届计算机毕设的常客。做的人多,但真正把“统一身份认证”这…

2026/10/18 11:32:06 阅读更多 →
Java实现TRC20收款系统:从区块扫描到幂等回调的完整实践

Java实现TRC20收款系统:从区块扫描到幂等回调的完整实践

简介:这是一套基于Java开发的TRC20收款系统完整源码包,面向Java后端开发者与区块链应用集成人员,可用于快速搭建支持USDT(TRC20)收款的业务平台。资源共377个文件,压缩包仅6.15MB,结构清晰&…

2026/10/18 11:32:06 阅读更多 →
LangChain SQL Agent实战:构建企业级自然语言查数助手

LangChain SQL Agent实战:构建企业级自然语言查数助手

说实话,直到今天,仍然有大量团队在“让大模型直接写SQL”这件事上反复踩坑。裸调大模型接口,让它根据一句“帮我查一下上个月华东区哪些客户的回款逾期了”生成SQL,然后把结果丢给用户——你很快会发现几类问题:生成的…

2026/10/18 11:31:06 阅读更多 →

日新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 0:55:02 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 14:23:36 阅读更多 →