A dark slide headed 'One source. Web, PDF, editable PowerPoint. It can't drift.' with three tiles: 3 formats, 2-way import and export, and MCP.
From the YC demo-day example deck, rendered with slaide.

How to Version Control Your Presentations With Git

Putting a .pptx in a git repo beats emailing “final_v3_REAL_final.pptx” around a team. Git takes the file happily. It just cannot do much with it.

git log shows who committed and when. git diff shows nothing useful, because git prints “Binary files differ” for a path it treats as binary. A .pptx is a zip package with one XML file per slide, plus images. Nobody can look at a pull request and say “the pricing slide changed, the rest didn’t” without opening both files side by side.

Why binary decks break git

Git is built around line-based diffs of text. A .pptx, a .key or a .pdf export is not text, so git shows “binary files differ” and stores the whole changed file again. Your repo grows with every save, and your diff view is useless for review.

The options

Store the binary, diff nothing. This is the default, because nobody set anything else up. It works exactly as well as it sounds.

Export-and-diff scripts. Git itself offers a way to do this. A textconv filter converts a binary file to text before the diff. A tool like pptx2md, which converts a .pptx to Markdown, could feed it. You then maintain a script whose whole job is working around the file format. I have not tried this setup.

Plain text formats. Marp turns Markdown into slides. Slaide uses its own plain-text .slaide format. The deck source is text from the start, so there is nothing to export. This is the option I prefer.

What a diff looks like

Here is a diff of a pricing slide in a text deck. The numbers are made up:

 ## Pricing
 
-Starter: $29/mo, up to 5 seats
-Team: $99/mo, up to 25 seats
+Starter: $29/mo, up to 5 seats
+Team: $79/mo, up to 25 seats
+Enterprise: custom, unlimited seats

Two lines changed, one line added. A reviewer sees exactly that and nothing else. No image bytes, no XML noise. The same change in a .pptx tends to get a review comment like “looks fine I guess” from someone who opened the file, glanced at the slide, and closed it again.

Why this matters beyond diffing

A text deck reviews like code: it is line-addressable, greppable and mergeable. Two people can edit different slides in the same file, and git can usually merge the change, the same as for a config file. Two people in the same .pptx end up asking who has it open, and a merge that means “throw one version away.”

It also means the deck can be generated. A weekly report deck built from a script, a customer deck built from a template plus data: none of that works when the source format needs a GUI to write.

Where I landed

Slaide decks are .slaide files: Markdown for the words, with a small config block at the top that points to a theme. The getting started guide describes the format. You export from the CLI:

slaide export deck.slaide --pdf deck.pdf
slaide export deck.slaide --pptx deck.pptx

The CLI reference says the .pptx export has real text, shapes and images. So when someone asks for “the PowerPoint,” you have one to send. Export uses headless Chromium, so install it once with npx playwright install chromium. The deck itself stays in git the whole time, and the diff shows what changed.

A tool that tracks changes and then cannot show you the change has not given you version control. It has given you a backup folder with extra steps. You can try Slaide on a deck of your own.