玩转 Git 三剑客 · 实操学习博客(真实数据版)

📅 2026/7/22 1:40:05 👁️ 阅读次数 📝 编程学习
玩转 Git 三剑客 · 实操学习博客(真实数据版)

玩转 Git 三剑客 · 实操学习博客(真实数据版)

本文所有命令均已在真实的代码托管平台与云主机上执行,文中的仓库地址、commit 哈希、对象 ID、机器信息、部署日志全部来自真实运行结果,非示意。

实操时间:2026-07-20 · 环境:华为云 FlexusX ×4(Ubuntu 24.04.4 LTS)+ GitHub + Gitee


0. 实操环境总览(真实探测结果)

0.1 代码托管平台(通过 API 真实创建)

平台账号仓库仓库 ID首个 commit
GitHubcpyaxjqhttps://github.com/cpyaxjq/git-three-musketeers-demo13063885400e40cc6
GiteeLiaCin(Lincoln)https://gitee.com/LiaCin/git-three-musketeers-demo492286660e40cc6

两个仓库均由 API 创建(HTTP 201),随后本地git push推入同一个 commit0e40cc6,实现「一套代码双平台镜像」。

0.2 云主机(4 台,SSH 逐台实测)

主机公网 IP私网 IP系统内核规格Git
ecs-6ac4-00011.92.70.215192.168.0.160Ubuntu 24.04.4 LTS6.8.0-106-generic8 vCPU / 14Gi2.43.0
ecs-6ac4-00021.92.114.92192.168.0.142Ubuntu 24.04.4 LTS6.8.0-106-generic8 vCPU / 14Gi2.43.0
ecs-6ac4-00031.92.94.91192.168.0.123Ubuntu 24.04.4 LTS6.8.0-106-generic8 vCPU / 14Gi2.43.0
ecs-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/root&&mkdirgit-demo&&cdgit-demo&&gitinitmkdir-psrcecho"# Demo">README.mdecho"int main(){return 0;}">src/main.cgitadd-A&&gitcommit-m"commit1: init"echo"v2">>README.md&&gitcommit-am"commit2: edit readme"echo"x">src/a.c&&gitadd-A&&gitcommit-m"commit3: add src/a.c"

真实版本历史:

* 18877b0 commit3: add src/a.c * cc5d712 commit2: edit readme * 1d84fe2 commit1: init

git cat-file -t HEADcommitgit cat-file -p HEAD真实内容:

tree 49e8fdc0ecfca7f6b112784e54ad92bc99606b76 parent cc5d71224223328b476c432a2c8b879919e3ebbf author demo <demo@local> 1784537390 +0800 committer demo <demo@local> 1784537390 +0800 commit3: add src/a.c

find .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.c

2. 远端同步篇:GitHub + Gitee 双平台真实推送

2.1 通过 API 真实创建仓库

# GitHub(返回 HTTP 201,仓库 id=1306388540)curl-H"Authorization: token <TOKEN>"\-d'{"name":"git-three-musketeers-demo","private":false}'\https://api.github.com/user/repos# Gitee(返回 HTTP 201,仓库 id=49228666)curl-d'{"access_token":"<TOKEN>","name":"git-three-musketeers-demo"}'\https://gitee.com/api/v5/user/repos

2.2 本地提交并推送到两个平台

gitclone https://github.com/cpyaxjq/git-three-musketeers-demo.gitcdgit-three-musketeers-demo# 放入博客文件 + README,提交gitadd-Agitcommit-m"docs: 提交 Git 三剑客学习博客(MD+HTML)与 README"# → [main (root-commit) 0e40cc6] 3 files changed, 886 insertions(+)# 推 GitHubgitpush origin main# * [new branch] main -> main# 加 Gitee 远端并推送(镜像)gitremoteaddgitee https://LiaCin:<TOKEN>@gitee.com/LiaCin/git-three-musketeers-demo.gitgitpush gitee main# * [new branch] main -> main

真实验证:Gitee API 查询分支 →branches= ['main'];两平台main分支均指向同一 commit0e40cc6

💡 踩坑记录(真实遇到):Gitee 用https://<token>@host会触发交互式密码提示导致失败,必须写成https://<用户名>:<token>@host并设GIT_TERMINAL_PROMPT=0。GitHub 则用https://<token>@host即可。


3. 冲突解决篇:同区域冲突真实复现(ecs-0001)

课程第 36 讲「不同人修改了同文件的同一区域」——在 ecs-0001 上用两个分支改同一行,真实制造冲突:

# base: line1 / common / line3gitcheckout-balice&&sed-i's/common/ALICE-change/'app.txt&&gitcommit-am"alice"gitcheckout main&&gitcheckout-bbob&&sed-i's/common/BOB-change/'app.txt&&gitcommit-am"bob"gitmerge 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 line3

git status --shortUU app.txt(both modified)。

解决:手动编辑保留正确内容、删除<<<<<<< / ======= / >>>>>>>标记 →git add app.txtgit 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/git&&cd/srv/gitgitinit--bareproject.gitcat>project.git/hooks/post-receive<<'HOOK' #!/bin/bash # 迷你 CI/CD:push 后自动检出到部署目录并记录版本 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 HOOKchmod+x project.git/hooks/post-receive

4.2 开发端(ecs-0002):生成密钥 → 授权 → clone → push

ssh-keygen-ted25519-N''-f~/.ssh/id_ed25519# 把公钥写入 ecs-0001 的 ~/.ssh/authorized_keys(真实公钥指纹 root@ecs-6ac4-0002)gitclone ssh://root@192.168.0.160/srv/git/project.git workcdwork&&gitcheckout-bmainecho"# Self-hosted Git server demo">README.mdecho"v1.0.0">VERSIONgitadd-A&&gitcommit-m"feat: 首次提交(多节点自建 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_COMMIT=d73315b3770889422bcb45e82ee3f812ff5231ea

4.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 镜像约 2GB,5 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--nowdocker

5.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.json<<EOF {"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.22

5.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_http=200 # 外网访问同样返回 200: $ curl http://1.92.70.215:3000/ → ext_http=200

✅ 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-democommit0e40cc6,id 1306388540
Gitee 仓库gitee.com/LiaCin/git-three-musketeers-democommit0e40cc6,id 49228666
Git 对象模型ecs-0001 真实 12 对象(3 commit/5 tree/4 blob)HEAD 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)

对课程三大主线的真实印证

  1. Git 原理:commit/tree/blob 不是抽象概念——12 个真实对象、可cat-file逐一验证,快照与内容寻址一目了然。
  2. 平台协作:同一 commit 真实推送到 GitHub + Gitee 双平台;踩了 Gitee token URL 格式的坑。
  3. GitLab/DevOps:用 post-receive 钩子实现了「push 即部署」的 CI/CD 最小内核;用 Docker + Gitea 真实搭起了 Web 代码平台(GitLab 的轻量替身,流程完全一致)。

安全说明:本文所有 token / 密码一律以<TOKEN>占位,真实凭据未写入任何仓库或文档。自建服务默认仅演示,生产环境请开启 HTTPS、分支保护、最小权限。