Skip to content

04 | Git 与 GitHub:版本管理与云端仓库

上一篇(03 服务端应用部署)把构建动作搬到了服务器:mvn package,Flask 要 pip install,服务器上多出源码、依赖、构建产物三套东西。这里藏着一个真问题:服务器上正在跑的这次构建,对应哪一份代码?

如果回答不了这个问题,回退、排查、复现都会变成“靠记忆猜”。痛点三:没有版本追踪——手动备份会被跳过、没有上下文、回退要重做一遍——在服务端部署场景下变得更加危险。

这个痛点在生产发布流程里的体现是:每一次变更的内容缺乏精确、不可篡改的物理锚点。你改了什么、什么时候改的、改坏了回哪个版本、服务器上那次构建对应哪次提交——这些关键的发布溯源信息散落在操作记忆里,没有被固化下来。

这一篇的解法分两步:本地用 Git 拍快照 + GitHub 把快照搬到云端。第一步解决"找不到对应版本",第二步解决"代码传不到服务器"。

:03 篇痛点三的解法

03 篇 提到服务器构建时手动备份 dist-20260713 的三个断点,Git 一次性补完:

断点手动备份Git
会被跳过改动小时直接覆盖git commit 是轻量操作,不会跳过
没有上下文只有日期每次 commit 附带修改人、时间、说明
回退要重做mv 目录 + 重启git revert / git checkout,秒级回退

核心能力:给每一次变更拍一张带上下文的快照(commit)。快照连成链,任何一次部署都能精确对应到链上的某一个节点。

Git 分布式协作与部署架构图

📐 静态信息图 Prompt 与 Mermaid 结构参考

Prompt:

text
极简手绘马克笔信息图,16:9 横版。主题为「Git:从本地快照到生产部署」:左上蓝色笔记本标注「开发者 A」「本地仓库」「C1 → C2」;左下蓝色笔记本标注「开发者 B」「本地仓库」「C1 → C3」;中间灰色云朵标注「GitHub 远程仓库」,云内是合并提交链「C1 → C2 → C3」,两条入云箭头标注 `git push`;右侧橙色服务器标注「生产服务器」,从云到服务器的箭头标注 `git pull`,服务器下方依次标注「拉取 C3」「构建并部署」。暖白背景、黑色线稿、留白充足,所有自然语言使用简体中文;无阴影、无渐变、无 3D 效果。
  • 产物路径:docs/public/images/img-git-github/diagram-git-distributed-collaboration-v2.png
  • 站点引用:https://media.xiaolin.fun/docs/img-git-github/diagram-git-distributed-collaboration-v2.png

Git:给变更拍快照

Git 是本地工具,不依赖 GitHub 也能完整使用。 它在你的电脑上管理版本历史,不需要联网、不需要注册账号。GitHub 是后面才加的一层——先把本地的 Git 用明白。

运维场景 × 命令

这不是通用 Git 教程,而是“运维拿 Git 干什么”对应的最小命令集:

运维场景命令说明
初始化项目版本管理git init把当前目录变成 Git 仓库
声明忽略文件(防误传依赖/密钥)创建 .gitignore写入 node_modules/venv/.env
改了配置 / 代码,先看看改了啥git status / git diffcommit 之前必看,确认改动范围
确认没问题,记录这次变更git add .git commit -m "说明"拍快照——这就是代码变更的一次精确锚定
出问题了,查“当时改了什么”git log --oneline + git diff A B事后排查的入口
出问题了,要回退git revert <commit>生成一次“反向 commit”,不丢历史
想回到某个历史版本看看git checkout <commit>临时切到旧版本,看完切回来

关键习惯与分支概念

  1. 养成第一习惯:新建项目第一步务必先创建 .gitignore,防止第三方依赖包(如 node_modules/venv/)和敏感配置文件(如 .env 密钥)误提交。
  2. 单主线模式即可:前期无需引入复杂的分支策略,保持在默认主分支 main 上顺着线性快照链向前推进即可。多分支与变基留到复杂协同场景。

快照链:比备份目录可靠在哪

备份目录只有“旧”和“新”两个状态,而 commit 历史是一条链:

text
A → B → C → D

每个节点都知道自己从哪里来,也能随时回到任意节点。想回退到 B,不需要手动 mv 目录,只需要告诉 Git“我要回到 B”即可。

这条链还解决了 02 篇提到的“版本不一致”问题——本地构建的 dist 对应哪次 commit、服务器上跑的又是哪次 commit,都有据可查。

Commit 信息:开发者最该写好的那一行

