本机环境

windows 11 本地 git 已经与 github 配置了对应的 SSH 密钥

需求

笔者每天的学习都会有许多的笔记内容,笔者现在实验室配有电脑,自己还有一台笔记本电脑,每次写的笔记都是写在不同的电脑上。笔者希望可以在多个设备间很好的同步笔记内容,但是笔者一来不希望对笔记软件如语雀充钱,二来出于数据安全的考虑,笔者更希望笔记内容既有存储在本地电脑上,可以通过本地文件查看,同时也在云端有所备份。

解决方案

处于上述需求

  1. 从笔记本地化考虑

    • 那么笔记就不能用现在语雀,飞书,有道,notion 等软件进行记录

    • 所以本地的笔记一直都用的 obsidian 和 Typora 进行配合编写使用(obsidian 管理笔记分类分库,Typora 进行具体的笔记书写)

  2. 从云端备份考虑

    • 无论是阿里云还是百度云,一来不易于云端的在线阅读,二来这两个软件占用较高,不希望让其占用在后台,三来希望空间不受限制

    • 出于可以在线阅读,并且空间不受限制的考虑,这里选定了使用 github 进行同步,将所有的笔记放在一个文件夹下,让这个文件夹与在 github 创建的仓库建立好连接。

现在笔者每天写完笔记后,都可以使用 git 的命令将对应的更新内容推送到远程仓库,换电脑后也只需要从云端拉取后即可。但是这里有一个问题,笔者是一个巨懒的人,不想每天写完后都输入推送命令,而且大概率会写完笔记后忘记推送这件事情。

因此笔者希望可以在电脑上设置一个或者多个定时任务,每天定时检查,然后拉取远程仓库内容,定时推送本地内容。这里选用的是 PowerShell+Windows 任务计划程序+git 的方案

由于笔者的电脑都是 windows 环境,因此写的脚本都是 powershell 的脚本 首先是每天定时检查,推送本地内容的脚本

  • $repoPath 表示的本地存储所有笔记内容的文件夹

  • $logPath 表示的本地存储每次推送日志的位置

sync_to_github.ps1(注意其中的路径换成自己电脑上面的)

 # 设置脚本执行路径
 ​
 $repoPath = "F:\zsbao\Obsidian\WareHouse"
 ​
 $logPath = "F:\zsbao\Obsidian\ScheduledSynchronizationShell\logs\obsidian_sync_log.txt"
 ​
 $logDir = Split-Path $logPath
 ​
   
 ​
 # 创建日志目录(如果不存在)
 ​
 try {
 ​
     if (!(Test-Path $logDir)) {
 ​
         New-Item -ItemType Directory -Force -Path $logDir | Out-Null
 ​
         "Created log directory: $logDir" | Out-File -Append $logPath
 ​
     }
 ​
 } catch {
 ​
     Write-Error "Failed to create log directory: $_"
 ​
     exit 1
 ​
 }
 ​
   
 ​
 # 设置日期时间格式
 ​
 $datetime = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
 ​
 "===== Start sync to github everyday 12:00 or 18:00 or 21:30 at $datetime =====" | Out-File -Append "F:\zsbao\Obsidian\ScheduledSynchronizationShell\logs\obsidian_sync_log.txt"
 ​
 "Starting synchronization at: $datetime" | Out-File -Append $logPath
 ​
 try {
 ​
     # 切换到仓库目录
 ​
     Set-Location -Path $repoPath -ErrorAction Stop
 ​
     "Changed directory to: $repoPath" | Out-File -Append $logPath
 ​
 } catch {
 ​
     "Error changing directory: $_" | Out-File -Append $logPath
 ​
     exit 1
 ​
 }
 ​
   
 ​
 try {
 ​
     # 添加所有更改
 ​
     git add .
 ​
     "Executed: git add ." | Out-File -Append $logPath
 ​
 } catch {
 ​
     "Error adding files: $_" | Out-File -Append $logPath
 ​
     exit 1
 ​
 }
 ​
   
 ​
 # 准备提交消息(使用Here-String避免引号问题)
 ​
 $commitMsg = @"
 ​
 Auto sync on $datetime everyday auto commit
 ​
 "@
 ​
   
 ​
 try {
 ​
     # 提交更改(捕获标准错误)
 ​
     $commitOutput = git commit -m $commitMsg 2>&1
 ​
     if ($LASTEXITCODE -ne 0) {
 ​
         # 如果没有更改,提交会失败,这不一定是错误
 ​
         if ($commitOutput -match "nothing to commit") {
 ​
             "No changes to commit" | Out-File -Append $logPath
 ​
         } else {
 ​
             "Commit failed: $commitOutput" | Out-File -Append $logPath
 ​
             exit $LASTEXITCODE
 ​
         }
 ​
     } else {
 ​
         "Committed changes: $commitOutput" | Out-File -Append $logPath
 ​
     }
 ​
 } catch {
 ​
     "Error during commit: $_" | Out-File -Append $logPath
 ​
     exit 1
 ​
 }
 ​
   
 ​
 try {
 ​
     # 推送到远程仓库
 ​
     $pushOutput = git push origin main 2>&1
 ​
     if ($LASTEXITCODE -ne 0) {
 ​
         "Push failed: $pushOutput" | Out-File -Append $logPath
 ​
         exit $LASTEXITCODE
 ​
     } else {
 ​
         "Pushed to origin/main: $pushOutput" | Out-File -Append $logPath
 ​
     }
 ​
 } catch {
 ​
     "Error during push: $_" | Out-File -Append $logPath
 ​
     exit 1
 ​
 }
 ​
   
 ​
 # 记录成功同步
 ​
 "Successfully synced at: $datetime" | Out-File -Append $logPath
 ​
 "===== End sync to github everyday 12:00 or 18:00 or 21:30 at $datetime =====" | Out-File -Append "F:\zsbao\Obsidian\ScheduledSynchronizationShell\logs\obsidian_sync_log.txt"

