teamserver-git · git:20261030.4fa453f · 2026-10-30 · sha256 a7648250d58cc94f
teamserver-git git:20261030.4fa453fA
Immutable. This exact content never changes and is served at /api/v1/blob/a7648250d58cc94f.
---
name: teamserver-git
description: "Commit, branch and push a Mendix project in git the way Studio Pro and Mendix Team Server expect — branches created on the server (not with git checkout -b), the mx_metadata commit note written with `mxcli git note`, and the notes ref pushed with the branch. Use before any git commit, branch, merge, rebase or push in a Mendix app repository, and when Studio Pro shows conflicts or changes that git does not, fails to open the project, or cannot deploy a revision."
---
<!-- skill-index: generated by scripts/skill-index.py; make check-skill-index -->
## Find it fast
`sed -n '<from>,<to>p' SKILL.md` one section rather than reading the file;
`./mxcli syntax <topic>` answers *how do I write this* for a fraction of either.
| lines | section |
|---|---|
| 35-41 | The rule: let Studio Pro do version control when it can |
| 42-55 | Branches: create them on the server |
| 56-97 | Commit from the agent |
| 98-112 | Push the branch and the notes together, and soon |
| 113-134 | Never rewrite or merge model history with git |
| 135-145 | Reading what Studio Pro recorded |
| 146-154 | Checklist |
<!-- /skill-index -->
# Working with Git on a Mendix Team Server Project
A Mendix project in git is more than its files. Studio Pro keeps four things in
step that plain git does not, and a commit that skips them makes Studio Pro report
conflicts nobody can see, crash on open, or refuse to deploy a revision.
| What | Where | What breaks without it |
|------|-------|------------------------|
| Model units | `mprcontents/**/*.mxunit` | — (git handles these) |
| Unit index | the `.mpr` `Unit` table, `ContentsHash` per unit | Studio Pro's change detection; it shows changes the files do not have |
| Commit metadata | a git note per commit under `refs/notes/mx_metadata` | version check and package build for that revision; the history shows `(unknown)` |
| Branches | on the Team Server | Studio Pro 11.13 crashes opening a branch that has no upstream |
## The rule: let Studio Pro do version control when it can
If the user has the project open in Studio Pro, the cheapest correct commit is
theirs: **Version Control › Commit** in Studio Pro commits, writes the note,
and pushes, all in one go, even when every change in it was made with mxcli.
Suggest that first. Everything below is for committing from the agent.
## Branches: create them on the server
- **Never `git checkout -b` a branch the user will open in Studio Pro.** A
local-only branch has no upstream, and Studio Pro 11.13 fails to open it with
*"Unable to find 'system' property in 'system'"*.
- Ask the user to create the branch in Studio Pro: **Version Control › Manage
Branch Lines… › New**. That creates it on the Team Server. Then
`git fetch && git switch <branch>`, and git tracks it as `origin/<branch>`.
- If they want the agent to do it instead, it must be pushed with an upstream
straight away. That is an outward action, so ask first:
`git switch -c <branch> && git push -u origin <branch>`.
- `mxcli docker check`, `mxcli run --local` and `mxcli diag -p app.mpr` warn
when the checked-out branch has no upstream.
## Commit from the agent
The one command does it all — hashes, staging, commit, the note:
```bash
mxcli git commit -m "<what changed for the user>" -p app.mpr
```
It repairs ContentsHash mismatches from the files first (MISSING/ORPHAN refuse
the commit), stages everything and unstages the files Studio Pro never commits
(`project-settings.user.json`, `*.mpr.lock`, `*.mpr.bak`, `.mendix-cache/`,
`deployment/`, `theme-cache/`, `.mxcli/`), commits, and attaches the note. Add
`--push` to push the branch and the notes ref together; `--dry-run` stages,
reports and unstages without committing. Refused while the `.mpr.lock` exists.
The manual equivalent, one step at a time:
```bash
mxcli fix hashes -p app.mpr # unit index matches the files (exit 0)
git add App.mpr mprcontents <other source you changed>
git commit -m "<what changed for the user>"
mxcli git note -p app.mpr --write # attach the mx_metadata note
```
- Stage `App.mpr`, `mprcontents/` and the source you changed (`theme/`,
`javasource/`, `javascriptsource/`, `widgets/`, `mdlsource/`). Never stage
`project-settings.user.json`, `*.mpr.lock`, `*.mpr.bak`, `.mendix-cache/`,
`deployment/`, `theme-cache/` or `.mxcli/`; Mendix's `.gitignore` already
excludes most of them.
- `mxcli fix hashes` matters after anything other than mxcli or Studio Pro
touched a unit file: `git checkout -- mprcontents/…`, `git restore`, a merge
tool. `mx check` does not notice a stale index. `--repair` fixes it.
- `mxcli git note` with no commit argument annotates every commit not pushed yet
(`@{upstream}..HEAD`). It computes the change list from the commit itself,
so run it after committing. It never overwrites a note Studio Pro wrote
(`--force` does) and it does replace Studio Pro's placeholders. Without
`--write` it only previews.
- A repository that has known only plain git may drift further: missing
`mendix.*`/`core.autocrlf` local config, an SSH remote Studio Pro cannot
use, notes missing or malformed across history. `mxcli git doctor` reports
all of it in one pass and `--fix` repairs it.
## Push the branch and the notes together, and soon
```bash
git push origin <branch> refs/notes/mx_metadata
```
- `git push` alone does not push notes.
- While the project is open, **Studio Pro fetches every few minutes**, and its
fetch force-replaces the local `refs/notes/mx_metadata` with the Team Server's
copy. Any note not pushed yet is gone, and Studio Pro back-fills an
`"(unknown)"` placeholder for the commit. If that happened, run
`mxcli git note -p app.mpr --write` again; it replaces placeholders. Then push.
- Pushing goes to the user's Team Server and needs their credentials (a PAT).
Only push when the user asks.
## Never rewrite or merge model history with git
- **No plain `git merge`, `rebase` or `cherry-pick` of model changes.** The
`.mpr` is a SQLite file; git cannot merge it (every two-sided model change
is a binary conflict), and a textual merge of `mprcontents/` leaves an
index that does not match the files. Model-aware merging exists in two
forms: **`mxcli git merge <ref>`** from the command line (it hands the
conflict to `mx merge` over three project folders — Studio Pro's own
engine, Linux devcontainers included — and commits the resolved model as a
normal merge commit with the note), and **Version
Control › Merge Changes Here** in Studio Pro (*Merge feature branch* or
*Cherry Pick*) — which is also where the conflicts mx cannot auto-resolve
go. A conflict `mxcli git merge` cannot resolve — and an engine failure —
aborts the merge cleanly; nothing is left half-done.
Studio Pro's history on Team Server is linear for a reason: do not "fix"
a conflicted model merge by hand-editing files.
- **No `--amend` or force-push of a pushed commit.** Before pushing, an amend is
fine: the `notes.rewriteRef` Studio Pro puts in `.git/config` carries the
note. Re-run `mxcli git note --write` anyway; it is cheap.
- Do not switch branches or write the model while `<App>.mpr.lock` exists, which
means Studio Pro has the project open. mxcli refuses to write then.
## Reading what Studio Pro recorded
```bash
git log --notes=mx_metadata --format='%h %s%n%N' -10
```
A note lists `ModelChanges` (`Added | Modified | Deleted | Moved`, with unit
type, name and module), the `ModelerVersion`, and the `BranchName` (`""` on main).
A note with `"HasModelerVersion":false` is a placeholder Studio Pro wrote for a
commit made outside it.
## Checklist
- [ ] Suggested committing from Studio Pro when it is open
- [ ] On a branch that exists on the Team Server (has an upstream)
- [ ] `mxcli fix hashes -p app.mpr` clean
- [ ] Only project files staged
- [ ] `mxcli git note -p app.mpr --write` after the last commit
- [ ] Pushed `<branch>` and `refs/notes/mx_metadata` together, when the user asked to push
- [ ] No git merge, rebase, cherry-pick or force-push of model history