git init / add / push 都会变成肌肉记忆,唯独 commit 信息写什么,过去时常是一件伤脑筋的事——三个月后排查问题的人、接手代码的新同事、回溯事故的运维,先看的都是这一行。“update” / “fix bug” / “tmp” 这类含糊写法,会让历史变成“考古谜题”。

Conventional Commits:把 commit 信息结构化

Conventional Commits 是社区主流的 commit 格式规范:

text
<类型>[可选作用域]: <简短说明>

[可选正文]

[可选脚注]

日常高频使用的 4 个核心类型:

前缀用途典型示例
feat新增功能feat: 增加用户登录登出接口
fixBug 修复fix: 修复静态文件路径 404 问题
chore杂项变动(构建、依赖升级、配置调整)chore: 升级 vitepress 版本至 1.0
docs仅文档修改docs: 补充生产部署环境架构图

格式化的价值在于让 commit 信息变成可机读的结构化数据

  • CI/CD 自动化feat: 触发 minor 版本号、fix: 触发 patch 版本号、BREAKING CHANGEfeat!: / fix!: 触发 major。
  • CHANGELOG 自动生成:工具按类型分组输出变更摘要,无需人工整理。
  • 排查提速:扫一眼前缀就知道本次改动的性质,无需打开 diff。

AI 时代的新挑战:从“靠自觉”到“靠工程化治理”

过去写 commit 信息是开发者的“软素质”——靠自觉、靠 code review 提醒、靠团队规范约束。在 AI Agent 时代则升级为 靠工程化治理:自动提交拦截、Conventional Commits 强校验(commitlint)、自动信息填充、commit 质量门禁(pre-commit + 服务端分支保护)等议题本文暂不展开。

详见 《AI Agent 时代下重新审视 Git》

GitHub:让快照离开本地硬盘

Git 在本地管理版本——但本地硬盘坏了,历史一起没了。而且手动 scp 上传代码本身就是 02 篇的痛点。

scp 与 git pull 的发布方式对比图

📐 静态信息图 Prompt 与 Mermaid 结构参考

Prompt:

text
极简手绘马克笔信息图,16:9 横版。主题为「scp vs git pull:代码从本地到服务器的两种方式」:左侧橙色色块标注「02 篇方式:手动 scp」,含本机图标 → 「scp 命令(无历史、无版本)」→ 服务器图标(裸文件覆盖),从上到下用橙色箭头串联,路径下方标注「覆盖式、易出错、无版本」;右侧蓝色色块标注「04 篇方式:git pull + GitHub」,含本机图标 → 中间灰色云朵图标「GitHub 远程仓库(带历史 + commit 链)」→ 服务器图标(git pull → 精确 commit),从上到下用蓝色箭头串联,路径下方标注「快照式、可回退、有锚点」。所有自然语言使用简体中文;无阴影、无渐变、无 3D 效果。
  • 产物路径:docs/public/images/img-git-github/diagram-scp-vs-git-v2.png
  • 站点引用:https://media.xiaolin.fun/docs/img-git-github/diagram-scp-vs-git-v2.png

GitHub 解决两件事:

  1. 备份:本地仓库同步到云端,硬盘坏了历史还在。
  2. 传输:服务器通过 git clone / git pull 拿到代码,不需要 scp。

首次关联与推送

在使用 git push 推送到远程仓库前,需要确保本地已经完成了初始化并提交了至少一次 commit:

bash
# 1. 在本地项目根目录初始化并提交代码
git init
git add .
git commit -m "feat: initial commit"

# 2. 关联远程仓库(请将下面的地址替换为你自己的 GitHub 仓库 URL)
git remote add origin https://github.com/your-username/your-repo.git

# 3. 推送到远程主分支
git push -u origin main

之后三条核心命令:

命令方向作用
git push本地 → GitHub把本地新 commit 送到云端
git pullGitHub → 本地 / 服务器把云端新 commit 拉下来
git cloneGitHub → 任意机器首次把整个仓库(含历史)复制过来

有了 GitHub,02 篇的 scp 部署可以升级为:

bash
# 服务器上
git clone https://github.com/your-username/your-repo.git
cd your-repo
# 构建 + 部署……

每次更新,服务器上 git pull 就拿到最新代码——不再需要手动 scp。

TIP

生产服务器拉取守则严禁直接修改工作区文件。如果执行 git pull 提示 error: Your local changes to the following files would be overwritten by merge,说明服务器上存在未提交的临时修改。规范流程应保持服务器为纯净的只读拉取端,变更统一在开发端 commit 并 push 后,再在服务端拉取。

推荐用 SSH 协议:非对称密钥替代密码

