Featured image of post 使用 Git 在不同设备间同步 Obsidian 库

使用 Git 在不同设备间同步 Obsidian 库

起因

我手头有两台 Windows 设备,经常需要在它们之间同步 Obsidian 库。平时用 SMB 协议拷来拷去实在是不太方便,我便想利用自己的 Debian 服务器,通过 Git 实现多设备同步。


服务端准备

首先,要在服务器上安装 Git。通过 SSH 连接到服务器,并使用 apt 命令进行安装。

1
sudo apt-get install git

为了方便管理,需要创建一个用户组与用户来运行 Git。先创建一个名叫 git 的用户组,再在该用户组中创建一个名叫 git 的用户。注意,不要为 git 用户设置口令。

1
2
sudo groupadd git
sudo useradd git -g git

出于安全考虑,需要限制 git 用户仅可通过 SSH 使用 Git。通过以下命令打开 /etc/passwd 文件。

1
sudo vi /etc/passwd

找到关于 git 用户的行,将末尾最后一个冒号后的默认 Shell 字段替换为 /usr/bin/git-shell。该行修改后的形式应与下方代码块中所示的类似。

1
git:x:1001:1001::/home/git:/usr/bin/git-shell

至此,服务端基本准备完成。


密钥

在 Windows 设备上,打开终端,生成 RSA 公钥与私钥。

1
2
cd ~\.ssh
ssh-keygen -t rsa

当提示输入保存密钥的文件时,不建议使用默认文件名 id_rsa,建议自定义一个方便辨认的文件名,输入后按下回车。在这里,我以 id_rsa_server_git 为文件名保存密钥。随后出现的提示,可以根据需要自行配置,如不需要配置,皆按回车即可,完成密钥生成。此时,在 ~\.ssh 目录中会生成两个文件,一个是名为 id_rsa_server_git 的私钥文件;另一个则是名为 id_rsa_server_git.pub 的公钥文件。

~\.ssh 目录中打开 config 文件。如果没有 config 文件,创建一个即可。在该文件中新增以下内容,其中需要将 HostName 字段中的 server.lan 修改为服务端的地址或域名, Host 字段中的 Server-git 可以进行自定义。

1
2
3
4
5
Host Server-git
    HostName server.lan
    User git
    PreferredAuthentications publickey
    IdentityFile ~/.ssh/id_rsa_server_git

在管理员终端中使用如下命令启动 OpenSSH Authentication Agent 服务,并将其设置为开机自启动。

1
2
Start-Service ssh-agent
Set-Service ssh-agent -StartupType Automatic

为了在使用 Git 时自动运行 ssh-agent,参考 Github 文档中提供的方法,创建 ~/.profile 文件,并将以下内容粘贴其中。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
env=~/.ssh/agent.env

agent_load_env () { test -f "$env" && . "$env" >| /dev/null ; }

agent_start () {
    (umask 077; ssh-agent >| "$env")
    . "$env" >| /dev/null ; }

agent_load_env

# agent_run_state: 0=agent running w/ key; 1=agent w/o key; 2=agent not running
agent_run_state=$(ssh-add -l >| /dev/null 2>&1; echo $?)

if [ ! "$SSH_AUTH_SOCK" ] || [ $agent_run_state = 2 ]; then
    agent_start
    ssh-add
elif [ "$SSH_AUTH_SOCK" ] && [ $agent_run_state = 1 ]; then
    ssh-add
fi

unset env

在终端中使用以下命令设置用户环境变量。设置完成后需重新启动系统。

1
[System.Environment]::SetEnvironmentVariable('GIT-SSH','C:\Windows\System32\OpenSSH\ssh.exe',[System.EnvironmentVariableTarget]::User)

打开之前生成的公钥 id_rsa_server_git.pub 文件,将其中的内容全部添加到服务端的 /home/git/.ssh/authorized_keys 文件中,一个公钥占一行。此时,在 Windows 设备的终端中使用以下命令确认配置是否正确。

1
ssh git@server.lan

若没有提示需要输入口令,且弹出如下提示并断开连接,即配置成功。

1
2
3
fatal: Interactive git shell is not enabled.
hint: ~/git-shell-commands should exist and have read and execute access.
Connection to server.lan closed.

在所有需要同步的 Windows 设备上,均需要完成本节中的操作。


初始化 Git 仓库

在服务端的合适位置创建 Git 裸仓库。在这里我在 git 用户的目录下创建了 git_repos 目录用以存放仓库。

1
2
sudo mkdir /home/git/git_repos
sudo git init --bare /home/git/git_repos/obsidian_vault.git

/home/git/git_repos 目录内的所有文件与目录之所有者移交给 git 用户。

1
sudo chown -R git:git /home/git/git_repos

在某一台需要同步的 Windows 设备上克隆该仓库到设备。在合适的位置启动终端,并使用以下命令进行克隆。

1
git clone git@server.lan:/home/git/git_repos/obsidian_vault.git

此时,在对应目录中会出现 obsidian_vault 目录,进入该目录,创建 .gitignore 文件,告诉 Git 在提交时要忽略哪些文件和目录。.gitignore 文件中的内容可以按需更改,下面仅作为示例。

1
2
3
4
5
6
.obsidian/
#.obsidian/plugins
#.obsidian/workspace.json
#.obsidian/workspace-mobile.json
.trash/
.DS_Store

另外,为了避免 CRLF 与 LF 的问题,还需创建 .gitattributes 文件。同样,该文件的内容可以按需更改,下面仅作为示例。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
* text=auto

*.md text
*.txt text
*.js text
*.json text
*.html text
*.css text

*.png binary
*.jpg binary
*.gif binary
*.bmp binary

至此,便可以将已有的 Obsidian 库中的所有内容复制到 obsidian_vault 目录,并在该目录下利用终端使用以下命令进行暂存、提交、推送。

1
2
3
git add .
git commit
git push

需要注意的是,在第一次推送完成后,需要在所有未克隆过远程仓库的 Windows 设备上进行一次克隆。


同步 Obsidian 库

启动 Obsidian 并打开 obsidian_vault 目录。在设置中的第三方插件下关闭安全模式,随后浏览社区插件市场,搜索并安装 Git 插件,并在安装的插件中启用它。此时,插件便已经可以读取到 Git 仓库的信息。打开命令面板,搜索 Git: Open source control view 并点击相应条目,便可在右侧的侧边栏中进行暂存、提交、推送、拉取等操作,以实现同步。插件的具体使用方法与配置详见 Git 插件的 GitHub 页面与文档,在此不多赘述。至此,已完成使用 Git 在不同设备间同步 Obsidian 库的基本配置。

最后更新于 Feb 04, 2024