Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
217 changes: 93 additions & 124 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,176 +1,145 @@
<div align="center">

# Git File Sync
*Selective, file-by-file sync between your vault and GitHub, GitLab, or Gitea.*

[![CI](https://img.shields.io/github/actions/workflow/status/firstsun-dev/git-files-sync/ci.yml?branch=main&style=flat-square)](https://github.com/firstsun-dev/git-files-sync/actions/workflows/ci.yml)
[![Release](https://img.shields.io/github/v/release/firstsun-dev/git-files-sync?style=flat-square)](https://github.com/firstsun-dev/git-files-sync/releases)
[![Downloads](https://img.shields.io/github/downloads/firstsun-dev/git-files-sync/total?style=flat-square)](https://github.com/firstsun-dev/git-files-sync/releases)
[![Obsidian](https://img.shields.io/badge/Obsidian-v0.15.0+-purple?style=flat-square)](https://obsidian.md)
[![TypeScript](https://img.shields.io/badge/TypeScript-5.8-blue?style=flat-square&logo=typescript&logoColor=white)](https://www.typescriptlang.org/)
[![Conventional Commits](https://img.shields.io/badge/Conventional%20Commits-1.0.0-yellow.svg?style=flat-square)](https://conventionalcommits.org)
[![License](https://img.shields.io/github/license/firstsun-dev/git-files-sync?style=flat-square)](LICENSE)
[![CI](https://img.shields.io/github/actions/workflow/status/firstsun-dev/git-files-sync/ci.yml?branch=main&style=for-the-badge)](https://github.com/firstsun-dev/git-files-sync/actions/workflows/ci.yml)
[![Release](https://img.shields.io/github/v/release/firstsun-dev/git-files-sync?style=for-the-badge&color=2ea44f)](https://github.com/firstsun-dev/git-files-sync/releases)
[![Downloads](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fraw.githubusercontent.com%2Fobsidianmd%2Fobsidian-releases%2Fmaster%2Fcommunity-plugin-stats.json&query=%24%5B%22git-file-sync%22%5D.downloads&label=downloads&style=for-the-badge&color=007acc)](https://obsidian.md/plugins?id=git-file-sync)
[![License](https://img.shields.io/github/license/firstsun-dev/git-files-sync?style=for-the-badge)](LICENSE)

**Supports:**
<img src="https://img.shields.io/badge/GitHub-181717?style=flat-square&logo=github&logoColor=white" alt="GitHub" height="20">
<img src="https://img.shields.io/badge/GitLab-FC6D26?style=flat-square&logo=gitlab&logoColor=white" alt="GitLab" height="20">
<img src="https://img.shields.io/badge/Gitea-609926?style=flat-square&logo=gitea&logoColor=white" alt="Gitea" height="20">
**[Releases](https://github.com/firstsun-dev/git-files-sync/releases)** · **[繁體中文使用說明](USAGE_zh.md)** · **[Changelog](CHANGELOG.md)**

**Git File Sync** is a powerful Obsidian plugin that enables seamless synchronization of individual notes with GitLab, GitHub, or self-hosted Gitea repositories. Unlike full-vault sync solutions, it gives you granular control over what gets pushed and pulled, making it perfect for shared projects, selective backups, and cross-platform workflows.
</div>

[繁體中文使用說明](USAGE_zh.md)
Push, pull, diff, and resolve conflicts — file by file, not whole-vault. Unlike full-vault sync solutions, Git File Sync gives you granular control over exactly what leaves your device, so you can keep personal notes private while sharing project files through a real Git repository.

[git-file-sync](https://github.com/user-attachments/assets/78f383be-e8a4-4c9c-8845-1f46d06ea661)
<img src="https://img.shields.io/badge/GitHub-181717?style=flat-square&logo=github&logoColor=white" alt="GitHub" height="20"> <img src="https://img.shields.io/badge/GitLab-FC6D26?style=flat-square&logo=gitlab&logoColor=white" alt="GitLab" height="20"> <img src="https://img.shields.io/badge/Gitea-609926?style=flat-square&logo=gitea&logoColor=white" alt="Gitea" height="20">

![sync-status](imgs/sync-status.png)
*The Sync Status View provides a clear overview of your files, allowing you to selectively push, pull, or view diffs for modified files.*
<video src="https://blog-assets.firstsun.org/obsidian/plugins/git-file-sync/git-file-sync-en.webm" autoplay loop muted playsinline width="600"></video>

![conflict](imgs/git-diff.png)
*The Built-in Diff Viewer lets you compare local and remote changes side-by-side before syncing.*

---

## Supported Providers

<img src="https://img.shields.io/badge/GitHub-181717?style=for-the-badge&logo=github&logoColor=white" alt="GitHub" height="28"> &nbsp;
<img src="https://img.shields.io/badge/GitLab-FC6D26?style=for-the-badge&logo=gitlab&logoColor=white" alt="GitLab" height="28"> &nbsp;
<img src="https://img.shields.io/badge/Gitea-609926?style=for-the-badge&logo=gitea&logoColor=white" alt="Gitea" height="28">

| Provider | Hosting | Min. Version |
| :--- | :--- | :--- |
| <img src="https://img.shields.io/badge/GitHub-181717?style=flat-square&logo=github&logoColor=white" alt="GitHub"> | github.com · GitHub Enterprise | — |
| <img src="https://img.shields.io/badge/GitLab-FC6D26?style=flat-square&logo=gitlab&logoColor=white" alt="GitLab"> | gitlab.com · self-hosted | GitLab 13.0+ |
| <img src="https://img.shields.io/badge/Gitea-609926?style=flat-square&logo=gitea&logoColor=white" alt="Gitea"> | self-hosted | Gitea 1.12+ |
![sync-status](imgs/sync-status.png)
*The Sync Status View gives a bird's-eye view of your vault, letting you selectively push, pull, or diff modified files.*

> **Gitea compatibility note**: The plugin uses the Gitea API v1 (`/api/v1`). It resolves branch names to commit SHAs before fetching the file tree, which ensures compatibility with Gitea 1.12 and later. Versions before 1.12 are not supported.
## What's inside

---
- **File-by-file control** — Sync individual notes or whole folders, not your entire vault. No lock-in to a single sync provider for everything.
- **Three Git providers** — GitHub, GitLab (including self-hosted), and Gitea, all behind one consistent UI.
- **Visual diffing** — A built-in diff viewer compares local and remote versions side-by-side before anything is overwritten.
- **Conflict resolution** — When local and remote both changed, resolve manually with a dedicated conflict tool instead of guessing which version wins.
- **Works on mobile** — Full support for Obsidian Mobile with a touch-friendly sync dashboard.

## Key Features
## Sync Status View

### Selective Synchronization
Don't sync your whole vault. Selectively push or pull individual notes, or use batch operations for specific folders. Perfect for keeping personal notes private while sharing project files.
A single dashboard shows the state of every tracked file:

### Visual Sync Dashboard
A comprehensive dashboard provides a bird's-eye view of your vault's status:
- **Status Filtering**: Instantly see what's modified, new, or missing.
- **Visual Diffs**: Compare local and remote changes line-by-line before syncing.
- **Remote-Only Detection**: Identify files existing on GitLab/GitHub/Gitea that aren't in your vault yet.
- **Status filtering** — instantly see what's modified, new, or missing.
- **Visual diffs** — line-by-line comparison of local vs. remote before syncing.
- **Remote-only detection** — spot files that exist on GitHub/GitLab/Gitea but haven't been pulled into the vault yet.

### Intelligent Conflict Resolution
When versions clash, Git File Sync provides a dedicated diff viewer to help you resolve conflicts manually. Choose the local version, the remote version, or merge them with confidence.
![conflict](imgs/git-diff.png)
*The built-in diff viewer compares local and remote changes before you push or pull.*

### Mobile First
Full support for Obsidian Mobile. Push and pull your notes on the go with a responsive UI designed specifically for touch interfaces.
## Providers

---
| Provider | Hosting | Min. version |
|---|---|---|
| <img src="https://img.shields.io/badge/GitHub-181717?style=flat-square&logo=github&logoColor=white" alt="GitHub"> | github.com · GitHub Enterprise | — |
| <img src="https://img.shields.io/badge/GitLab-FC6D26?style=flat-square&logo=gitlab&logoColor=white" alt="GitLab"> | gitlab.com · self-hosted | GitLab 13.0+ |
| <img src="https://img.shields.io/badge/Gitea-609926?style=flat-square&logo=gitea&logoColor=white" alt="Gitea"> | self-hosted | Gitea 1.12+ |

## Installation
> **Gitea note:** the plugin talks to the Gitea API v1 (`/api/v1`) and resolves branch names to commit SHAs before fetching the file tree, which is what makes 1.12+ the floor.

### From Community Plugins (Recommended)
1. Open **Obsidian Settings** > **Community plugins**.
2. Click **Browse** and search for `Git File Sync`.
3. Click **Install**, then **Enable**.
## Configuration

### Manual Installation
1. Download the latest `main.js`, `manifest.json`, and `styles.css` from the [Releases](https://github.com/firstsun-dev/git-files-sync/releases) page.
2. Create a folder named `git-file-sync` in `<vault>/.obsidian/plugins/`.
3. Copy the downloaded files into that folder.
4. Reload Obsidian and enable the plugin.
![Plugin Settings](imgs/plugin-settings.png)
*Pick a provider and supply its credentials in Settings > Git File Sync.*

---
| | Provider | Required info | Token scope |
|:---:|---|---|---|
| <img src="https://img.shields.io/badge/GitHub-181717?style=flat-square&logo=github&logoColor=white" alt="GitHub"> | **GitHub** | Personal access token, owner, repo name | `repo` |
| <img src="https://img.shields.io/badge/GitLab-FC6D26?style=flat-square&logo=gitlab&logoColor=white" alt="GitLab"> | **GitLab** | Personal access token, project ID, base URL | `api` |
| <img src="https://img.shields.io/badge/Gitea-609926?style=flat-square&logo=gitea&logoColor=white" alt="Gitea"> | **Gitea** | Personal access token, base URL, owner, repo name | (all) |

## Configuration
- **GitHub token:** Settings → Developer settings → Personal access tokens → `repo` scope.
- **GitLab token:** User settings → Access tokens → `api` scope. Base URL defaults to `https://gitlab.com`; change it for self-hosted instances.
- **Gitea token:** User settings → Applications → Access tokens. Point the base URL at your instance (e.g. `https://gitea.example.com`).

![Plugin Settings](imgs/plugin-settings.png)
*Configure the plugin by selecting your preferred Git service and providing the necessary credentials.*
Other settings: **branch** to sync against (default `main`), **root path** prefix inside the repo, **vault folder** to scope which notes are tracked, and **symbolic link handling** (*real* — recreate the link, GitHub only; *follow* — sync the target's content; *skip*). See [Symbolic link handling](docs/symlink-handling.md) for details.

### 1. Choose Your Service
Go to **Settings** > **Git File Sync** and select **GitLab**, **GitHub**, or **Gitea** from the dropdown.
## Daily workflow

### 2. Provider Setup
**Pushing:**
- One note — the cloud icon in the ribbon, or the command `Push current file to GitLab/GitHub/Gitea`.
- Several notes — open the Sync Status View, filter to **Modified**, select files, click **Push selected**.
- From the file tree — right-click any file and choose `Push to GitLab/GitHub/Gitea`.

| | Provider | Required Info | Token Scope |
| :---: | :--- | :--- | :--- |
| <img src="https://img.shields.io/badge/GitHub-181717?style=flat-square&logo=github&logoColor=white" alt="GitHub"> | **GitHub** | Personal Access Token, Owner, Repo Name | `repo` |
| <img src="https://img.shields.io/badge/GitLab-FC6D26?style=flat-square&logo=gitlab&logoColor=white" alt="GitLab"> | **GitLab** | Personal Access Token, Project ID, Base URL | `api` |
| <img src="https://img.shields.io/badge/Gitea-609926?style=flat-square&logo=gitea&logoColor=white" alt="Gitea"> | **Gitea** | Personal Access Token, Base URL, Owner, Repo Name | (all) |
**Pulling:**
1. Open the Sync Status View and click **Refresh status**.
2. Files with remote updates show as **Modified** or **Remote only**.
3. Select them and click **Pull selected**. Pulling overwrites local changes — if both sides changed, the conflict tool opens instead.

**GitHub token**: Settings → Developer settings → Personal access tokens → `repo` scope.
**Resolving a conflict:**
1. The Conflict Resolution window opens automatically.
2. Left pane is your **Local** version, right pane is **Remote**.
3. Choose **Keep Local** (overwrite remote on next push) or **Keep Remote** (accept remote, overwrite local).

**GitLab token**: User settings → Access tokens → `api` scope. The Base URL defaults to `https://gitlab.com`; change it for self-hosted instances.
**On mobile:** swipe from the left to open the ribbon and the Sync Status View, pull before you start editing, push when you're done.

**Gitea token**: User settings → Applications → Access tokens. Set the Base URL to your Gitea instance (e.g. `https://gitea.example.com`).
## Installation

### 3. Common Settings
- **Branch**: Specify the target branch (default: `main`).
- **Root Path**: Prefix for files in the repository (e.g., `notes/`).
- **Vault Folder**: Limit sync to a specific folder in your vault.
- **Symbolic links**: Choose how symlinks are synced — *real* (recreate the link, GitHub only), *follow* (sync the target's content), or *skip*. See [Symbolic link handling](docs/symlink-handling.md).
### From Community Plugins (recommended)
1. Open **Settings > Community plugins** and turn off restricted mode.
2. Click **Browse**, search for **Git File Sync**, click **Install**, then **Enable**.

---
### Manual
1. Download `main.js`, `manifest.json`, and `styles.css` from the [latest release](https://github.com/firstsun-dev/git-files-sync/releases/latest).
2. Create `<vault>/.obsidian/plugins/git-file-sync/`.
3. Copy the three files into that folder.
4. Reload Obsidian and enable the plugin under **Settings > Community plugins**.

## Usage Guide
## Quick start

### First-Time Setup
Once configured, you should perform an initial status check:
1. Open the **Sync Status View** by clicking the list icon in the left ribbon or using the Command Palette (`Open sync status view`).
2. Click **Refresh status**. The plugin will compare your local files with the remote repository.
3. Review the file list to see which files are synchronized, modified, or missing.
1. Configure a provider in **Settings > Git File Sync** (see [Configuration](#configuration)).
2. Open the **Sync Status View** — the list icon in the ribbon, or run `Open sync status view` from the Command Palette.
3. Click **Refresh status** to compare your vault against the remote repo.
4. Select files and **Push selected** or **Pull selected** as needed.

### Daily Workflow: Pushing Changes
When you finish editing a note and want to save it to Git:
- **Current Note**: Use the cloud icon in the ribbon or the command `Push current file to GitLab/GitHub/Gitea`.
- **Multiple Notes**: Open the Sync Status View, use the **Modified** filter, select the files you want to sync, and click **Push selected**.
- **Context Menu**: Right-click any file in the File Explorer and select `Push to GitLab/GitHub/Gitea`.
**Commands:**

### Daily Workflow: Pulling Changes
To get the latest updates from other devices:
1. Open the Sync Status View and click **Refresh status**.
2. Files with remote updates will show as **Modified** or **Remote only**.
3. Select these files and click **Pull selected**.
4. **Warning**: Pulling will overwrite local changes. If there are conflicts, the Conflict Resolution tool will open.

### Handling Conflicts
If a file has changed both locally and on the remote server:
1. A **Conflict Resolution** window will appear.
2. The left pane shows your **Local** version, and the right pane shows the **Remote** version.
3. Review the differences.
4. Click **Keep Local** to overwrite the remote version on next push, or **Keep Remote** to accept the remote changes and overwrite your local file.

### Mobile Synchronization
On mobile devices:
- Swipe from the left to access the ribbon and open the Sync Status View.
- Use the **Pull** action to keep your mobile vault up to date before editing.
- After editing, use the **Push** action to save your changes back to the repository.
| Command | What it does |
|---|---|
| Open sync status view | Open the sync dashboard |
| Push current file to GitLab/GitHub/Gitea | Push the active note |
| Pull current file to GitLab/GitHub/Gitea | Pull the active note |
| Push all files | Push every tracked, changed file |
| Pull all files | Pull every tracked, changed file |

---
## Privacy and security

## Privacy and Security
- **Local storage** — personal access tokens are stored locally in the plugin's data folder inside your vault, and are only ever sent to the Git provider you configured.
- **No telemetry** — the plugin collects no usage data or analytics.

- **Local Storage**: Your Personal Access Tokens (PAT) are stored locally in the plugin's data folder within your vault. They are never sent to any server other than your configured Git provider.
- **No Telemetry**: This plugin does not collect any data or usage analytics.
## Requirements

---
- Obsidian **1.13.0** or later
- Desktop and mobile supported

## Development

If you want to contribute or build from source:

```bash
# Clone and install
git clone https://github.com/firstsun-dev/git-files-sync.git
npm install

# Development build
npm run dev

# Production build
npm run build
npm run dev # watch build
npm run build # type-check + production build
npm run test # vitest suite
npm run lint # eslint
```

---

## License

This project is licensed under the [MIT License](LICENSE).
MIT

---

Expand Down
7 changes: 6 additions & 1 deletion USAGE_zh.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
# Git File Sync 使用說明書

<video src="imgs/git-file-sync-zh.webm" width="100%" controls autoplay loop muted playsinline></video>
[![CI](https://img.shields.io/github/actions/workflow/status/firstsun-dev/git-files-sync/ci.yml?branch=main&style=for-the-badge)](https://github.com/firstsun-dev/git-files-sync/actions/workflows/ci.yml)
[![Release](https://img.shields.io/github/v/release/firstsun-dev/git-files-sync?style=for-the-badge&color=2ea44f)](https://github.com/firstsun-dev/git-files-sync/releases)
[![Downloads](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fraw.githubusercontent.com%2Fobsidianmd%2Fobsidian-releases%2Fmaster%2Fcommunity-plugin-stats.json&query=%24%5B%22git-file-sync%22%5D.downloads&label=downloads&style=for-the-badge&color=007acc)](https://obsidian.md/plugins?id=git-file-sync)
[![License](https://img.shields.io/github/license/firstsun-dev/git-files-sync?style=for-the-badge)](LICENSE)

<video src="https://blog-assets.firstsun.org/obsidian/plugins/git-file-sync/git-file-sync-zh.webm" width="100%" controls autoplay loop muted playsinline></video>

本指南將引導您如何使用 Git File Sync 插件,在行動裝置與桌面電腦之間,透過 GitLab、GitHub 或自架的 Gitea 輕鬆同步您的筆記。

Expand Down
Loading