HTTPS 协议每次推送都要输入用户名密码(或 Personal Access Token),CI/CD 场景下基本不可用。推荐改用 SSH 协议 + 非对称密钥:本地生成密钥对,把公钥交给 GitHub,之后推送用私钥签名、GitHub 用公钥验签——全程不传密码,CI 也能免密跑。

三步配好 SSH

  1. 本地生成密钥对

    bash
    ssh-keygen -t ed25519 -C "your_email@example.com"

    一路回车即可,会在 ~/.ssh/ 生成 id_ed25519(私钥)和 id_ed25519.pub(公钥)。

  2. 把公钥复制到 GitHub

    打开 ~/.ssh/id_ed25519.pub,复制全部内容。登录 GitHub → SettingsSSH and GPG keysNew SSH key,粘贴并保存。

  3. 验证连通性

    bash
    ssh -T git@github.com

    看到 Hi username! You've successfully authenticated... 即表示配置成功。

WARNING

私钥安全与权限排查

  1. 私钥千万不能泄漏:私钥(id_ed25519)留在本地和目标服务器,绝对不能提交到 Git 仓库,更不能公开发布。万一误推,应立刻在 GitHub 后台删除公钥并轮换新密钥。
  2. 权限过大报错:若连接时提示 Permissions 0644 for 'id_ed25519' are too openUNPROTECTED PRIVATE KEY FILE!,是因为私钥文件权限过于宽松,运行 chmod 600 ~/.ssh/id_ed25519 限制权限即可解决。

Git 在部署路径中的位置

03 篇确立的服务端部署范式:构建产物( / wheel + 依赖声明)→ 进程拉起 → 后台挂着 → 验证 + 排查

Git 是这条范式的前置能力——没有版本管理,部署无法可追溯:

  • 构建产物可追溯:每次 git commit 是产物的一次锚定——服务器上跑的是哪次 commit、有谁改了什么、出问题回哪个版本,都有据可查。
  • 部署可重现git checkout <commit> → 构建 → 部署,每一步都有精确锚点。
  • 回退变成重跑:出问题 → git revert 反向 commit → 重新跑一遍部署 → 回到上一个稳定状态。
  • 03 篇“没有版本追踪”痛点彻底解决:手动备份会被跳过、没有上下文、回退要重做——Git 一次性补完。

Git 不是“开发者的工具”,是服务端部署范式能运转的前提——没有版本管理,的输入只是模糊的临时代码;有了 Git,每次发布都绑定在 commit hash 锚定的精确快照上。

不只是开发者:Git 的适用范围

Git 在公众视野里几乎和“程序员”绑定——但这是职业视角的误读。Git 是面向所有人的版本管理工具,本质和 Word 的“修订模式”、Excel 的“修改记录”是同一类需求——只是做得更彻底、更通用、更可协作。它不挑职业,只挑内容形态:纯文本最擅长,二进制能存但有代价。

为什么特别适合纯文本

Git 的快照是按文件整体存的,但只有纯文本能让它发挥最大价值——文本可读、可搜索、可对比、可合并。绝大多数职业的核心产出物都是文本:代码、配置、需求文档、合同条款、论文、小说章节。所有人都需要版本管理,只是大多数人叫它另存为 v2-final.docx

与 Markdown 的天然协同

Git 和 Markdown 是事实上的最佳搭档——一份 .md 文件同时是 Git 的理想内容和几乎所有文档平台的输入:

  • Git 看 Markdown:纯文本,diff / merge 完美工作,“改了哪一段、删了哪一句”一目了然。
  • Markdown 看 Git:单文件极小(一份项目文档通常几十 KB,.docx 动辄几十 MB)——仓库体积可控、git clone 毫秒级。
  • 编辑器友好:VS Code / Obsidian / Typora / JetBrains 全家桶都原生支持 Git + Markdown,开箱即用。
  • 平台中立:同一份 .md 可以渲染到 / GitHub Pages / GitBook / Notion / 自建站 / 微信公众号,不被任何厂商锁定。
  • AI 友好:LLM 天然生成与解析 Markdown,AI 写的文档可直接 commit,CI 可自动校验格式。

这正是 Git × Markdown 流行的根本原因:写作者只需要“想清楚写什么 + 用 Git 管理变更”,下游的渲染、分发、协同全部交给生态

一切即代码:公式、图表、基础设施都可进 Git

