「若无必要,勿增实体」——奥卡姆剃刀(Ockham’s Razor)
Git 库在经过一段时间的使用后,可能会产生一些「垃圾」,影响使用体验,所以需要不定期清理以保持仓库的健康。
有的清理属于业务层面的,这些需要 git 用户根据业务的情况自行处理,比如:
还有些属于 git 库本身的问题,这些本文会进一步说明,比如:
假定库已经准备好了,如果需要新建库,可以参考第九章,这里只是准备一些文件和文件变动:
$ ls
hello
$ echo "hello2" > hello
$ echo "hello2" > hello2
$ mkdir hello3
$ cd hello3
$ echo "hello3" >> hello3
git clean
git clean
用以清理未跟踪的文件。有时我们会在工作目录里编译,或其他什么操作,生成一些不必要的文件。
强制删除所有未跟踪的文件:
git clean -df
-d
表示要列出当前目录的子目录的修改情况, -f
表示强制删除了,-df
表示 -d
和 -f
的合写。
如果只想列出哪些需要删除,可以用「干跑(白跑)」--dry-run
参数:
$ git clean --dry-run
Would remove hello2
$ git clean --dry-run -d
Would remove hello2
Would remove hello3/
上面也可见 -d
的效果,带上它,会列举子目录的情况。但是不论带不带它,文件 hello
是不会见到的,因为 hello
已经被 git 跟踪了,而 git clean
只清理还没有被跟踪的文件的原因。
如果需要交互式操作,可以带上 -i
参数:
$ git clean -d -i
Would remove the following items:
hello2 hello3/
*** Commands ***
1: clean 2: filter by pattern 3: select by numbers
4: ask each 5: quit 6: help
What now>
git stash
对于已经进入暂存区(Stage Area)的改动,可以用 stash
来清理
$ git stash
如果 stash stack 的内容都不需要了,可以通过下面的指令清理掉
$ git stash clear
还有一种诡异的清理方法
$ git reset --hard HEAD
# or
$ git checkout -- .
git reset --hard HEAD
或 git reset --hard
硬重置到 HEAD,就是丢弃现有改动的意思git checkout -- .
签出当前版本的所有文件,还是丢弃现有改动的意思以上两个指令其实只要执行一个就行,两个都执行,简直是双保险。
git gc
通常情况下,清理本地库,执行
$ git gc
就行了。
git gc
执行时,会调用 git prune
等指令。
本地仓库持有远程仓库的分支和标签信息。
如果远程仓库新增了分支或标签,fetch / pull
操作会把它们取下来更新到本地,但如果远程仓库删掉一些,本地并不会同步删除。我们可以用下面的指令清理多余的引用:
$ git fetch origin --prune --prune-tags --force
如果设置了多个远程仓库,可以使用 --all
参数一次将所有远程库相关的内容都清理完(注意,根据我的实际使用经验,发现 --all
参数只是部分生效,建议实作时还是按库操作):
$ git fetch --all --prune --prune-tags --force
上面这条指令也可以简写为:
$ git fetch -a -p -P -f
官方文档的说明摘要如下:
-p
,--prune
, After fetching, remove any remote-tracking branches which no longer exist on the remote.-P
,--prune-tags
, Before fetching, remove any local tags that no longer exist on the remote if--prune
is enabled.
如果只需要清理多余的对远程 branch 的引用,可以用:
$ git remote prune origin
如果只需要清理本地多余的 tag,还可以这样:
$ git tag -d $(git tag)
$ git fetch --tags
可以考虑设置一个自动任务,周期性执行;也可以设置一个日历提醒,收到消息后再手工执行。
仓库经过长时间使用后,有一些 branch 可能已经成为僵尸:早已合并进 master/main 分支,但忘了删除。此时可以通过
$ git checkout master
$ git branch --merged
$ git branch -r --merged
找到本地和远程的这些分支,然后放心删除。注意在执行这些操作特别是远程操作之前用下列指令将本地库和远程库更新到一致状态:
$ git fetch --all
$ git fetch --prune --prune-tags --force