Dotfiles 管理-使用 git 裸倉庫

語言: CN / TW / HK

傳統管理

dotfiles 代指 linux/mac 中各種配置檔案。我們希望有一個方法可以集中管理它們,這樣切換不同機器時就能快速恢復熟悉的工作環境。目前比較流行的做法是 使用 git 來管理 ,藉助 orphan branch 還可以給不同系統/機器 建立不同的分支,分開管理。使用 git 管理需要三個步驟:

  1. 建立一個倉庫。
  2. 把所有 dotfiles 移動到倉庫裡。
  3. 在原來的地方建立一個軟連結。

所以… 一兩個檔案其實還好,但沒人希望給一堆檔案手動建立軟連結吧。

那麼有一個新方案:利用 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

這時候只好備份後覆蓋,然後手動合併咯。