Dotfiles 管理-使用 git 裸仓库
传统管理
dotfiles 代指 linux/mac 中各种配置文件。我们希望有一个方法可以集中管理它们,这样切换不同机器时就能快速恢复熟悉的工作环境。目前比较流行的做法是 使用 git 来管理,借助 orphan branch 还可以给不同系统/机器 建立不同的分支,分开管理。使用 git 管理需要三个步骤:
- 建立一个仓库。
- 把所有 dotfiles 移动到仓库里。
- 在原来的地方建立一个软链接。
所以... 一两个文件其实还好,但没人希望给一堆文件手动建立软链接吧。
那么有一个新方案:利用 git 裸仓库。它可以在 原地 跟踪 dotfiles,无需移动,自然也无需软链接。此方案来源:Git Bare Repository - A Better Way To Manage Dotfiles
裸仓库?
我们知道 git init
可以建立一个 git 仓库。之后,这个目录就成了「工作区」,可以存放并跟踪任意文件。同时,git 会建立一个 .git
文件夹,用于存放 git 所需要的数据。不难看出,一个普通的 git 仓库分为两部分:git 数据与工作区。
所谓裸仓库,就是只包含 git 数据而没有工作区,使用 git init --bare
命令来创建。裸仓库下的文件就是普通仓库下 .git
文件夹里的那些东西。等等,没有工作区?!
是的,没有工作区,这意味着这个仓库无法像普通的那样检出、修改、提交。那有什么用?用来储存呀!比如 github 应该就是在服务器上存了裸仓库——它只需要保存 git 数据就行了。
这里要澄清一个事实:git 数据包含了已跟踪的文件的状态以及修改记录。也就是说 commit 过的文件存储在 git 数据里,而不是工作区里。工作区只是一份检出而已。
没有工作区不代表不能执行常规的 git 操作,只不过我们需要通过选项 --work-tree
来指定一下工作目录。这也是无需移动 dotfiles 的关键所在。
创建
执行:
git init --bare $HOME/.dotfiles
alias config="/usr/bin/git --git-dir $HOME/.dotfiles --work-tree=$HOME"
首先创建了一个裸仓库,然后指定了一个别名 config
方便后续操作。它执行了 git 主程序,指定仓库位置以及工作目录。这样一来 config
的用法就与 git
一样了,可以便捷地添加文件。
此时如果执行 config status
会发现列出了一大堆 untracked files,因为 home 下所有文件都还没加入 git 跟踪。但我们本来就不是要跟踪所有文件,这样全部列出来看着很乱。因此执行一下:
config config --local status.showUntrackedFiles no
第一个 config
是我们创建的别名,第二个 config
是 git 的命令。这样就不会显示没有跟踪的文件了。
至此我们完成了仓库的创建,可以像普通 git 那样来直接管理所有文件,例如:
config add .zshrc
config commit -m "add .zshrc"
config push
...
恢复
面对一台新电脑...
首先克隆裸仓库:
git clone --bare <git_url> $HOME/.dotfiles
和创建时一样,新建一个别名方便操作,然后屏蔽未跟踪的文件。
alias config="/usr/bin/git --git-dir $HOME/.dotfiles --work-tree=$HOME"
config config --local status.showUntrackedFiles no
然后 checkout 一下,就可以恢复所有文件了:
config checkout
不过,如果某些文件已经存在了,则会报错:
error: The following untracked working tree files would be overwritten by checkout:
.zshrc
Please move or remove them before you can switch branches.
Aborting
这时候只好备份后覆盖,然后手动合并咯。