使用裸 Git 仓库备份 *nix 系统用户配置文件
The information in this article may be outdated. Please verify carefully.
之前一直比较头疼配置文件在多台设备上的备份与共享,最近 Google 到了一个简单方便的终极方法,这个方法只需要使用 Git。
此方法需要读者了解如何使用 Git,若不了解 Git 请先学习 Git 基本操作。
简介
本方法主要思想是使用 git 仓库管理配置文件,在 HOME 目录下保存一个 git 版本库,并将 HOME 目录设置为工作区,将需要备份的配置文件添加到 git 仓库中,而无需手动复制配置文件。在不同主机上如果使用不同的配置文件,可以使用不同的分支加以区分,并在 master 分支上保存公共的配置文件。这样我们可以充分利用 git 的 checkout、merge、rebase 等各种功能来管理我们的配置文件。
创建配置仓库
第一次备份配置时,需要创建一个 Git 仓库到 HOME 目录下:
git init --bare $HOME/.dotfiles
以上命令创建了一个裸 git 仓库,没有工作区。也就是说 .dotfiles
相当于普通 git 仓库下的 .git
文件夹,里面存放 git 仓库的历史记录及配置信息。
接着我们在 shell 的配置文件中定义一个别名 alias:
alias config='git --git-dir=$HOME/.dotfiles --work-tree=$HOME'
将以上内容添加到 shell 的配置文件中,可以使用下面的命令。shell 配置文件路径比如 bash 是 ~/.bashrc
,zsh 是 ~/.zshrc
,fish 是 ~/.config/fish/config.fish
。之后我们都通过 config
命令来操作配置仓库。而且只要把 config
当成 git
命令来使用即可。
echo "alias config='/usr/bin/git --git-dir=$HOME/.dotfiles --work-tree=$HOME'" >> $HOME/.bashrc
添加完后执行 exec bash
让配置生效,使用其它 shell 对应地替换掉 bash
即可。
现在通过以下命令我们可以看到当前配置仓库的状态:
config status
但是这样有个问题,HOME 目录下所有文件都被标记为 untracked,很影响仓库状态的查看,所以配置 git 仓库不显示未被追踪的文件:
config config --local status.showUntrackedFiles no
另外,为了避免今后在其它地方通过 git 获取备份的配置时出现奇怪的回溯问题,在 HOME 目录下创建 .gitignore
文件,并将以下内容添加到该文件中。
.dotfiles
之后我们就可以通过 git add 和 git commit 命令将需要备份的配置文件添加到 git 仓库中,也可以通过 git remote add 添加远程 git 仓库。当然需要使用 config
替换 git
。
在其他设备上获取配置
从远程仓库获取你的配置仓库,将 <git-repo-url>
换成实际远程仓库地址:
git clone --bare <git-repo-url> $HOME/.dotfiles
和之前一样,在 shell 中定义别名,如果备份的配置中已经定义了别名,现在可以直接在 shell 中执行以下命令,临时添加别名:
alias config='git --git-dir=$HOME/.dotfiles --work-tree=$HOME'
接着我们来从仓库中检出之前备份的配置文件:
config checkout
在这一步可能会发生冲突导致检出失败,比如出现类似下面的输出:
error: The following untracked working tree files would be overwritten by checkout:
.bashrc
.gitignore
Please move or remove them before you can switch branches.
Aborting
这时我建议将出现冲突的本地文件重命名,加上 .bak
后缀再执行之前的检出命令。
检出成功执行后,所有的配置文件就都出现在其原本的位置。
最后和之前创建仓库时一样,需要设置仓库不显示未被追踪的文件:
config config --local status.showUntrackedFiles no
与 vim-fugitive 结合使用
vim-fugitive 是 Vim 上一个与 git 深度结合的插件,通过它可以方便快捷地操作暂存区以及查看 git 历史。要将该插件用于本文的配置仓库中,需要对仓库进行一些额外的配置。
因为 fugitive 根据 git 仓库的 core.worktree
属性确定工作区位置,所以需要配置仓库的这个属性:
config config --local core.worktree $HOME
为了检查确认设置正确可以运行不加参数的命令,如果输出是实际的 HOME 路径就没问题:
config config --local core.worktree
另外,因为我们通过 --bare
命令初始化仓库,在查看仓库状态时会遇到 warning: core.bare and core.worktree do not make sense
的问题,解决方法是去掉仓库 core.bare
属性或将它的值改成 false
,这里选择前者:
config config --unset core.bare
最后我们在启动 (neo)vim 时,添加环境变量 GIT_DIR=$HOME/.dotfiles
即可让 fugitive 获取配置仓库的位置
GIT_DIR=$HOME/.dotfiles vim
我使用的是 fish shell,所以使用以下命令:
env GIT_DIR=$HOME/.dotfiles vim
最后在 shell 配置文件中,可以将运行命令定义成一个别名 alias 方便使用(dv: dotfiles vim):
alias dv='GIT_DIR=$HOME/.dotfiles vim'
另外补充一点,使用这种方法,fugitive 只能在 HOME 目录或子目录下正常使用,否则会出现 fugitive: working directory does not belong to a Git repository
的错误。所以如果在 HOME 中有软链接链接到其它地方,在其中 fugitive 会无法使用。
Refs
- GitHub does dotfiles - dotfiles.github.io
- Dotfiles - ArchWiki
- 本文内容基本来自此文章:How to store dotfiles | Atlassian Git Tutorial
- Handle GIT_WORK_TREE · Issue #415 · tpope/vim-fugitive · GitHub
- vim-fugitive 参考 How to use vim-fugitive with a git bare repository? - Stack Overflow okket 的回答,并根据我自己(gkzhb)的实践补充了额外需要的配置写了一条更完整回答。