Files
mtkports/dev-vcs/git
2026-08-09 10:47:07 +02:00
..
2026-08-09 10:47:07 +02:00
2026-08-09 10:47:07 +02:00
2026-08-09 10:47:07 +02:00
2026-08-09 10:47:07 +02:00
2026-08-09 10:47:07 +02:00

git for MontaukOS

Upstream git/git, pinned at v2.39.5 (upstream/, submodule). Reports itself as 2.39.5-montauk.

Installs as a system program, not an app bundle:

Path What
0:/os/git.elf the binary (~3 MB stripped)
0:/os/git/share/git-core/templates git init skeleton
0:/os/git/etc/gitconfig system config (not created by the install)
make -C dev-vcs/git          # build
make -C dev-vcs/git install  # -> MontaukOS/programs/bin/os/

make ports from the MontaukOS tree does both (git is in the top-level Makefile's SELF_INSTALL_PORTS).

Status

First run on hardware: git started, died at exit 128, printed nothing. Two bugs, both outside git and both now fixed -- needs a retest:

  1. sanitize_stdfds() opened /dev/null, which MontaukOS does not have, so xopen() died before any command dispatched. That function guards against inheriting closed descriptors, which cannot happen on a system that spawns rather than forks; patches/0002 makes it a no-op.
  2. Nothing git wrote with write(2, ...) ever appeared -- which is why the fatal error was invisible. The libc's read()/write() passed fd 0/1/2 straight to SYS_READ/SYS_FWRITE as file handles, and the kernel hands out file handles starting at 0, so those numbers named real files. A program's third open() owned "stderr". Fixed in the OS: the kernel no longer allocates handles 0/1/2, and the libc routes them to the terminal.

Second run got as far as git init (works, repository created) and then hit fatal: detected dubious ownership. That is git's safe.directory check comparing lstat()'s st_uid against geteuid(); MontaukOS stores no per-file owner, so it is false for every directory on the system. The port now answers that check directly -- see compat/montauk-ownership.h, which also records what has to change when the OS grows real ownership.

Confirmed working on hardware so far: startup, error output, git init, and quoted arguments. The rest is still only what the build configuration implies.

What should work

Everything git does inside one process and one filesystem:

  • init, add, rm, mv, status, diff, commit, log, show
  • branch, checkout, switch, restore, merge, reset, revert
  • tag, stash, cherry-pick, rebase (the builtin, non-interactive path)
  • cat-file, rev-parse, ls-files, ls-tree, hash-object, fsck
  • config, blame, grep, describe, bisect
  • clone/fetch/push against a local path, e.g. git clone 0:/users/dan/repo

What does not work, and why

Anything that starts another process. MontaukOS spawns (SYS_SPAWN); it has no fork(), no exec() and no pipe(), and a spawned process cannot inherit a pipe for its stdio. Every git feature built on sub-processes fails with ENOSYS rather than misbehaving:

  • hooks (pre-commit, commit-msg, ...) -- the samples are installed but never run
  • $EDITOR, so git commit needs -m or -F, and interactive rebase and git add -p are out
  • the pager (harmless -- output goes straight to the terminal, and DEFAULT_PAGER=cat is compiled in anyway)
  • aliases that shell out (!command), git submodule, difftool, mergetool, git gc (it re-runs itself as git repack)

Network transports. No http://, https://, git:// or ssh://. The port is built NO_CURL NO_OPENSSL, and the socket shims fail: MontaukOS TCP lives behind IPC handles rather than file descriptors, and DNS resolution is inside the kernel with no userspace interface. Local paths are the transport.

Symlinks. The VFS cannot create them, so git behaves as if core.symlinks=false -- a symlink in a tree checks out as a regular file containing the link target.

File modes. Built NO_TRUSTABLE_FILEMODE, so the executable bit is not read back from the filesystem; core.fileMode defaults to false.

Threads. NO_PTHREADS, so packing, delta search and git grep are single-threaded. Correct, just slower.

mmap. NO_MMAP, so pack and index access reads into memory instead of mapping. Large repositories will be heavier on RAM than on Linux.

Before the first commit

The environment MontaukOS hands a process is empty, so the port sets HOME itself from the session user (0:/users/<name>) before git reads any config -- that is what makes --global work. Set an identity:

git config --global user.name "Your Name"
git config --global user.email [email protected]

This is not optional. Left unset, git builds a fallback address from the session user and the hostname -- and since gethostname() answers montauk, with no domain in it, git marks the address bogus, appends .(none) and refuses:

fatal: unable to auto-detect email address (got 'admin@montauk.(none)')

That is stock git behaviour on any host without a domain name, not something the port introduces.

Quoting

Arguments are split by the C runtime, not by a shell. crt1.c understands '...' and "..." (added for this port), so

git commit -m "a message with spaces"

reaches git as three arguments. There is no escaping and no substitution -- a literal quote character cannot be passed.

How the port is put together

Makefile drives upstream's own build with the toolchain and a long list of NO_* knobs; the header comment there explains the ones that are not self-evident. Two mechanisms fill the gaps:

  • compat/ -- headers MontaukOS has no equivalent of, plus libgitcompat.a with the POSIX functions the libc does not carry. See compat/README.
  • patches/ -- two patches: calling montauk_startup() from main(), and emptying sanitize_stdfds(), which cannot run without a /dev/null.

Everything else upstream needed was already reachable through git's own portability knobs, which is the reason this port is small.