Branch:
- New "Branch" text field (default: main) stored in gitSyncBranch on
the project. Used for git fetch, symbolic-ref, and push target.
Validated server-side: alphanumeric + / _ . - only, no ..
First-push confirmation:
- When pushFiles is enabled and the user hasn't confirmed for the
current subPath, clicking "Push now" shows an inline warning:
"The <subPath> directory will be completely replaced …"
with "Yes, push and replace" / "Cancel" buttons.
- Confirmation is stored in localStorage keyed by projectId+subPath,
so it's shown again if the subPath is changed.
- Auto-push bypasses the dialog (user already opted in explicitly).
PDF-only replace:
- Already correct with the fetch-first approach: only the specific
file at pdfPath is written; other files in the same directory
(e.g. output/old.pdf) are preserved from the fetched remote state.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Two new boolean fields on the project (gitSyncPushFiles, gitSyncPushPdf,
both default true) let users control what gets pushed independently:
- "Push project files" switch — skip all docs/binary files when off
- "Push compiled PDF" switch — grayed out when no pdfPath is set
The push button and auto-push are disabled when both switches would
result in nothing being pushed. Config is stored in MongoDB so settings
persist per-project.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Move userId + req.body reads inside try/catch in pushToGit and
pullFromGit so any synchronous throw returns JSON, not an HTML 500
(which made err.data undefined and showed only "Internal Server Error")
- Add extractError() helper in widget that tries err.data.error first,
then err.message, then String(err) — surfaces the actual git failure
message from the server log
- Change rail icon from 'merge' (not in unfilled-symbols list) to
'autorenew' (sync arrows, already in the list) — fixes text showing
when panel is closed and wrong icon when open
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
POST /project/:id/git-sync/pull clones the configured remote at depth 1,
walks all files under the configured subPath, and upserts each into the
Verso project using upsertDocWithPath (text) or upsertFileWithPath
(binary), with full folder creation via mkdirp. The .git directory is
skipped. Pull is additive/update-only — no Verso entities are deleted.
Text vs binary classification uses Settings.textExtensions (same list
the editor uses for file uploads), so .typ, .tex, .md, .yml etc. all
become editable docs while images and PDFs stay as files.
Frontend: "Pull from git" button added alongside "Push now".
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Icon: change rail tab from integration_instructions to merge
- Auto-push on compile: toggle stored in localStorage, watches compile
context; when compiling goes true→false with no error, triggers a push
automatically (including the latest build's PDF if configured)
- PDF destination path: new gitSyncPdfPath field; backend fetches the
compiled PDF from CLSI (buildId + clsiServerId passed from frontend)
and writes it at the configured path in the repo; silently skipped if
no recent compile or field is blank
- Push now always sends current buildId/clsiServerId so PDF is included
without needing a separate save step
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Push now always saves the current form values first, so clicking Push
without a prior Save no longer returns "No git remote configured".
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Project files can now be pushed into a subfolder of the target repo
rather than always going to the root. The path is sanitised on the
backend (strips leading/trailing slashes, rejects traversal with ..).
An empty value (default) keeps the existing root behaviour.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds a "Git Sync" section in the Integrations rail panel that lets
project owners configure an HTTPS remote URL (with embedded auth token)
and force-push all project files as a single commit.
Backend:
- GitSyncHandler: assembles project docs + binary files into a temp dir,
runs git init/commit/push --force, then cleans up
- GitSyncController: GET/POST /project/:id/git-sync (configure),
POST /project/:id/git-sync/push (trigger)
- Project model: gitRemote field
- Dockerfile: ensures git is present at runtime
- Env flag: OVERLEAF_ENABLE_GIT_SYNC=true (set in k8s manifest)
Frontend:
- GitSyncWidget: URL input + Save + Push Now buttons, success/error feedback
- Integrations panel: shows widget when gitSyncEnabled
- Rail: shows Integrations tab when gitSyncEnabled (was only gitBridgeEnabled)
- i18n: en + fr translations
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>