(sec-dev-git)= # Working with git in this repository What to type, in what order, and what a change has to look like before it is pushed. Written for the command line, because that is what a VS Code user has in front of them; every command has an equivalent in the editor's git panel and in Visual Studio, and they do the same thing. This page is the *mechanics*. **What** a change has to pass before it is committed — the issue, the version bump, the four gates — is [WORKFLOW.md](WORKFLOW.md). If you have not cloned yet, start at [GETTING_STARTED.md](GETTING_STARTED.md). ## Branches | branch | what it is | |---|---| | `master` | the public GitHub branch, currently a read-only mirror frozen at 1.11.0 — **never commit here** | | `v2-dev` | the working branch of the 2026 revision; the name is historical (it was planned as 1.11 → 2.0 and completes as 1.12) | | `release/*` | release preparation | ``` origin → the internal server (v2-dev tracks origin/v2-dev) github → git@github.com:jgerstmayr/EXUDYN.git (master tracks github/master) ``` **Work on `v2-dev`.** A bare `git push` from it goes to `origin`, the internal server, which is the safe default and the normal thing to do. **Nothing reaches GitHub before the 1.13 release** (decision D16); `tools/hooks/pre-push` refuses it, but only where `core.hooksPath` is set — which is why that is step 4 of [GETTING_STARTED.md](GETTING_STARTED.md). ## The everyday loop ```bash git status #what is changed, and on which branch git pull #before starting, and before pushing #... make the change, run the gates ... git add #or: git add -A, after reading git status git commit -F #or: git commit -m "..." git push #to origin ``` Three habits that save time here: - **`git status` before `git add -A`.** The build writes into `build/`, `dist/` and `python/logs/`; they are ignored, but a stray scratch file is not. - **Pull before you push, not after a conflict.** The working branch is shared. - **Never commit a generated file by hand.** `src/Autogenerated/`, `docs/generated/` and `CHANGELOG.md` are written by the generators and by the issue tracker; they *are* committed, but only as the generators wrote them. A hand edit survives until the next run and no longer. ### Seeing what you are about to commit ```bash git diff #unstaged git diff --staged #what "git commit" would record git diff --stat #the file list with line counts, to check the size of a change git log --oneline -10 #the last ten commits, which is the style guide for the next one ``` ## Commit messages The message reuses the **vocabulary of the issue tracker**, so that a commit and its issue speak the same language: ``` #: ``` `` is one of the issue types — `BUG`, `FIX`, `CHANGE`, `EXTENSION`, `IMPROVEMENT`, `TESTING`, `DOCU`, `EXAMPLE`, `CHECK`, `IDEA` — and the number is the issue the change resolves. A change worth committing is worth an issue; that is the loop in [WORKFLOW.md](WORKFLOW.md) §2. ``` BUG #2107: fix 32-byte alignment of VectorBase under AVX2 The AVX2 module reads 32 bytes at a time, and VectorBase was aligned to 16, so a load at the end of an array crossed into unmapped memory on Linux only. ``` Two rules about the body: **say why, not what** — the diff already says what — and **name what a reader could not see**, such as a measurement, a platform the fault appears on, or a decision that was taken and the alternative that was not. A **work in progress** commit, used only on `v2-dev` and only to move unfinished work between machines, is prefixed `WIP:` and says what is broken. It is the one kind that does not pass the gates. ## Branching for a larger change For anything that will take more than a day, or that might not work out: ```bash git switch -c topic/ #branch from v2-dev #... commits ... git switch v2-dev git pull git merge topic/ git branch -d topic/ ``` Merge into `v2-dev` when the change passes the gates, not before. If `v2-dev` has moved on and the merge conflicts, `git pull` first and resolve on the topic branch, where a mistake costs nothing. ```bash git merge --abort #get out of a merge you do not want to finish git switch - #back to the previous branch ``` ## If you are contributing from outside The repository is **not open for unsolicited pull requests** — the reasons are in [CONTRIBUTING.md](../../CONTRIBUTING.md), and the short one is that reviewing a change to the C++ core costs more than writing it. **Talk first**: an issue, a discussion or an email. If a change is agreed, this is what it has to arrive as: 1. a branch off the current working branch, with a **clear, small set of commits** — one logical change per commit; 2. commit messages in the form above, naming the agreed issue; 3. **no generated file edited by hand**, and `tools/regenerate.py` run if you changed anything under `definitions/`; 4. the **test suite passing**: `python tools/exudev test`, and `pytest python/testing` if you touched Python; 5. whatever documentation the change makes wrong, corrected in the same commit — the four gates in [WORKFLOW.md](WORKFLOW.md) §8 are what a pull request is checked against. What is *not* expected: that you bump a version, edit `CHANGELOG.md` or close an issue. The micro version is derived from the count of resolved issues and is written by the tracker; a contribution that edits it creates a conflict for everybody. ## Things that go wrong, and the way back | | | |---|---| | committed on the wrong branch | `git switch -c right-branch` then `git reset --hard HEAD~1` on the wrong one | | committed too early | `git commit --amend` — **only** if it is not pushed yet | | want to undo the last commit but keep the work | `git reset --soft HEAD~1` | | a file you did not mean to add | `git restore --staged ` | | your working tree is a mess | `git stash`, do the urgent thing, `git stash pop` | | a push is refused by the hook | read the message; it is refusing a push of the working branch to the public remote, which is the rule of decision D16 | `git reset --hard` and `git push --force` throw work away. Before either one, `git log --oneline` and be sure of what you are pointing at; a commit that is lost from a branch is still reachable through `git reflog` for a while, and that is the escape hatch.