然后是每天定时检查,然后拉取仓库内容的脚本 pull_or_push_sync.ps1

 # 智能同步脚本:本地有变更就上传,否则拉取远程
 ​
 cd "F:\zsbao\Obsidian\WareHouse"
 ​
   
 ​
 $datetime = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
 ​
 "===== Start Smart Sync(every day push or pull at 9AM) at $datetime =====" | Out-File -Append "F:\zsbao\Obsidian\ScheduledSynchronizationShell\logs\obsidian_sync_log.txt"
 ​
   
 ​
 # 获取工作区状态
 ​
 $status = git status --porcelain
 ​
   
 ​
 if ($status) {
 ​
     # 有本地修改或新增,执行提交并上传
 ​
     git add .
 ​
     git commit -m "Auto commit from local at $datetime morning has changed, push" 2>$null
 ​
     git push origin main
 ​
   
 ​
     "Local changes detected. Committed and pushed at $datetime." | Out-File -Append "F:\zsbao\Obsidian\ScheduledSynchronizationShell\logs\obsidian_sync_log.txt"
 ​
 } else {
 ​
     # 无本地修改,尝试从远程拉取
 ​
     git pull origin main | Out-File -Append "F:\zsbao\Obsidian\ScheduledSynchronizationShell\logs\obsidian_sync_log.txt"
 ​
     "No local changes. Pulled from remote at $datetime." | Out-File -Append "F:\zsbao\Obsidian\ScheduledSynchronizationShell\logs\obsidian_sync_log.txt"
 ​
 }
 ​
   
 ​
 "===== Edd Smart Sync(every day push or pull at 9AM) at $datetime =====" | Out-File -Append "F:\zsbao\Obsidian\ScheduledSynchronizationShell\logs\obsidian_sync_log.txt"

现在脚本已经设置完毕,接下来我们利用 windows 操作系统的内置的任务计划程序 (Task Scheduler),即定时任务工具,来设置定时任务

首先按 Win + R 打开“运行”,输入

 taskschd.msc

进入任务计划程序,点击右侧创建基本任务

填写任务名称,描述

填写触发器相关内容(这里笔者是希望每天都进行) 注意是每隔 1 天发生一次,开始时间电脑会自动填写你创建的当前时间 然后填写定时任务的操作,由于我们是运行脚本,因此选择启动程序

点击下一页后进入具体执行内容的填写完界面

其中填写内容为

程序:powershell

添加参数:-ExecutionPolicy Bypass -File "电脑中同步脚本的目录位置\sync_to_github.ps1",例如 -ExecutionPolicy Bypass -File "F:\zsbao\Obsidian\ScheduledSynchronizationShell\sync_to_github.ps1"

点击完成

笔者希望每天的 12:00,18:00,21:30电脑自动推送内容到远程仓库,每天的 9:30自动从远端拉取,因此笔者创建了 4 个定时任务

bug

在运行一段时间后,笔者突然发现,有一段时间并没有正确推送 查看日志记录文件发现有报错

 Push failed: fatal: unable to access 'https://github.com/xxxx/ObsidianNote.git/': Recv failure: Connection was reset

这是一个典型的 HTTPS 连接被中途重置 问题(网络/代理/证书/HTTP2 兼容性等都会触发)

这种错误一般都是我们在推送是,推送的地址使用的是仓库的 HTTPS 所造成的问题

这里我们在配置好本地与 github 的 ssh 密钥后 进入本地仓库对应的文件夹,一般里面有个. git 目录

我们把远程地址换成 SSH 的对应地址 PowerShell 里执行执行以下命令

 # 1) 进到仓库目录
 cd F:\zsbao\Obsidian\WareHouse
 ​
 # 2) 看看现在的远端
 git remote -v
 ​
 # 3) 改成 SSH 形式(关键一步)
 git remote set-url origin [email protected]:xxxx/ObsidianNote.git
 ​
 # 4) 再确认
 git remote -v
 ​

修改后,问题解决。