2026-08-18 · 建站运维
最近把基础设施仓库做了大规模重构(26 个脚本分层迁移、目录树重组、镜像仓瘦身),把 Git 操作远程文件结构的经验整理成文,都是实战踩过的。
一、目录迁移:用 git mv 保历史
用 git mv 而不是 mv + git add。git mv 是元数据操作,git 能识别为 rename(显示 R 旧 -> 新 (100%)),完整保留历史——哪怕文件在迁移中改了内容,只要相似度够高也能识别。如果已经用普通 mv 了也别慌,git add -A 后 git 会自动检测 rename。
批量迁移前先做两件事:
mkdir -p目标目录(git mv 不会自动建目录)- 列好映射表:哪些文件去哪,避免迁移一半发现归属错误
迁移后验证远端而不是本地:
git ls-tree -r --name-only origin/main docs/ # 远端目录树
git show origin/main:docs/xxx.md | head # 远端文件内容
只看本地会漏掉「push 没成功」的情况;ls-tree 确认远端才是真。
二、推送:先 rebase 保线性历史
push 前先 git pull --rebase origin main,这是铁律。远端领先时直接 push 会被拒(rejected non-fast-forward);用 rebase 而不是 merge,保持线性历史,不会产生「Merge branch」噪音提交。今天多次遇到远端领先(不同会话在推同一个仓),rebase 一次解决,零冲突。
跨机器 clone 的仓库会报 dubious ownership,一条命令解决:
git config --global --add safe.directory /tmp/walle/prod/xxx
三、仓库体积:别让 git 历史撑爆限额
用 git count-objects -vH | grep size-pack 看真实体积——size-pack 才是 push 到远端的实际大小,工作区大小无关。大文件入库前先估算压缩后大小:
gzip -c bigfile.sql | wc -c
备份仓每日推增量,git 历史对象会无限累积(实测 733M → 重建后 99M)。根治办法是定期重建历史:
rm -rf .git && git init && git add -A && git commit -m "rebase" && git push -f origin main
前提是历史可丢——我们的备份镜像只保留最新 1 批,本地还有 7 份兜底,所以每月重建一次毫无压力。force push 前必须确认:远端历史丢弃可接受。
四、结构组织:分层 + README
仓库目录按「产品线版本号 / 功能名称 / 文档类型」分层,每层放 README 说明规范:
docs/ 产品线-v版本/功能/文档类型 (三层)
scripts/ 产品线-v版本/功能 (两层)
归属不清的放 _misc/_overview 定期整理,不留「无家可归」的文件。提交信息带结构化前缀(docs:/scripts:/feat:/fix:),git log --oneline 一眼分类,配合 --grep 快速检索历史。
五、避雷清单
| 坑 | 解法 |
|---|---|
| push 被拒(远端领先) | pull --rebase 再推,别硬推 |
| 大文件入库仓暴增 | 先估算压缩后大小 |
| 镜像仓 push 超时/内存不足 | 调低 pack.windowMemory + --threads=1 |
| 迁移后旧路径引用失效 | 迁移前 grep 全仓;README 留映射记录 |
一句话总结
git mv 保历史、pull --rebase 保线性、ls-tree/show 验远端、count-objects 看体积、分层 + README 保结构、定期重建历史防膨胀。