Scrivener and git (or github)

Is there a way to use Scrivener together with git for collaborative writing?

You would need to use the Sync with External Folder functionality to create a git repository outside of the Scrivener project. There are no supported ways to directly edit Scrivener projects other than Scrivener itself.

Katherine

Even if you decided to go the unsupported route and try it for yourself, know that you’re wading into deep technical water.

The whole strength of git is allowing multiple people to work on the same files without having to check them out, where those files are loosely coupled. Since most programming format are text-based, Git’s conflict-resolution algorithms are usually good enough to do the right thing; figure out if the same files (and same areas of the files) were edited once you commit your changes. If not, it can seamlessly merge them; if so, you get to resolve them manually before you get to actually commit the conflicting edit.

Scrivener’s internal file format is a mixture of XML, RTF, and text files. What’s going to really trip you up is the RTF files – any tiny change to one of those and git will be able to detect that the file changed but it won’t be able to parse which chunk changed. In addition, git doesn’t understand the relationship between the various files that it DOES understand – so its conflict resolution mechanism is liable to get things wrong.

It’s incredibly difficult, if not impossible; I’m a pretty seasoned git user, and so is my co-writer, and we tried pretty hard to make it work, and it was just …a nightmare.

You have the advantage that RTF is, under the hood, a plaintext format. That is, the actual bytes on disk are plaintext; if you open an rtf file up in any plaintext editor (such as VS Code or TextMate) you can see this. So in my experience, git’s diff algorithm is able to work fine, and you don’t have bloat in repos because you’re not uploading a bunch of binaries.

I personally have been keeping my Scrivener projects in git for a while, and have had no real issues—however, I am also not collaborating with someone else. Dealing with conflicts in collaboration might be a trick.

That said, it really helps to have a good gitignore, so you can avoid checking in extremely volatile files. Here is the relevant bit of mine:

*.scriv/Files/binder.autosave
*.scriv/Files/binder.backup
*.scriv/Files/search.indexes
*.scriv/Files/user.lock
*.scriv/Files/Docs/docs.checksum
*.scriv/Files/Data/docs.checksum
*.scriv/QuickLook/
*.scriv/Settings/ui.plist

You’ll still end up with changes every time you open a file (I find it interesting to do a diff to see what it is; mostly tracking the document stack and UI state), but you should be able to manage that well enough.

Hopefully that helps.

I was wondering about using it like this also – just for myself, for both backup and change control purposes. How do you find this works for you? I love the idea of:

  1. Being able to back up the project without having to create a whole big zip file every time (my current project file is 11 MB and that’s with only text, no images/media).
  2. Tracking lifecycle of project or chapters/scenes using git features (tags/branches or even just commit comments), for example “1st pass revision done”.

Do you find it works okay for that? I was worried about the RTFs not comparing well but maybe, like you say, it will work all right as they are a kind of marked-up plaintext.

My primary reason for using git is the backup and distribution capabilities. If something happens to my personal computer, I know that I can always just clone the repo somewhere else, and just pick it back up. I can even do a distributed backup, and have some other machine regularly fetch the repo, and know that it’s on there.

My secondary reason is seeing dates that I worked on things. While this does happen inside of Scrivener, I also will put several smaller projects in one repo, so I can kind of see the interleaving—and I can also track changes in things outside of the Scrivener project itself, such as ancillary scripts and the like.

A downside is that images don’t play as nicely with git, but my repo provider has LFS, so I just take advantage of that.

The RTFs compare fine; you can play with this yourself if you just create a new repo and make an rtf file in it, make a commit, then change the file and save, and diff the changes. It really is just a plaintext format under the hood.

In practice, I never look at those changes, though—it’s mostly a space-saving measure.

As for tracking lifecycle itself, I would highly caution against branches or any fancy git stuff. Code is easy to resolve conflicts on—while the RTF documents themselves might not be too bad on this, Scrivener has a host of other files that it uses, and managing conflicts with those would be Not Fun. Tags may be useful for tracking some things, but again, I’d advise caution. Git works really well for the backup part, but these are not code files; in a lot of ways, you should probably just consider your Scrivener project as a binary file in this regard, and treat it in source control the way you would treat any other binary file. It just has the advantage of actually being plaintext under the hood for efficiency’s sake.

My commit messages are usually unhelpful. “Write” or “Write Teapot” (when differentiating different projects in one repo)

Make sure to also use the gitignore lines given above.

Using git with Scrivener is very much not a supported thing, and probably ill-advised unless you 1) know what you’re doing with git, and 2) only plan on using it within a very small, well-defined scope. While I have found it personally useful, it’s not something I would generally recommend to other authors.

And, as noted, it’s probably a nightmare for collaboration.

Thanks! I’ve been using it for the last year and it’s been fantastic! I use it for backup like you, and also for a change history. The RTF compares aren’t great but still workable (you have to learn to ignore all the weird RTF markup). It’s really great when doing revision as you can see what you changed in a particular scene, when, and why (assuming you made a decent commit comment).