是時候同步你的 dotfiles 了 — 我選擇 yadm

輕鬆管理 dotfiles

kyo
9 min readApr 9, 2023
from Pixabay

本文主要寫給軟體工程師,尤其是後端。

不過, 這並不是一篇 yadm 操作教學 ,而是我在選擇 dotfiles 同步方案時,所做的功課與思路整理,其中的考量大概有下:

  1. 靠自己簡單實作就好,還是要透過工具?
  2. 如果要用工具,工具這麼多,該如何選擇
  3. 工具之間有什麼本質的差別嗎?(其實就是下述流派上的差別)

場景與需求

如〈 Linux 開發環境設定大全:zsh、zinit、pyenv、poetry、docker 〉所言,因為新 VM 的建立,我又得重設一次開發環境,而重設開發環境往往是一個耗時且繁瑣的過程。

在這個過程中,需要重新建立一些設定檔,例如.bashrc.zshrc 。這些設定檔通常包含了工具設定、命令別名、環境變數等大量內容,因此特別惱人。

此外,即使不是重建環境,平時要在不同 VM 包括本機電腦間「 手動同步 」這些檔案,也是一件讓人很想逃避的事。

.zshrc為例,如果它很少變動,那可能還好。但很不幸的,我又是一個很愛為命令列工具建立 alias(別名)的人,光憑這點,就使我不時會修改.zshrc

不同 VM 間的 dotfiles 手動同步讓人想逃避

而當你有 1 台、2 台……甚至更多 VM 時,.zshrc修改後的「 內容同步 」問題,足以讓你非常痛苦。

以我自己為例,我工作上「只有」2 台 VM,哪怕是兩台, 在很長一段時間裡,這兩台 VM 的 alias 設定都 沒有完全一致 — 因為我在其中一台新增了 alias 後,就懶得手動為另一台更新相同內容。

這聽起來有點愚蠢,卻是人之常情……但這次我不忍了!為了解決這個問題,我打算使用「更先進的手段」,來同步和管理這些設定檔。

如此一來,無論「重設開發環境」或「在多個 VM 之間同步設定」,我的 dotfiles 都可以輕鬆保持一致,提高工作效率。

什麼是 dotfiles?

前面已經提了幾次 dotfiles,卻還沒有解釋它。不過相信對於很多人來說,應該一點也不陌生:舉凡在$HOME目錄底下的各種 工具設定檔,常常都是以一個點「. 」開頭,所以它們被稱為 dotfiles。

當然,它們未必 全都放在$HOME目錄底下,甚至也未必皆以「. 」開頭,只是在多數時候如此而已。

一些常見的 dotfiles 包括:

  1. .bashrc.bash_profile:最常見的 dotfiles。
  2. .vimrc:Vim 編輯器的設定檔,包含了一些編輯器偏好、快捷鍵綁定等。
  3. .gitconfig:Git 版控系統的設定檔,最基本的功能是儲存使用者的 name 和 email。而我個人也習慣把 Git「子命令」相關的 alias 放在這裡,而非放在.zshrc,像下面這樣:
[user]
name = kyo
email = odinxp@gmail.com

[alias]
st = status
br = branch
co = checkout
brs = branch -a

管理 dotfiles 的兩大流派:Symbolic Link vs Bare Git

做過一番功課以後,我認為同步 dotfiles 所使用的手段,大致可分為兩個流派:

  1. Symbolic Link。
  2. Bare Git。

而且各有各的工具方便你使用。

如果想要自己摸索,嘗試,這篇 Reddit 討論串我覺得頗值參考:

我對 dotfiles 管理工具的理解,也大致是從這篇討論延伸而來。

方案一:Symbolic Link

事實上,想要輕鬆同步你的 dotfiles,未必要使用別人寫的工具。最常見的做法,就是透過軟連結(Symbolic Link)。

在此不細論具體的做法為何,可以隨意 Google 一下「 symbolic link dotfiles 」就有滿坑滿谷的資訊。

意即,自己弄一個 dotfiles repo 並手動建立軟連結,就是一個簡單暴力的方式。

但這樣做的主要缺點是:「軟連結」部分需要你 手動建立,也還是不太輕鬆,所以並不推薦使用 — 但適合 不想靠工具,又希望比「複製貼上」更有效的 極簡主義者

再「聰明」一點,則是配合 stow,可參考這篇〈 【譯】使用 GNU stow 管理你的點文件 〉,我想這樣已經足夠優雅了。

方案二:Bare Git

既然如此,那為什麼還需要寫這篇文章呢?當然是為了那些 — 包括我 — 不想在本機建立一個獨立的 dotfiles repo 的人!

