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. If you have not cloned yet, start at 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.

The everyday loop

git status                       #what is changed, and on which branch
git pull                         #before starting, and before pushing
                                 #... make the change, run the gates ...
git add <the files you changed>  #or: git add -A, after reading git status
git commit -F <message file>     #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

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:

<TYPE> #<issue number>: <one line summary>

<why, and whatever the diff does not make obvious>

<TYPE> 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 §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:

git switch -c topic/<short name>      #branch from v2-dev
                                      #... commits ...
git switch v2-dev
git pull
git merge topic/<short name>
git branch -d topic/<short name>

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.

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, 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 §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 <file>

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.