Cao Yi

第十一章 清理仓库

⇦上一章 - 首页🏠 - 下一章⇨



「若无必要,勿增实体」——奥卡姆剃刀(Ockham’s Razor)

Git 库在经过一段时间的使用后,可能会产生一些「垃圾」,影响使用体验,所以需要不定期清理以保持仓库的健康。

有的清理属于业务层面的,这些需要 git 用户根据业务的情况自行处理,比如:

  1. 多余的分支
  2. 遗弃的分支
  3. 错误的标签
  4. 等等

还有些属于 git 库本身的问题,这些本文会进一步说明,比如:

  1. 没有引用的对象
  2. 不存在的远程的引用
  3. 等等

1. 准备实验

假定库已经准备好了,如果需要新建库,可以参考第九章,这里只是准备一些文件和文件变动:

$ ls
hello
$ echo "hello2" > hello
$ echo "hello2" > hello2
$ mkdir hello3
$ cd hello3
$ echo "hello3" >> hello3

2. 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>

3. git stash

对于已经进入暂存区(Stage Area)的改动,可以用 stash 来清理

$ git stash

如果 stash stack 的内容都不需要了,可以通过下面的指令清理掉

$ git stash clear

还有一种诡异的清理方法

$ git reset --hard HEAD
# or
$ git checkout -- .

以上两个指令其实只要执行一个就行,两个都执行,简直是双保险。

4. git gc

通常情况下,清理本地库,执行

$ git gc

就行了。

git gc 执行时,会调用 git prune 等指令。

5. 清理本地对远程的引用

本地仓库持有远程仓库的分支和标签信息。

如果远程仓库新增了分支或标签,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

可以考虑设置一个自动任务,周期性执行;也可以设置一个日历提醒,收到消息后再手工执行。

6. 清理已合并的分支

仓库经过长时间使用后,有一些 branch 可能已经成为僵尸:早已合并进 master/main 分支,但忘了删除。此时可以通过

$ git checkout master
$ git branch --merged
$ git branch -r --merged

找到本地和远程的这些分支,然后放心删除。注意在执行这些操作特别是远程操作之前用下列指令将本地库和远程库更新到一致状态:

$ git fetch --all
$ git fetch --prune --prune-tags --force

⇦上一章 - 首页🏠 - 下一章⇨