NeoGDSync

by martinlegend
5
4
3
2
1
Score: 28/100

Description

neo google drive sync for Obsidian

Reviews

No reviews yet.

Stats

7
stars
1,594
downloads
2
forks
118
days
46
days
46
days
5
total PRs
1
open PRs
1
closed PRs
3
merged PRs
1
total issues
1
open issues
0
closed issues
50
commits

Latest Version

2 months ago

Changelog

Fixes a bug where two devices syncing the same vault could end up with two Drive files sharing the exact same name and path — silently, with zero conflict ever reported.

What happened

handlePush() decides how to push a pending create/modify op. When the local path index has no entry for that path, it's supposed to first check whether Drive already has a file with that name in the target folder (findOnDrive()) before deciding whether to update the existing file or upload a new one. That safety net was added in 1.0.9 for modify ops (an index-loss recovery case) — but create ops never got it, and just uploaded unconditionally.

A create op fires whenever a device's local index has no record of a path yet — which includes the case where another device already pushed that exact file to Drive, and this device simply hasn't learned about it. Since conflict detection only compares Drive changes against paths already present in the local index, a path with no index entry never enters that check either. Two devices could therefore push the same filename through two completely different, conflict-free code paths and end up with two Drive objects.

Reproduced 2026-08-06/07: a note was edited on a Mac (auto-pushed via a scheduled Smart Sync) and independently re-created on an iPad before the iPad's index had ever seen that path. Both devices' Smart Sync runs reported zero conflicts. Drive ended up holding two files at the same path: 2026/2026.08.06 Communication with Leo on ETHSystem.md (10Cm8T3BLFyyjIZ1F9jC7v_dXGtfeIUR0 and 1uOmTJX4ZmyBAZbdbSnQLlOvr4mst0OvQ), confirmed via a direct Drive API files.list query scoped to the vault's 2026 folder.

Fix

  • syncer.ts: handlePush() now runs findOnDrive() for both create and modify ops before deciding to upload vs. update. findOnDrive() already resolves duplicates deterministically (prefers the index-cached id, else the most recently modified same-name file) — no new duplicate-resolution logic was needed, just closing the gap in which op types used it.
  • tests/syncer.test.ts (new — syncer.ts had no test coverage before this): asserts a create op with no index entry updates an existing same-name Drive file instead of uploading a duplicate, and that a genuinely new filename still uploads normally.

Upgrade notes

This prevents new duplicates from forming; it does not scan for or merge duplicates that already exist in a vault from before this version. If a device's index goes stale for long enough that it stops recognizing paths another device owns, re-running "Rebuild Drive Index" keeps both devices' views of Drive in sync and avoids relying on findOnDrive()'s per-path fallback lookup.

README file from

Github

Lightweight Google Drive sync plugin for Obsidian.

Features

  • Smart Sync — auto conflict detection, only syncs changed files
  • Force Push — local vault → Google Drive
  • Force Pull — Google Drive → local vault
  • Conflict handling — saves Drive copy as a conflict file, never overwrites silently
  • Path-based index — fast, no full crawl needed after first sync
  • Version history — optionally keep file revisions on Drive
  • Configurable excludes — glob patterns to skip files/folders
  • URI handlerobsidian://neogdsync?mode=smart|push|pull for automation

Setup

  1. Install the plugin
  2. Go to Settings → NeoGDSync
  3. Enter your Google OAuth2 Refresh Token
  4. Enter your Google Drive Vault Root Folder ID (the Drive folder that maps to your vault root)
  5. Click the ☁ ribbon icon or run a command to sync

Getting a Refresh Token

This plugin uses a standard OAuth2 refresh token with read/write access to Google Drive.

You can obtain one via:

The refresh token is stored locally in your vault's plugin data. To obtain short-lived access tokens, the plugin sends the refresh token to an OAuth proxy (by default the NeoGDSync Cloudflare Worker, see oauth-proxy/worker.js), which exchanges it with Google and returns the access token. The proxy does not store tokens. If you prefer not to route through the shared proxy, deploy your own Worker (instructions in oauth-proxy/worker.js) and set its URL in Settings → NeoGDSync → Auth proxy URL.

Commands

Command Description
Smart Sync Detect and sync only changed files, with conflict detection
Force Push Upload all local changes to Drive
Force Pull Download all Drive changes to local
Rebuild Drive Index Re-crawl Drive vault folder to rebuild index
Show Conflicts View detected conflicts

URI Handler

Trigger sync from outside Obsidian (Shortcuts, scripts, etc.):

obsidian://neogdsync?mode=smart
obsidian://neogdsync?mode=push
obsidian://neogdsync?mode=pull

License

MIT