Markdown 不只是“写文章”,它把代码化的思维带进了文档——以前嵌在 Word 里的复杂对象,现在都能用纯文本承载、随 Git 进版本管理:

  • 数学公式:Markdown + KaTeX(行内 $...$、块级 $$...$$)让 LaTeX 公式直接写在文档里,渲染为网页公式——不再需要 Word 那种“嵌入对象”的黑盒。
  • 架构图:Markdown + Mermaid 让流程图、时序图、ER 图、状态图用纯文本语法画出来——diff 可读、改动可追溯、版本可比较。
  • 基础设施:Dockerfile、docker-compose、GitHub Actions、Jenkinsfile、Ansible、Terraform——这些“基础设施即代码”的配置文件本身就是声明式代码,天然适合 Git。

一句话总结一切即代码,代码即可版本管理。把“贴在 Word 里的截图 / 嵌入对象”换成“写在 Markdown 里的公式、Mermaid、IaC 配置”,就同时获得 diff 可读、版本可追、轻松渲染、极其方便迁移——一份 .md 走到任何平台都能渲染,不用担心厂商锁定。

AI 原生协作新范式

在 AI Agent 时代,“Git + Markdown + 声明式配置”成为了人类与 AI 协作的公共语言:AI 编写 Markdown 文档并提交 commit,人类审阅、合并;CI 自动校验格式、自动构建、自动部署。

后续篇章中,我们将继续基于这种模式展开:

  • 基础设施即代码(IaC):05 篇 Docker / Docker Compose、06 篇基础、07 篇 GitHub Actions 都会落到这一层——服务器配置不再“贴控制台截图”,而是写在仓库里的 YAML / Dockerfile。

适合什么、不适合什么

内容类型是否适合 Git原因 / 替代方案
代码、配置、Markdown、LaTeX✅ 非常适合纯文本,diff/merge 全自动
设计文档 / 需求文档(结构化文本)✅ 适合同上
图片(少量、偶尔改)⚠️ 可用二进制版本管理,diff 不可读
图片(频繁改 / 大量)❌ 不适合仓库膨胀、无法合并——用 DAM / 对象存储
视频、音频、大型 3D 素材❌ 不适合单文件几百 MB,用对象存储
Office 文档(.docx / .xlsx)⚠️ 凑合内部 zip+xml,diff 不可读——用 Word / 飞书协同
数据库、生产数据❌ 极不适合用迁移工具管 schema,数据本身做备份

简单原则:主产出物是文本 → 用 Git;主产出物是大文件或频繁变的二进制 → 专用工具(图床、对象存储、专业 DAM、Word 协同)。

小结

Git 是本地版本管理工具,不依赖 GitHub 也能独立使用——它在你的电脑上管理版本历史,给每一次变更拍带上下文的快照。GitHub 是云端托管平台,解决备份和跨机器传输问题(告别手工 scp)。

对运维而言,Git 的核心价值是让发布输入有了精确的不可篡改锚点:每次部署对应哪次 commit、出问题回哪个版本、服务器上跑的是什么代码,都有据可查。

留给下一篇的遗留痛点

虽然 Git 解决了**“代码版本锚定”“源码免 scp 传输”**,但回到服务器端,03 篇提出的核心噩梦依然存在:

  • 服务器通过 git pull 拿到源码后,依然要在线执行 mvn package,依然要装 JDK / Python,依然存在编译争抢 CPU 以及 (环境强耦合) 的问题。
  • Git 锁定了代码版本,但锁不住运行环境。如何把”编译好的产物 + 运行环境本身”一起打包?这就是 05 篇(Docker 容器化) 登场要解决的根本问题。

思考

  1. git commit -m "update" 这样的说明有什么问题?Conventional Commits 前缀(如 feat: / fix:)对自动生成日志与版本发布有什么帮助?
  2. 如果有人直接在服务器上修改了代码(没走 Git),再执行 git pull 会发生什么?正确的服务端更新流程应该是什么?
  3. 如果 GitHub 仓库误上传了密码或 API Key,只删除文件再提交一次够不够?正确做法是什么?

延伸阅读:其他 Git 托管平台

GitHub 不是唯一的 Git 托管平台。选择时主要看网络可达性功能需求

平台特点推荐场景
GitHub全球最大开源社区,CI/CD(GitHub Actions)生态完善个人开发者、开源项目
GitLab一站式 DevOps(代码 + CI + 镜像仓库 + CD),可自托管中小团队、企业内网
Gitee国内直连、无需科学上网,功能与 GitHub 类似国内开发者、网络受限环境

三者底层都用 Git,git push / git pull 命令完全一样——只是远程地址不同。选哪个取决于你的网络环境和团队需求,不影响本地 Git 的使用。

参考

  1. Git 官方文档
  2. GitHub 官方文档
  3. Conventional Commits
  4. GitHub Hello World