玩转 Git 三剑客 · 实操学习博客真实数据版本文所有命令均已在真实的代码托管平台与云主机上执行文中的仓库地址、commit 哈希、对象 ID、机器信息、部署日志全部来自真实运行结果非示意。实操时间2026-07-20 · 环境华为云 FlexusX ×4Ubuntu 24.04.4 LTS GitHub Gitee0. 实操环境总览真实探测结果0.1 代码托管平台通过 API 真实创建平台账号仓库仓库 ID首个 commitGitHubcpyaxjqhttps://github.com/cpyaxjq/git-three-musketeers-demo13063885400e40cc6GiteeLiaCinLincolnhttps://gitee.com/LiaCin/git-three-musketeers-demo492286660e40cc6两个仓库均由 API 创建HTTP 201随后本地git push推入同一个 commit0e40cc6实现「一套代码双平台镜像」。0.2 云主机4 台SSH 逐台实测主机公网 IP私网 IP系统内核规格Gitecs-6ac4-00011.92.70.215192.168.0.160Ubuntu 24.04.4 LTS6.8.0-106-generic8 vCPU / 14Gi2.43.0ecs-6ac4-00021.92.114.92192.168.0.142Ubuntu 24.04.4 LTS6.8.0-106-generic8 vCPU / 14Gi2.43.0ecs-6ac4-00031.92.94.91192.168.0.123Ubuntu 24.04.4 LTS6.8.0-106-generic8 vCPU / 14Gi2.43.0ecs-6ac4-0004119.3.252.176192.168.0.198Ubuntu 24.04.4 LTS6.8.0-106-generic8 vCPU / 14Gi2.43.0四台均为全新实例uptime约 30 分钟、load average 0.00、内存占用约 500Mi/14Gi非常适合做干净的实验。1. 原理篇commit / tree / blob 对象模型ecs-0001 真实验证在 ecs-0001 上新建仓库并做 3 次提交然后直接查看 Git 底层对象。以下全部是真实输出。cd/rootmkdirgit-democdgit-demogitinitmkdir-psrcecho# DemoREADME.mdechoint main(){return 0;}src/main.cgitadd-Agitcommit-mcommit1: initechov2README.mdgitcommit-amcommit2: edit readmeechoxsrc/a.cgitadd-Agitcommit-mcommit3: add src/a.c真实版本历史* 18877b0 commit3: add src/a.c * cc5d712 commit2: edit readme * 1d84fe2 commit1: initgit cat-file -t HEAD→commitgit cat-file -p HEAD真实内容tree 49e8fdc0ecfca7f6b112784e54ad92bc99606b76 parent cc5d71224223328b476c432a2c8b879919e3ebbf author demo demolocal 1784537390 0800 committer demo demolocal 1784537390 0800 commit3: add src/a.cfind .git/objects -type f | wc -l→ 12 个对象。逐个git cat-file -t得到真实类型分布18877b05... - commit # commit3 (HEAD) cc5d7122... - commit # commit2 1d84fe29... - commit # commit1 49e8fdc0... - tree # commit3 根树 9f097660... - tree 60059c9f... - tree 82c71cc0... - tree cc6c297d... - tree b2e50482... - blob 2c99a527... - blob 587be6b4... - blob 0805455a... - blob结论用真实数据印证课程原理3 个 commit → 3 个 commit 对象每个 commit 通过parent串成链通过tree指向一次完整快照。12 个对象 3 commit 5 tree 4 blob。注意 tree 有 5 个而非 3 个因为有src/子目录每次涉及目录变化都会生成新的目录 tree而内容未变的 blob/tree 会被复用内容寻址相同内容只存一份。这正是课程第 10、11 讲「数一数 tree 的个数」的真实答案对象数量取决于目录层级与内容变化而非简单等于提交次数。commit(18877b0) │ tree 49e8fdc ← commit3 快照 ├── blob README.md └── tree src/ ├── blob main.c └── blob a.c2. 远端同步篇GitHub Gitee 双平台真实推送2.1 通过 API 真实创建仓库# GitHub返回 HTTP 201仓库 id1306388540curl-HAuthorization: token TOKEN\-d{name:git-three-musketeers-demo,private:false}\https://api.github.com/user/repos# Gitee返回 HTTP 201仓库 id49228666curl-d{access_token:TOKEN,name:git-three-musketeers-demo}\https://gitee.com/api/v5/user/repos2.2 本地提交并推送到两个平台gitclone https://github.com/cpyaxjq/git-three-musketeers-demo.gitcdgit-three-musketeers-demo# 放入博客文件 README提交gitadd-Agitcommit-mdocs: 提交 Git 三剑客学习博客MDHTML与 README# → [main (root-commit) 0e40cc6] 3 files changed, 886 insertions()# 推 GitHubgitpush origin main# * [new branch] main - main# 加 Gitee 远端并推送镜像gitremoteaddgitee https://LiaCin:TOKENgitee.com/LiaCin/git-three-musketeers-demo.gitgitpush gitee main# * [new branch] main - main真实验证Gitee API 查询分支 →branches [main]两平台main分支均指向同一 commit0e40cc6。 踩坑记录真实遇到Gitee 用https://tokenhost会触发交互式密码提示导致失败必须写成https://用户名:tokenhost并设GIT_TERMINAL_PROMPT0。GitHub 则用https://tokenhost即可。3. 冲突解决篇同区域冲突真实复现ecs-0001课程第 36 讲「不同人修改了同文件的同一区域」——在 ecs-0001 上用两个分支改同一行真实制造冲突# base: line1 / common / line3gitcheckout-balicesed-is/common/ALICE-change/app.txtgitcommit-amalicegitcheckout maingitcheckout-bbobsed-is/common/BOB-change/app.txtgitcommit-ambobgitmerge alice真实输出Auto-merging app.txt CONFLICT (content): Merge conflict in app.txt Automatic merge failed; fix conflicts and then commit the result.冲突文件真实内容原样line1 HEAD BOB-change ALICE-change alice line3git status --short→UU app.txtboth modified。解决手动编辑保留正确内容、删除 / / 标记 →git add app.txt→git commit。4. DevOps 篇一自建 Git 服务器 迷你 CI/CD多节点真实联动Docker Hub 拉 GitLab CE 镜像太大且默认被墙本次先用最纯粹、零外网依赖的方式验证「自建 Git 服务 自动部署」——ecs-0001 当服务器ecs-0002 当开发机走私网 SSH。4.1 服务端ecs-0001裸仓库 post-receive 钩子mkdir-p/srv/gitcd/srv/gitgitinit--bareproject.gitcatproject.git/hooks/post-receiveHOOK #!/bin/bash # 迷你 CI/CDpush 后自动检出到部署目录并记录版本 GIT_WORK_TREE/srv/git/deploy git --git-dir/srv/git/project.git checkout -f main echo [$(date %F %T)] deployed $(git --git-dir/srv/git/project.git rev-parse --short HEAD) /srv/git/deploy.log HOOKchmodx project.git/hooks/post-receive4.2 开发端ecs-0002生成密钥 → 授权 → clone → pushssh-keygen-ted25519-N-f~/.ssh/id_ed25519# 把公钥写入 ecs-0001 的 ~/.ssh/authorized_keys真实公钥指纹 rootecs-6ac4-0002gitclone ssh://root192.168.0.160/srv/git/project.git workcdworkgitcheckout-bmainecho# Self-hosted Git server demoREADME.mdechov1.0.0VERSIONgitadd-Agitcommit-mfeat: 首次提交多节点自建 Git 服务实测gitpush origin main真实结果warning: You appear to have cloned an empty repository. remote: Switched to branch main To ssh://192.168.0.160/srv/git/project.git * [new branch] main - main PUSHED_COMMITd73315b3770889422bcb45e82ee3f812ff5231ea4.3 服务端自动部署验证钩子真实触发$ cat /srv/git/deploy.log [2026-07-20 16:58:14] deployed d73315b $ ls /srv/git/deploy README.md VERSION $ cat /srv/git/deploy/VERSION v1.0.0 $ git --git-dir/srv/git/project.git log --oneline d73315b feat: 首次提交多节点自建 Git 服务实测✅一次git push自动触发部署ecs-0002 推送的 commitd73315b被 ecs-0001 的 post-receive 钩子实时检出到/srv/git/deploy并写入部署日志。这就是 CI/CD「push 即部署」的最小内核。5. DevOps 篇二Docker Gitea 自建代码平台真实部署成功GitLab CE 镜像约 2GB5 Mbit/s 带宽下不现实改用轻量的Gitea同为自建代码平台验证同样的 Docker/Web 平台流程。5.1 安装 Docker真实版本apt-getinstall-ydocker.io# → Docker version 29.1.3, build 29.1.3-0ubuntu3~24.04.2systemctlenable--nowdocker5.2 配置国内镜像加速真实踩坑 → 解决首次docker pull直连 Docker Hub超时失败failed to resolve reference docker.io/gitea/gitea: dial tcp 108.160.172.200:443: i/o timeout配置镜像加速器后成功cat/etc/docker/daemon.jsonEOF {registry-mirrors:[https://docker.m.daocloud.io,https://mirror.ccs.tencentyun.com]} EOFsystemctl restartdockerdockerpull gitea/gitea:1.22# → Status: Downloaded newer image for gitea/gitea:1.225.3 启动 Gitea 并验证真实运行中dockerrun-d--namegitea--restartalways\-p3000:3000-p2222:22\-v/var/lib/gitea:/data\gitea/gitea:1.22真实验证$ docker ps --format {{.Names}} {{.Status}} gitea Up 25 seconds $ curl -o /dev/null -w gitea_http%{http_code} http://127.0.0.1:3000/ gitea_http200 # 外网访问同样返回 200 $ curl http://1.92.70.215:3000/ → ext_http200✅ Gitea 已在 ecs-0001 真实运行浏览器可直接访问 http://1.92.70.215:3000首次访问需完成安装向导设置管理员。⚠️ 端口踩坑真实初次用-p 22:22映射会与宿主机 SSH 的 22 端口冲突导致容器启动失败改用-p 2222:22即可。6. 实操总结真实产出清单类别真实产出凭证GitHub 仓库github.com/cpyaxjq/git-three-musketeers-democommit0e40cc6id 1306388540Gitee 仓库gitee.com/LiaCin/git-three-musketeers-democommit0e40cc6id 49228666Git 对象模型ecs-0001 真实 12 对象3 commit/5 tree/4 blobHEAD tree49e8fdc合并冲突ecs-0001 真实同区域冲突 标记UU app.txt自建 Git 服务ecs-0001 裸仓库 post-receive 自动部署commitd73315b日志 16:58:14多节点协作ecs-0002 → ecs-0001 私网 SSH pushed25519 免密Docker 平台ecs-0001 Docker 29.1.3 Gitea 1.22http://1.92.70.215:3000 (HTTP 200)对课程三大主线的真实印证Git 原理commit/tree/blob 不是抽象概念——12 个真实对象、可cat-file逐一验证快照与内容寻址一目了然。平台协作同一 commit 真实推送到 GitHub Gitee 双平台踩了 Gitee token URL 格式的坑。GitLab/DevOps用 post-receive 钩子实现了「push 即部署」的 CI/CD 最小内核用 Docker Gitea 真实搭起了 Web 代码平台GitLab 的轻量替身流程完全一致。安全说明本文所有 token / 密码一律以TOKEN占位真实凭据未写入任何仓库或文档。自建服务默认仅演示生产环境请开启 HTTPS、分支保护、最小权限。