申言之,軟連結方案通常會改變 dotfiles 的實際存放路徑 — 因為它們必須集中到 dotfiles repo 底下。而 stow 等工具的通常用途把你手動建立連結部分變成自動。

至於不想要變動 dotfiles 路徑的人(這無疑也是一種偏執呀,哈哈哈!),則需要第二種的「Bare Git」方案。

雖說是第二種方案,但其實 兩者都需要在遠端維護一個 dotfiles repo ,只不過 Git 方案在「本地」並沒有建立一個獨立的 dotfiles repo — 所以也不必變動原來 dotfiles 的存放路徑。

何謂 Bare Git 方案?

具體而言,就是指這篇〈 Dotfiles: Best Way to Store in a Bare Git Repository 〉中的做法。因為文章就稱它為「Bare Git」,所以我也這麼稱呼。

講白了,就是利用 Git 本身的進階功能(但不是一般我們常用的那種)來達到同步 dotfiles 的目的。

這種做法的 特色和優點在於, 無須在本機建立額外的 dotfiles repo,而是直接將你的「 家目錄」作為 dotfiles repo。此外, 你需要主動選擇並加入想要同步的檔案 ,而不像我們平常使用 Git 時,工作目錄中未被 gitignore 的檔案都會自動被同步。

這篇文章不長,但我實際試著一步步照做後,發現其中的「坑」還真是不少 — 畢竟這不是我們平常使用 Git 的方式。

經歷一小時的嘗試與挫敗後,我放棄了!決定直接使用工具即可。

同步 dotfiles 的自動化工具選項

管理、同步 dotfiles 究竟有哪些工具可以選擇呢?說真的,非常多!

可以參考 這個清單 ,它依照 GitHub 星星數量排序列出,並附上了言簡意賅的介紹。

如果想要知道工具間的更多細節與比較,則可以參考 這個對照表

作為一個 Python 工程師,我偏好選擇由 Python 開發而成的工具。上述頁面中提到的 Dotbotyadm 都是不錯的選項 — 它們主要都是使用 Python 語言開發的。

我選擇 yadm

老實說,Dotbot 和 yadm 我一開始也不知道要選哪個,所以乾脆直接先挑其中一個來試試,看看稱不稱手、合不合用。

如果是,就可以結束這回合;如果否,就換另一個。

我先試了 yadm,因為已經自己實作過〈 Dotfiles: Best Way to Store in a Bare Git Repository〉的內容,我不禁訝異: 這不就是自動化的 Bare Git 方案嗎!

流程可以說非常類似,重要的是:它把那些 複雜且容易出錯 的地方「封裝並隱藏起來了」 — 顯然這就是我要的!

附帶一提,從 Dotbot 的 GitHub 介紹 看來,它更偏向於使用 Symbolic Link:

Dotbot only supports Python 3.8+, and it requires that your account is allowed to create symbolic links.

開始使用 yadm

教學什麼的就不獻醜了,而且步驟也非常簡單,尤其在我親身「折騰」過〈 Dotfiles: Best Way to Store in a Bare Git Repository 〉以後,更是覺得:靠工具通常還是會讓你輕鬆不少,所以也不再堅持要「自己來」了。

建議直接 安裝,並參考官網的「 Getting Started 」操作。

其實你只要自己實踐過〈 Dotfiles: Best Way to Store in a Bare Git Repository 〉就會知道,兩者大同小異,只是 yadm 隱藏了更多容易出錯的細節,讓人更容易上手。

安裝好 yadm 後,它就變成了一種「特殊的 Git」指令 — 但只會影響你的 dotfiles repo。

yadm 常用指令

常用的指令可參考 這個頁面

就跟 Git 非常類似 — 畢竟它本質上就是 Git。只是增加了一些 額外的指令方便你查看目前 dotfiles repo 狀態,比如 yadm list

這些區別,頁面中也都有說明:

Most of these operations will look like Git commands; because they are. yadm wraps Git, allowing it to perform all of Git’s operations. The difference is your $HOME directory becomes the working directory, and you can run the commands from any directory.

Commands below which are special to yadm are denoted with *, and those which are passed directly through to Git are denoted with git.

所以使用上,與操作 Git 大同小異,如下圖:

解說:

  • pullpush這些常見 Git 操作,在使用 yadm 時也一樣,所以如果發生「檔案狀態衝突」,也是要依照與 Git 相同方式去處理。
  • 為了同步需求,在遠端比如 GitHub,還是要建立一個「收集這些 dotfiles 清單與狀態」的倉庫,通常我們也會命名為「dotfiles」。

Originally published at https://blog.kyomind.tw on April 9, 2023.

--

--

kyo

這裡只更新「非程式相關」文章,更多內容歡迎查看我的部落格:https://blog.kyomind.tw/ ;如果你只對非程式類文章感興趣,歡迎訂閱🥰