Press can sync users notes through a git repository. Instead of locking them into a proprietary system, their notes are theirs to own. The notes are saved as standard markdown (.md
) files so that they can be accessed on devices where using Press isn't possible or desired. By using git as the underlying sync mechanism, Press is also able to offer users a version history that can be used for recovering accidental edits or deletions by the user as well as Press (because syncing is hard).
GitHub is currently the only available git host, but contributions for adding new hosts are welcome. If you're interested, add a new enum here and let the compilation errors guide you.
Press primarily treats git as a tool for syncing files and not for storing them (which is handled using SQLite). On every sync,
- The git directory is reset to the
last-pushed SHA1
(if present). Any unsynced or dirty changes are discarded. Each sync is treated as a transaction. If Press enters an unexpected state, the git directory is reset to the last good state. - When syncing for the first time, all local notes are backed up in a separate branch. If Press makes any mistakes, this branch can be used for recovering notes.
- Next, upstream note changes are fetched and the local git branch is rebased onto it. At this step, merge conflicts aren't expected because Press ensures they don't happen. More on this in step 5.
- Local changes are fetched from the SQLite database and committed. If Press detects that changes were made to files that were also pulled in step 2, they are outright treated as conflicts. When syncing for the first time, the latest copy is picked by comparing timestamps. For subsequent syncs, the local copy is duplicated as a new note. In case a conflicted note is open on the local device, Press blocks the user from making any further changes to it.
- Committed changes are pushed to remote. If the updates are rejected because remote contains work that Press does not locally, syncing is aborted and all new changes are discarded on the next occurrence of step 1. Press ensures that it's always working with the latest copy of user's notes to avoid merge conflicts.
- All new pulled and committed changes are saved to the SQLite database.
- The HEAD is saved as the
last-synced SHA1
for use in step 1.
Press tries really hard to avoid leaking Press's implementation into user's git repository. This includes using human readable filenames for saving notes, generated from notes' H1 headings. Considering that multiple notes can have the same heading (e.g., Shopping list
), Press maintains a canonical directory for mapping unique file names (e.g., shopping_list.md
, shopping_list_2.md
) with their SQLite IDs.
See FileNameRegisterTest for more info.
-
Press's way of detecting conflicts is very rudimentary. It could use git's recursive strategy for auto-merging conflicts.
-
Press stores a repository's entire git history on all devices. For repositories with a lot of notes, their size can grow large and potentially take a lot of space. It'd be nice to only maintain a shallow copy of repositories.