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()
相关推荐
秋难降10 分钟前
Python 知识点详解(三)
python·编程语言
chao_7891 小时前
二分查找篇——寻找旋转排序数组中的最小值【LeetCode】
python·线性代数·算法·leetcode·矩阵
金玉满堂@bj1 小时前
PyCharm 中 Python 解释器的添加选项及作用
ide·python·pycharm
程序员三藏1 小时前
如何使用Pytest进行测试?
自动化测试·软件测试·python·测试工具·职场和发展·测试用例·pytest
随心点儿2 小时前
使用python 将多个docx文件合并为一个word
开发语言·python·多个word合并为一个
不学无术の码农2 小时前
《Effective Python》第十三章 测试与调试——使用 Mock 测试具有复杂依赖的代码
开发语言·python
sleepybear11132 小时前
在Ubuntu上从零开始编译并运行Home Assistant源码并集成HACS与小米开源的Ha Xiaomi Home
python·智能家居·小米·home assistant·米家·ha xiaomi home
纪伊路上盛名在2 小时前
(鱼书)深度学习入门1:python入门
人工智能·python·深度学习
夏末蝉未鸣012 小时前
python transformers笔记(TrainingArguments类)
python·自然语言处理·transformer
德育处主任Pro2 小时前
「py数据分析」04如何将 Python 爬取的数据保存为 CSV 文件
数据库·python·数据分析