搜索 K
主题
git clean 用于删除工作区中未跟踪的文件;git gc/git maintenance 用于仓库的垃圾回收和性能优化。前者清理工作区,后者清理 .git 目录。
clean 清理工作区的垃圾文件,gc 清理 .git 目录的冗余数据。
# ⚠️ git clean 是不可逆操作!删除后无法恢复
# 预览将被删除的文件(干跑模式,必须先运行这个!)
git clean -n
# Would remove build/
# Would remove temp.log
# Would remove src/debug.ts
# 确认后执行删除
git clean -f
# Removing build/
# Removing temp.log
# Removing src/debug.ts
# Git 默认要求 -f(force),防止误删
# 可以通过配置改变这个行为(不推荐)
# git config clean.requireForce false# -n / --dry-run: 预览(不实际删除)
git clean -n
# -f / --force: 强制删除
git clean -f
# -d: 同时删除未跟踪的目录
git clean -fd
# -x: 删除 .gitignore 中忽略的文件(如 node_modules、build)
git clean -fx
# ⚠️ 危险!会删除 node_modules、dist 等
# -X: 只删除 .gitignore 中忽略的文件(保留未跟踪但未被忽略的文件)
git clean -fX
# 只删除被 .gitignore 忽略的文件(清理构建缓存等)
# -i: 交互模式
git clean -di
# Would remove the following items:
# build/ temp.log src/debug.ts
# *** Commands ***
# 1: clean 2: filter by pattern 3: select by numbers 4: ask each one 5: quit
# -e: 排除特定模式
git clean -fd -e "*.log"
# 删除未跟踪文件和目录,但保留 .log 文件
# 组合使用
git clean -fdn # 预览:删除未跟踪的文件和目录
git clean -fdxn # 预览:删除所有未跟踪的(包括被忽略的)
git clean -fdXn # 预览:只删除被 .gitignore 忽略的| 命令 | 未跟踪文件 | 未跟踪目录 | .gitignore 忽略的文件 |
|---|---|---|---|
git clean -f | ✅ 删除 | ❌ 保留 | ❌ 保留 |
git clean -fd | ✅ 删除 | ✅ 删除 | ❌ 保留 |
git clean -fx | ✅ 删除 | ❌ 保留 | ✅ 删除 |
git clean -fdx | ✅ 删除 | ✅ 删除 | ✅ 删除 |
git clean -fX | ❌ 保留 | ❌ 保留 | ✅ 删除 |
git clean -fdX | ❌ 保留 | ✅ 删除 | ✅ 删除 |
# 构建缓存导致编译异常,需要完全清理重新构建
# 1. 预览
git clean -fdXn
# Would remove node_modules/
# Would remove dist/
# Would remove .turbo/
# Would remove .next/
# 2. 确认后清理
git clean -fdX
# 3. 重新安装和构建
npm install
npm run build# 「我想让工作区恢复到和仓库一模一样的状态」
# 1. 恢复所有已跟踪文件到最新提交
git checkout -- .
# 或
git restore .
# 2. 清理所有未跟踪文件(包括被忽略的)
git clean -fdx
# 组合命令:完全重置
git reset --hard HEAD && git clean -fdx
# ⚠️ 这会删除所有本地修改和未跟踪文件!
# 确保没有重要的未提交代码# 只清理 src/ 目录下的未跟踪文件
git clean -fd src/
# 只清理 build/ 和 dist/
git clean -fd build/ dist/
# 排除某些文件
git clean -fd -e "*.config.js" -e "local.*"git clean -fdi
# *** Commands ***
# 1: clean - 删除所有列出的文件
# 2: filter by pattern - 按模式过滤(如 *.log)
# 3: select by numbers - 选择特定文件
# 4: ask each one - 逐个确认
# 5: quit - 退出
# 选 4:逐个确认每个文件是否删除
# Remove temp.log [y/N]? y
# Remove debug/ [y/N]? n
# Remove test-output.txt [y/N]? y# Git 内部存储结构
.git/
objects/
ab/ # 松散对象(前 2 位作为目录名)
c1234... # 对象文件
pack/ # 打包文件
pack-xxx.idx # 索引文件
pack-xxx.pack # 数据文件
refs/ # 引用(分支、标签)
logs/ # reflog# 运行垃圾回收
git gc
# Enumerating objects: 1234, done.
# Counting objects: 100% (1234/1234), done.
# Delta compression using up to 8 threads
# Compressing objects: 100% (567/567), done.
# Writing objects: 100% (1234/1234), done.
# Total 1234 (delta 890), reused 345 (delta 234)
# 积极模式(更深度的优化)
git gc --aggressive
# 使用更多时间进行更深度的 delta 压缩
# 适合偶尔运行(如每月一次)
# 立即清理(不等待宽限期)
git gc --prune=now
# ⚠️ 慎用!会立即删除所有不可达的对象
# 自动 gc(Git 内部调用)
git gc --auto
# 只在需要时运行(松散对象超过阈值时)# Git 在以下情况自动运行 gc --auto:
# 1. 松散对象数超过 gc.auto(默认 6700)
# 2. packfile 数超过 gc.autoPackLimit(默认 50)
# 查看配置
git config gc.auto # 默认 6700
git config gc.autoPackLimit # 默认 50
# 禁用自动 gc(不推荐)
git config gc.auto 0
# 调整阈值
git config gc.auto 10000# 删除不可达的松散对象
git prune
# 通常不需要手动运行,gc 会调用
# 预览将被删除的对象
git prune --dry-run
# 指定宽限期(默认 2 周)
git prune --expire=2.weeks.ago
# 立即删除所有不可达对象
git prune --expire=now
# ⚠️ 在 reflog 也过期后才真正不可达# 现代化的仓库维护工具,替代手动 gc
# 注册仓库到维护计划
git maintenance register
# 启动后台维护
git maintenance start
# 自动在后台运行以下任务:
# - prefetch: 后台预取远程数据
# - commit-graph: 更新提交图缓存
# - gc: 垃圾回收
# - loose-objects: 打包松散对象
# - incremental-repack: 增量重新打包
# - pack-refs: 打包引用
# 手动运行特定任务
git maintenance run --task=gc
git maintenance run --task=commit-graph
git maintenance run --task=loose-objects
# 停止后台维护
git maintenance stop
# 取消注册
git maintenance unregister# maintenance 使用操作系统的调度功能
# Windows: 任务计划程序
# macOS: launchd
# Linux: cron 或 systemd timer
# 查看维护计划
git config --global --get-regexp maintenance
# 默认调度:
# hourly — prefetch(后台预取)
# daily — loose-objects, incremental-repack
# weekly — pack-refs, commit-graph, gc# 查看仓库大小
git count-objects -vH
# count: 42 # 松散对象数
# size: 1.2 MiB # 松散对象大小
# in-pack: 12345 # 打包对象数
# packs: 3 # packfile 数量
# size-pack: 156 MiB # packfile 大小
# prune-packable: 0 # 可清理的已打包松散对象
# garbage: 0 # 垃圾文件
# size-garbage: 0 bytes
# 查看 .git 目录大小
du -sh .git
# 或 Windows PowerShell
(Get-ChildItem .git -Recurse | Measure-Object -Property Length -Sum).Sum / 1MB# 找出仓库中最大的 10 个文件(当前和历史)
git rev-list --objects --all | \
git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' | \
grep "^blob" | \
sort -rnk3 | \
head -10
# blob abc1234 52428800 assets/video.mp4
# blob def5678 15728640 data/dump.sql
# ...
# 更友好的格式
git rev-list --objects --all | \
git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' | \
awk '/^blob/ {printf "%s\t%s\t%s\n", $3/1048576, $2, $4}' | \
sort -rnk1 | \
head -10
# 50.0 abc1234 assets/video.mp4
# 15.0 def5678 data/dump.sql# 使用 git filter-repo 删除历史中的大文件
# 安装: pip install git-filter-repo
# 删除特定文件
git filter-repo --path assets/video.mp4 --invert-paths
# 删除超过指定大小的文件
git filter-repo --strip-blobs-bigger-than 10M
# 删除后清理
git gc --aggressive --prune=now
# 强制推送(会重写历史)
git push --force --all
git push --force --tags# 浅克隆(只获取最近 N 个提交)
git clone --depth 1 <url>
# 适合 CI/CD 环境
# 部分克隆(不下载大文件对象)
git clone --filter=blob:none <url>
# 按需获取 blob 对象
# 部分克隆(不下载超过指定大小的文件)
git clone --filter=blob:limit=1m <url>
# 已有仓库转为浅仓库
git fetch --depth 1
git reflog expire --expire=all --all
git gc --prune=now# CI 构建后清理工作区
git clean -fdx
# 确保每次构建都是干净的环境
# 或使用 git checkout 的 clean 选项
git checkout -- .
git clean -fdx# GitHub Actions 中通常不需要手动 clean
# actions/checkout 每次都是全新的克隆
- uses: actions/checkout@v4
with:
clean: true # 默认为 true#!/bin/bash
# repo-maintenance.sh — 仓库定期维护
echo "🔧 Git 仓库维护"
echo "================"
# 1. 查看仓库大小
echo ""
echo "📊 仓库状态:"
git count-objects -vH
# 2. 清理过期的 reflog
echo ""
echo "🗑️ 清理过期 reflog..."
git reflog expire --expire=90.days --all
# 3. 运行 gc
echo ""
echo "📦 运行 gc..."
git gc --auto
# 4. 验证仓库完整性
echo ""
echo "🔍 验证仓库完整性..."
git fsck --no-dangling
# 5. 显示结果
echo ""
echo "📊 维护后状态:"
git count-objects -vH
echo ""
echo "✅ 维护完成"# 将仓库从 GitHub 迁移到 GitLab 前,先瘦身
# 1. 分析大文件
git rev-list --objects --all | \
git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' | \
awk '/^blob/ && $3 > 1048576 {printf "%.1fMB\t%s\n", $3/1048576, $4}' | \
sort -rnk1
# 2. 删除不需要的大文件
git filter-repo --strip-blobs-bigger-than 50M
# 3. 深度清理
git gc --aggressive --prune=now
# 4. 推送到新仓库
git remote add new-origin https://gitlab.com/team/repo.git
git push new-origin --all
git push new-origin --tags# 症状:Git 操作报错 "object corrupt" 或 "bad object"
# 1. 检查仓库完整性
git fsck --full
# error: object file .git/objects/ab/c1234... is empty
# missing blob abc1234...
# 2. 如果有远程仓库,从远程恢复
git fetch origin
# Git 会自动补全缺失的对象
# 3. 如果远程也没有,尝试从 packfile 恢复
git unpack-objects < .git/objects/pack/pack-xxx.pack
# 4. 最坏情况:重新克隆
cd ..
git clone <url> project-new
# 然后将本地未提交的修改手动复制过去# Windows 上 git clean 可能遇到的问题
# 1. 文件被占用无法删除
# 关闭 IDE、文件管理器等可能锁定文件的程序
# 2. 路径过长
# 启用长路径支持
git config --global core.longpaths true
# 3. 权限问题
# 以管理员身份运行终端
# 4. PowerShell 中的 clean 别名冲突
# PowerShell 有内置的 Clean-Item,不影响 git clean
git clean -fdn # 正常使用git clean -fdx 删除了重要文件# ❌ 不看预览直接清理
git clean -fdx
# 删除了 .env、本地配置、IDE 设置...
# ✅ 永远先预览
git clean -fdxn # 先看会删什么
git clean -fdx # 确认后再执行
# ✅ 或使用交互模式
git clean -fdxi # 逐个确认# ❌ 误操作后立即 gc
git reset --hard HEAD~5
git gc --prune=now # 永久删除了那 5 个提交!
# ✅ gc 前确保 reflog 中没有需要恢复的内容
git reflog # 先检查
git gc --prune=now # 确认后再清理# 默认 git clean -fd 不会删除 node_modules/(因为在 .gitignore 中)
git clean -fd
# node_modules/ 还在!
# 需要加 -x 才会删除被忽略的文件
git clean -fdx
# 或 -X 只删除被忽略的文件
git clean -fdX# ❌ 每次提交后都运行 aggressive gc
git gc --aggressive # 非常耗时!
# ✅ 正常使用 git gc(或让 Git 自动运行)
# 只在以下场景使用 --aggressive:
# - 仓库迁移后
# - 大规模 filter-repo 后
# - 每月/每季度一次的深度维护# ❌ 在主仓库运行 clean -fdx 可能清空子模块
git clean -fdx # 子模块目录也被清空了!
# ✅ 排除子模块目录
git clean -fdx -e "libs/shared"
# ✅ 或者分别清理
git clean -fd # 只清理未忽略的
git submodule foreach 'git clean -fd' # 单独清理子模块git clean 和手动删除有什么区别?git clean 只删除未跟踪的文件,不会误删已跟踪的文件。手动删除可能不小心删除被 Git 管理的文件。
git gc?大多数情况下不需要。Git 在 fetch、merge、rebase 等操作后会自动运行 gc --auto。以下场景建议手动运行:
filter-repo 后git maintenance 和 git gc 有什么区别?| 特性 | git gc | git maintenance |
|---|---|---|
| 引入版本 | 一直存在 | Git 2.31+ |
| 运行方式 | 手动/自动触发 | 后台定时调度 |
| 任务范围 | 打包+清理 | 打包+清理+预取+提交图 |
| 适用场景 | 简单维护 | 大型仓库持续优化 |
# 当前工作区中最大的已跟踪文件
git ls-files -z | xargs -0 ls -la | sort -rnk5 | head -10
# 历史中最大的文件(包括已删除的)
git rev-list --objects --all | \
git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' | \
awk '/^blob/ {printf "%.1fMB\t%s\n", $3/1048576, $4}' | \
sort -rnk1 | head -10| 目标 | 命令 |
|---|---|
| 预览要删除的文件 | git clean -n |
| 删除未跟踪文件 | git clean -f |
| 删除未跟踪文件和目录 | git clean -fd |
| 删除所有未跟踪(含忽略) | git clean -fdx |
| 只删除被忽略的文件 | git clean -fX |
| 交互式清理 | git clean -fdi |
| 排除特定文件 | git clean -fd -e "*.log" |
| 彻底重置工作区 | git reset --hard && git clean -fdx |
| 目标 | 命令 |
|---|---|
| 运行垃圾回收 | git gc |
| 深度优化 | git gc --aggressive |
| 立即清理不可达对象 | git gc --prune=now |
| 查看仓库大小 | git count-objects -vH |
| 验证仓库完整性 | git fsck --full |
| 启用后台维护 | git maintenance start |
| 手动运行维护任务 | git maintenance run --task=gc |
| 清理过期 reflog | git reflog expire --expire=90.days --all |
reset --hard + clean -fdx 彻底重置工作区