> ## Documentation Index
> Fetch the complete documentation index at: https://ayakaleaf-pro.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# GitLab Sync Project States Collection

`gitlabSyncProjectStates` holds one document per project that is linked to a GitLab project: which repository, and where the last sync left off. It belongs to the `gitlab-sync` web module (`services/web/modules/gitlab-sync`). The schema is in `services/web/modules/gitlab-sync/app/models/gitlabSyncProjectStates.mjs`, and all access goes through `services/web/modules/gitlab-sync/app/src/SyncStateManager.mjs`. The fields are the same as in [GitHub Sync Project States](https://ayakaleaf-pro.mintlify.site/dev/data-model/github-sync-project-states-collection.md).

#### Fields

| Field | Type | Meaning | Source |
| - | - | - | - |
| `_id` | ObjectId | Set by Mongoose on create. | |
| `projectId` | ObjectId | The linked project. Required. The schema says `unique: true`, but no index is built (see Indexes). | `gitlabSyncProjectStates.mjs:8` |
| `repoFullName` | String | The GitLab project path with its namespace (GitLab's `path_with_namespace`), for example `group/subgroup/name`. Required. | `gitlabSyncProjectStates.mjs:9`, `GitLabApiClient.mjs:347` |
| `defaultBranchName` | String | The branch the project syncs with. Set when the project is linked and not changed afterwards: on import, the branch sent by the import form; on export, the new repository's default branch, or `main` when the API gives none. Default `null`. | `gitlabSyncProjectStates.mjs:10`, `GitLabSyncHandler.mjs:175-181,234-240`, `GitLabApiClient.mjs:346-349` |
| `mergeStatus` | String | `clean`, `conflict` or `diverged`. Default `clean`. | `gitlabSyncProjectStates.mjs:11` |
| `lastSyncCommit` | String | The commit SHA on the synced branch at the last sync. Default `null`. | `gitlabSyncProjectStates.mjs:12` |
| `lastSyncVersion` | Number | The project history version at the last sync, from project-history `GET /project/:id/version`, read after a history flush. Default `null`. | `gitlabSyncProjectStates.mjs:13`, `services/web/modules/gitlab-sync/app/src/HistoryManager.mjs:8-17` |
| `unmergedBranchName` | String | During a conflict: the temporary branch with the Overleaf changes, named `overleaf-YYYY-MM-DD-HHMMSS`. `null` when there is no conflict. | `gitlabSyncProjectStates.mjs:14`, `GitMerge.mjs:817-821` |
| `unmergedBranchHead` | String | During a conflict: the head commit of that branch. Default `null`. | `gitlabSyncProjectStates.mjs:15` |
| `conflictVersion` | Number | During a conflict: the project history version when the conflict was recorded. Default `null`. | `gitlabSyncProjectStates.mjs:16` |
| `__v` | Number | The Mongoose version key. The schema does not turn it off. | Mongoose default |

#### Who Writes It

| Code | What it does |
| - | - |
| `SyncStateManager.mjs:9-14` (`createProjectState`) | Creates the document: after importing a repository as a new project (`services/web/modules/gitlab-sync/app/src/GitLabSyncHandler.mjs:175-181`), or after exporting a project to a new repository (`GitLabSyncHandler.mjs:234-240`, owner only, refused when already linked). |
| `SyncStateManager.mjs:16-21` (`updateProjectState`) | `$set` of the changed fields. `getMergeOverview` sets `mergeStatus: 'diverged'` when the synced branch no longer contains `lastSyncCommit` (merge base check, `services/web/modules/gitlab-sync/app/src/GitLabApiClient.mjs:460`), or the commit is gone and the user can push (`GitLabSyncHandler.mjs:123,126-137`). A sync (`services/web/modules/gitlab-sync/app/src/GitMerge.mjs`) moves `lastSyncCommit`/`lastSyncVersion` on success (for example `:152,189,231`), records a conflict with `unmergedBranchName`, `unmergedBranchHead` and `conflictVersion` (`:214-220`), and clears them once it is resolved (`:257-264`). |
| `SyncStateManager.mjs:23-25` (`removeProjectState`) | Deletes the document when the owner unlinks the project (`GitLabSyncHandler.mjs:83-97`) and when a deleted project expires (`services/web/modules/gitlab-sync/index.mjs:46-48`). |

#### Who Reads It

| Code | What it does |
| - | - |
| `GitLabSyncHandler.mjs:39-60` (`getProjectState`) | Gives the editor `mergeStatus`, `repoFullName` and `unmergedBranchName`. With no document it answers `need-export`, a value that is never stored. |
| `GitLabSyncHandler.mjs:110-143` (`getMergeOverview`) | Compares `lastSyncCommit` and `lastSyncVersion` with GitLab and the project history to list the new commits. |
| `GitLabSyncHandler.mjs:200` (`exportProject`) | Refuses to export a project that is already linked. |
| `GitMerge.mjs:36` (`doGitMergeWithoutLock`) | Loads the state at the start of a sync. |

#### Indexes

| Name | Keys | Options | Migration |
| - | - | - | - |
| `_id_` | `_id: 1` | | default |

Mongoose `autoIndex` is off (`services/web/app/src/infrastructure/Mongoose.mjs:7`), so the schema's `unique: true` on `projectId` creates nothing. No migration creates indexes for this collection.

#### Notes

* GitLab's API cannot move a branch to any commit as GitHub's can. A sync commits straight onto the synced branch when it can move forward, or onto a temporary branch that is then merged through a merge request (`GitMerge.mjs:16-21`).
* A sync runs under the `gitSync` lock of the project, shared with GitHub and Gitea Sync (`GitMerge.mjs:25-32`).
* A deleted project keeps its document until the project expires.
* The user's GitLab token is in [GitLab Sync User Credentials](https://ayakaleaf-pro.mintlify.site/dev/data-model/gitlab-sync-user-credentials-collection.md).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.