git自动同步obsidian

背景

入坑obsidian做笔记有一年多了,obsidian哪里都好,就是同步稍显麻烦,图片开了个阿里的oss,搭建了图床,算初步解决。数据同步方案折腾了一大堆,最后还是回到了git。平平淡淡才是真啊。但是每天手动提交,还得写上对笔记来说没那么重要的commit message,多少有点浪费时间。一时半会还行,时间久了还真是有些烦人。

解决方案

python + git + 批处理

GitPython

GitPython允许我们使用git命令来操作git仓库

安装

bash 复制代码
pip install gitpython

封装一个GitSync

python 复制代码
import git

class GitSync():
    def __init__(self, rep_path):
        log.info("rep_path:%s" % rep_path)
        # 判断rep_path是否为Path对象
        if not isinstance(rep_path, Path):
            log.error("rep_path is not Path object")
            raise Exception("rep_path is not Path object")
        # 判断rep_path是否为git仓库
        if not Path(rep_path).joinpath(".git").exists():
            log.error("not git repository")
            raise Exception("not git repository")
        self.rep_path = str(rep_path)
        self.repo = git.Repo(rep_path)

    def check_status(self):
        status = self.repo.git.status()
        if "nothing to commit, working tree clean" in status:
            return True
        else:
            return False

    def auto_commit(self):
        self.repo.git.add(".")
        # 获取当前时间
        now = datetime.now()
        # 格式化时间
        now = now.strftime("%Y-%m-%d %H:%M:%S")
        self.repo.git.commit("-m", "auto commit at %s" % now)
        self.repo.git.push()
        log.info("auto commit success")

    def pull(self):
        # 判断拉取是否存在冲突
        try:
            self.repo.git.pull()
            log.info("pull success")
            return True
        except git.exc.GitCommandError as e:
            log.error(e)
            log.error("pull error")
            return False

    def push(self):
        self.repo.git.push()
        log.info("push success")

为了扩展和方便使用,我们引入命令行,没有传入则使用当前路径作为git仓库

python 复制代码
import argparse

if __name__ == '__main__':
    # 创建一个ArgumentParser对象
    parser = argparse.ArgumentParser(description="git auto commit tool")
    parser.add_argument("--rep", type=str, default="", help="path of repository")
    # 解析命令行参数
    args = parser.parse_args()
    if args.rep:
        rep_path = Path(args.rep)
    else:
        rep_path = Path(__file__).parent.absolute()

搭配批处理

bat 复制代码
D:\dev\Anaconda\pythonw.exe D:\code\gitee\obsidian\git自动提交.py
pause

这里介绍一下pythonw

pythonw 是 Python 安装过程中在 Windows 系统上安装的一个可执行文件,它的作用与 python 类似,但有一些关键的区别:

  1. 无控制台窗口 :当你运行 pythonw.exe 时,它不会创建一个新的控制台窗口来显示输出或错误信息。这对于 GUI 应用程序或那些你不希望用户看到控制台窗口的脚本非常有用。
  2. 图形界面应用程序pythonw 通常用于运行没有控制台窗口的 Python GUI 应用程序。例如,使用 Tkinter 或 PyQt 等库创建的应用程序。
  3. 后台运行 :由于没有控制台窗口,使用 pythonw 运行的脚本适合作为后台进程运行,不会干扰用户的其他操作。
  4. 脚本运行 :如果你有一个 Python 脚本,你希望它在没有控制台窗口的情况下运行,你可以双击该脚本文件,或者在开始菜单中选择它,Python 会使用 pythonw 来运行它。
  5. 环境变量 :在 Windows 上,可以通过设置环境变量 PYTHONW_DEFAULT 来让双击 .py 文件时默认使用 pythonw.exe 运行。

这样我们可以将脚本放置在仓库根目录,并发送到桌面快捷方式,双击则可以自动同步并提交。如果有多台电脑,同步起来也异常方便。

完整代码

python 复制代码
import argparse
import git
import logging as log
from pathlib import Path
from datetime import datetime

log.basicConfig(level=log.INFO, format='%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s')


class GitSync():
    def __init__(self, rep_path):
        log.info("rep_path:%s" % rep_path)
        # 判断rep_path是否为Path对象
        if not isinstance(rep_path, Path):
            log.error("rep_path is not Path object")
            raise Exception("rep_path is not Path object")
        # 判断rep_path是否为git仓库
        if not Path(rep_path).joinpath(".git").exists():
            log.error("not git repository")
            raise Exception("not git repository")
        self.rep_path = str(rep_path)
        self.repo = git.Repo(rep_path)

    def check_status(self):
        status = self.repo.git.status()
        if "nothing to commit, working tree clean" in status:
            return True
        else:
            return False

    def auto_commit(self):
        self.repo.git.add(".")
        # 获取当前时间
        now = datetime.now()
        # 格式化时间
        now = now.strftime("%Y-%m-%d %H:%M:%S")
        self.repo.git.commit("-m", "auto commit at %s" % now)
        self.repo.git.push()
        log.info("auto commit success")

    def pull(self):
        # 判断拉取是否存在冲突
        try:
            self.repo.git.pull()
            log.info("pull success")
            return True
        except git.exc.GitCommandError as e:
            log.error(e)
            log.error("pull error")
            return False

    def push(self):
        self.repo.git.push()
        log.info("push success")


if __name__ == '__main__':
    # 创建一个ArgumentParser对象
    parser = argparse.ArgumentParser(description="git auto commit tool")
    parser.add_argument("--rep", type=str, default="", help="path of repository")
    # 解析命令行参数
    args = parser.parse_args()
    if args.rep:
        rep_path = Path(args.rep)
    else:
        rep_path = Path(__file__).parent.absolute()
    sync = GitSync(rep_path)
    nothing_status = sync.check_status()
    if nothing_status:
        log.info("nothing to commit, working tree clean")
    else:
        res = sync.pull()
        if not res:
            log.error("pull error")
            raise Exception("pull error")
        sync.auto_commit()
相关推荐
烛阴6 小时前
简单入门Python装饰器
前端·python
好开心啊没烦恼6 小时前
Python 数据分析:numpy,说人话,说说数组维度。听故事学知识点怎么这么容易?
开发语言·人工智能·python·数据挖掘·数据分析·numpy
面朝大海,春不暖,花不开6 小时前
使用 Python 实现 ETL 流程:从文本文件提取到数据处理的全面指南
python·etl·原型模式
2301_805054567 小时前
Python训练营打卡Day59(2025.7.3)
开发语言·python
万千思绪8 小时前
【PyCharm 2025.1.2配置debug】
ide·python·pycharm
&Sinnt&9 小时前
Git 版本控制完全指南:从入门到精通
git·后端
微风粼粼9 小时前
程序员在线接单
java·jvm·后端·python·eclipse·tomcat·dubbo
云天徽上10 小时前
【PaddleOCR】OCR表格识别数据集介绍,包含PubTabNet、好未来表格识别、WTW中文场景表格等数据,持续更新中......
python·ocr·文字识别·表格识别·paddleocr·pp-ocrv5
你怎么知道我是队长10 小时前
python-input内置函数
开发语言·python
叹一曲当时只道是寻常10 小时前
Python实现优雅的目录结构打印工具
python