Skip to content

Git bridge

Git is an adapter, not the engine. The bridge uses the git command line (plumbing only), so it needs git on PATH and never links Git's code. A walkthrough whose commands are run by the tests, including a check that an import followed by an export gives back the same trees, is Migrating a Git repository.

Import a Git repository

ag init --namespace me/project
ag git import /path/to/git/repo --rev HEAD --stream imported
ag log imported
ag verify

Every commit becomes a changeset with the same parents in the same order; operations are the diff against the first parent, which is exactly AgentGit's changeset semantics, so merges carry over without interpretation. Executable bits and symlinks are preserved. The author becomes user:<email> (sanitized), the commit time is kept, and the original SHA is appended to the message:

Imported-From: git 5f2c0e…

The target stream must not have history yet (import never rewrites an existing stream). The whole imported history is published in one verified operation.

Not carried over: submodules (gitlinks), paths AgentGit refuses to record (non-UTF-8, control characters, backslashes, and any .git/.ag component — a repository can contain such trees via plumbing, and checking them out would let it plant hooks), tags, notes, signatures, committer identity, timezone offsets, and every ref other than the one --rev names. What is reported: each skipped path, the number of submodule entries, and the number of commits whose text was not valid UTF-8 (lossy_commits in --json; git converts a commit that names its encoding, anything else that is not UTF-8 is repaired with U+FFFD). The rest is dropped without a message: a migration that needs signatures, tags or the committer must keep Git as the record of them.

What git prints cannot be changed from outside. The bridge asks git log for NUL-separated fields, so a commit message may hold any character; it passes --no-show-signature and --encoding=UTF-8, so log.showSignature and i18n.logOutputEncoding in your configuration change nothing; and it removes GIT_DIR, GIT_WORK_TREE, GIT_INDEX_FILE, GIT_OBJECT_DIRECTORY, GIT_COMMON_DIR, GIT_NAMESPACE, GIT_ALTERNATE_OBJECT_DIRECTORIES and GIT_PREFIX from the environment of every git process, so ag git import|export run from a git hook works on the repository it was given and not on the hook's. If git cat-file fails, the error is git's own message.

Export a stream to Git

ag git export main /path/to/new-or-existing/git/repo --branch main

Uses git fast-import. The branch name is checked by git check-ref-format before anything is created, so a refused name leaves no repository behind. The destination is git init-ed if missing. An identity such as user:alice becomes the author user:alice <user.alice@agentgit.invalid>; messages, timestamps, file modes and symlinks are preserved.

Round-trip guarantee

For histories without skipped paths, import → export reproduces the same Git tree SHA for every commit (and the same parent structure). This is tested on a history containing modified/deleted files, executable files, symlinks, empty and binary files, a non-ASCII path, a branch and --no-ff merge, directory↔file replacement, a mode-only change and a file→symlink type change (history_survives_a_round_trip_with_identical_git_trees). Commit SHAs differ, because identities and timestamps are mapped; the Imported-From: trailer lets you pair commits.

Using both

A practical migration path: keep Git as the system of record, run ag git import periodically into a scratch stream to let agents work with AgentGit's policy and leases, and ag git export the result back. The bridge is one-shot per direction, not a live mirror.