Git clean 先看预览:未跟踪目录、忽略文件和大小写选项分别覆盖什么
忽略列表并不是可以丢弃的清单
构建结束以后,工作目录里可能混着生成文件、个人草稿和本地配置。它们有些未被跟踪,有些被忽略,外观上却都只是普通文件。git clean 根据版本控制状态与选项决定候选范围,并不知道某个文件是否容易重建,所以开始清理之前必须先看实际预览。
最适合练习的环境是一次性临时仓库。下面所有 clean 调用都包含表示试运行的 n,只列出候选,不执行删除。示例通过 Python 创建独立仓库、安排样本并自动清理自己生成的临时目录,不会切换进现有项目,也不需要提交身份配置。
同一组文件,观察四种候选范围
运行环境需要 Python 三和 Git,本文使用三点十二与二点五十二验证。仓库里有已加入索引的文件、普通未跟踪文件、未跟踪目录,以及按规则忽略的缓存文件和构建目录。每组预览都由断言核对,最后再次检查全部样本仍然存在。
代码仅对演示子进程隔离全局配置读取,使用空模板创建仓库,并固定输出语言。这些设置不写入用户配置文件。示例路径名称刻意简单,让结果集中展示范围差异,而不把特殊文件名引用规则混在同一轮实验里。
AI概念配图,非真实界面
import os
from pathlib import Path
import subprocess
from tempfile import TemporaryDirectory
with TemporaryDirectory() as folder:
root = Path(folder)
repo = root / 'repo'
template = root / 'template'
template.mkdir()
env = {k: v for k, v in os.environ.items() if not k.startswith('GIT_')}
env.update(LC_ALL='C', GIT_CONFIG_NOSYSTEM='1',
GIT_CONFIG_GLOBAL=os.devnull)
def git(*args):
run = subprocess.run(['git', '-c', 'core.excludesFile=' + os.devnull,
'-C', str(repo), *args], env=env,
text=True, capture_output=True, check=True)
return run.stdout.splitlines()
repo.mkdir()
git('init', '-q', '--initial-branch=main', '--template=' + str(template))
(repo / '.gitignore').write_text('build/\n*.cache\n', encoding='utf-8')
samples = ['tracked.txt', 'notes.txt', 'local.cache',
'scratch/draft.txt', 'build/output.txt']
for name in samples:
path = repo / name
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text('sample', encoding='utf-8')
git('add', '--', '.gitignore', 'tracked.txt')
checks = [
('-n', ['notes.txt']),
('-nd', ['notes.txt', 'scratch/']),
('-ndX', ['build/', 'local.cache']),
('-ndx', ['build/', 'local.cache', 'notes.txt', 'scratch/']),
]
for option, expected in checks:
lines = git('clean', option)
assert lines == ['Would remove ' + name for name in expected], lines
print(option + ': ' + ', '.join(expected))
assert all((repo / name).is_file() for name in samples)
print('all sample files still exist')
print('all clean preview checks passed')小写 x 扩大范围,大写 X 改成只选忽略项
不带路径限定时,单独预览 n 只列出普通未跟踪文件,未跟踪目录不会自动递归处理。加入 d 后,scratch 目录进入候选。这个选项控制是否递归未跟踪目录,不能把它解释成“只处理目录”,普通未跟踪文件仍然在范围内。
大写 X 只选择被忽略的项目,所以预览里出现构建目录和缓存文件,个人草稿仍保留。小写 x 则不使用标准忽略规则,把普通未跟踪项和忽略项一起纳入。两个字母只差大小写,候选却明显不同,复制命令后应重新确认这一位。
已经加入索引的 tracked 文件没有出现在任何一组结果里,说明这些选项并不会把清理范围变成所有文件。相反,被忽略的配置仍可能包含无法重建的本地内容。版本控制状态与文件价值没有必然联系,不能把忽略规则当作删除授权。
把预览变成真实检查,而不是走过场
在实际项目中,应先确认仓库根目录、当前所在子目录和需要处理的路径,再用明确的路径限定生成预览。路径限定会改变命令的处理范围,官方手册也指出提供它时 d 的作用不同;不要把本文无路径限定的结果直接推广到所有写法。
预览之后,先逐项核对候选是否都有可验证的重建方式,必要时把需要保留的内容复制到仓库之外并检查备份。未跟踪文件往往没有提交记录,删除后不能指望普通的提交恢复流程把它找回来。真正执行前还要重新预览,避免中途新生成的文件改变集合。
嵌套 Git 仓库另有保护规则,不应该为了让命令“终于执行”而机械增加强制选项。遇到未预期的保护或候选,应停下来查看目录用途。自动构建任务最好使用专门工作区,并让清理范围与该任务实际拥有的生成物一致。
这份实验的验收重点是范围解释,而不是成功删掉多少文件。保留四组预览结果与文件仍存在的断言,能帮助团队在修改忽略规则或构建目录后重新检查清理脚本,避免一条看起来熟悉的命令逐渐覆盖新的重要内容。


