Git-for-Data Reference

Open inAnthropic

What you'll achieve

By the end of this guide, you will know how to push, pull, fetch, and clone data between TerminusDB instances — and how to manage remotes, rebase branches, and resolve diverged histories.

Git-for-Data lets you transport data between TerminusDB instances using operations that mirror git: clone, push, pull, and fetch. You can collaborate on structured data by synchronising content repositories across cloud-hosted and local TerminusDB instances.

Prerequisites

  • Two TerminusDB instances running (examples use localhost:6363 as local and localhost:6364 as remote)
  • A database on the remote instance to clone from, or a local database with a remote configured
  • Examples use admin/mydb with basic authentication

Remotes

Git-for-data operations use remotes — stored references to remote databases including branch information and layer state. One or more remotes can be added to a database.

Add a remote

Register a remote TerminusDB instance for push/pull operations:

curl -u admin:root -X POST http://localhost:6363/api/remote/admin/mydb \
  -H "Content-Type: application/json" \
  -d '{"remote_name": "origin", "remote_location": "http://localhost:6364/admin/mydb"}'

Expected response:

Example: JSON
{"@type": "api:RemoteResponse", "api:status": "api:success"}
Example: TypeScript
import TerminusClient from "@terminusdb/terminusdb-client";

const client = new TerminusClient.WOQLClient("http://localhost:6363", {
  user: "admin",
  key: "root",
  organization: "admin",
  db: "mydb",
});

await client.addRemote("origin", "http://localhost:6364/admin/mydb");

List remotes

curl -u admin:root "http://localhost:6363/api/remote/admin/mydb"

Expected response:

Example: JSON
{"@type": "api:RemoteResponse", "api:remote_names": ["origin"], "api:status": "api:success"}

Show remote details

curl -u admin:root "http://localhost:6363/api/remote/admin/mydb?remote_name=origin"

Expected response:

Example: JSON
{"@type": "api:RemoteResponse", "api:remote_name": "origin", "api:remote_url": "http://localhost:6364/admin/mydb", "api:status": "api:success"}

Update a remote URL

curl -u admin:root -X PUT http://localhost:6363/api/remote/admin/mydb \
  -H "Content-Type: application/json" \
  -d '{"remote_name": "origin", "remote_location": "http://newhost:6363/admin/mydb"}'

Expected response:

Example: JSON
{"@type": "api:RemoteResponse", "api:status": "api:success"}

Delete a remote

curl -u admin:root -X DELETE "http://localhost:6363/api/remote/admin/mydb?remote_name=origin"

Expected response:

Example: JSON
{"@type": "api:RemoteResponse", "api:status": "api:success"}

Clone a database

Clone creates a full copy of a database (schema, all branches, all layers) from one TerminusDB instance to another. A remote named origin is automatically configured in the new database.

curl -u admin:root -X POST http://localhost:6363/api/clone/admin/mydb \
  -H "Content-Type: application/json" \
  -H "Authorization-Remote: Basic YWRtaW46cm9vdA==" \
  -d '{
    "comment": "Clone of remote mydb",
    "label": "My Database",
    "remote_url": "http://localhost:6364/admin/mydb"
  }'

Expected response:

Example: JSON
{"@type": "api:CloneResponse", "api:status": "api:success"}

The Authorization-Remote header provides credentials for the remote instance. The -u admin:root authenticates against the local instance.

Example: TypeScript
await client.clonedb({
  comment: "Clone of remote mydb",
  label: "My Database",
  remote_url: "http://localhost:6364/admin/mydb",
}, "admin", "mydb");

Clone direction matters

Clone pulls data from the remote_url into the local instance. If the remote cannot reach your local instance (e.g. behind a firewall), use reverse branch cloning instead.


Fetch

Fetch retrieves layer information from a remote and updates local references — without changing any local branch data. This tells your local instance what the remote looks like.

curl -u admin:root -X POST http://localhost:6363/api/fetch/admin/mydb/origin/_commits \
  -H "Authorization-Remote: Basic YWRtaW46cm9vdA=="

Expected response:

Example: JSON
{"@type": "api:FetchRequest", "api:status": "api:success", "api:head_has_changed": true, "api:head": "Layer_ID_abc123"}

The path format is: /api/fetch/{organization}/{db}/{remote_name}/_commits

The Authorization-Remote header authenticates against the remote instance. The -u flag authenticates against the local instance.

Example: TypeScript
const result = await client.fetch("origin");
console.log(result);
// { head_has_changed: true, head: "Layer_ID_abc123" }

Pull

Pull fetches remote changes and applies them to a local branch. Missing layers from the remote branch are transported and appended to the local branch.

curl -u admin:root -X POST http://localhost:6363/api/pull/admin/mydb \
  -H "Content-Type: application/json" \
  -H "Authorization-Remote: Basic YWRtaW46cm9vdA==" \
  -d '{"remote": "origin", "remote_branch": "main"}'

Expected response (new data pulled):

Example: JSON
{"@type": "api:PullResponse", "api:status": "api:success", "api:head_has_changed": true, "api:head": "Layer_ID_def456"}

Expected response (already up to date):

Example: JSON
{"@type": "api:PullResponse", "api:status": "api:success", "api:head_has_changed": false}
Example: TypeScript
const result = await client.pull({
  remote: "origin",
  remote_branch: "main",
});
console.log(result);
// { head_has_changed: true, head: "Layer_ID_def456" }

Pull requires linear history

Pull succeeds only if the history has not diverged. If both local and remote have commits the other does not, the pull fails. Use rebase or merge to resolve diverged histories first.


Push

Push sends local branch changes to a remote branch. Missing layers from the local branch are transported and appended to the remote.

curl -u admin:root -X POST http://localhost:6363/api/push/admin/mydb \
  -H "Content-Type: application/json" \
  -H "Authorization-Remote: Basic YWRtaW46cm9vdA==" \
  -d '{"remote": "origin", "remote_branch": "main"}'

Expected response (new data pushed):

Example: JSON
{"@type": "api:PushResponse", "api:status": "api:success", "api:repo_head_updated": true, "api:repo_head": "Layer_ID_ghi789"}

Expected response (already up to date):

Example: JSON
{"@type": "api:PushResponse", "api:status": "api:success", "api:repo_head_updated": false, "api:repo_head": "Layer_ID_current"}
Example: TypeScript
const result = await client.push({
  remote: "origin",
  remote_branch: "main",
});
console.log(result);
// { repo_head_updated: true, repo_head: "Layer_ID_ghi789" }

Push requires linear history

Push succeeds only if the remote branch history is a strict ancestor of the local branch. If the remote has diverged (someone else pushed), you must pull and resolve first.

Push with prefixes

To also push prefix/context mappings along with data:

curl -u admin:root -X POST http://localhost:6363/api/push/admin/mydb \
  -H "Content-Type: application/json" \
  -H "Authorization-Remote: Basic YWRtaW46cm9vdA==" \
  -d '{"remote": "origin", "remote_branch": "main", "push_prefixes": true}'

Rebase

Rebase replays commits from one branch onto another. Both branches must share a common ancestor commit. Commit messages are retained.

curl -u admin:root -X POST http://localhost:6363/api/rebase/admin/mydb/local/branch/main \
  -H "Content-Type: application/json" \
  -d '{"author": "alice@example.com", "rebase_from": "admin/mydb/local/branch/feature"}'

Expected response:

Example: JSON
{
  "@type": "api:RebaseResponse",
  "api:status": "api:success",
  "api:forwarded_commits": ["commit/abc123", "commit/def456"],
  "api:rebase_report": [],
  "api:common_commit_id": "commit/ancestor789"
}

This replays all commits from feature onto main, starting from the common ancestor.

Example: TypeScript
const result = await client.rebase({
  rebase_from: "admin/mydb/local/branch/feature",
  author: "alice@example.com",
});
console.log(result.forwarded_commits);
// ["commit/abc123", "commit/def456"]

Complete workflow: clone, edit, push

This workflow demonstrates a full collaboration cycle — clone a database, make changes locally, and push them back:

# 1. Clone the remote database
curl -u admin:root -X POST http://localhost:6363/api/clone/admin/mydb \
  -H "Content-Type: application/json" \
  -H "Authorization-Remote: Basic YWRtaW46cm9vdA==" \
  -d '{"comment": "Working copy", "label": "My Database", "remote_url": "http://remote:6363/admin/mydb"}'

# 2. Add a document locally
curl -u admin:root -X POST \
  "http://localhost:6363/api/document/admin/mydb?author=alice&message=Add+new+product" \
  -H "Content-Type: application/json" \
  -d '{"@type": "Product", "name": "Widget", "price": 9.99}'

# 3. Push changes to remote
curl -u admin:root -X POST http://localhost:6363/api/push/admin/mydb \
  -H "Content-Type: application/json" \
  -H "Authorization-Remote: Basic YWRtaW46cm9vdA==" \
  -d '{"remote": "origin", "remote_branch": "main"}'

Complete workflow: pull remote changes

# 1. Fetch to see if remote has changed
curl -u admin:root -X POST http://localhost:6363/api/fetch/admin/mydb/origin/_commits \
  -H "Authorization-Remote: Basic YWRtaW46cm9vdA=="

# 2. Pull changes into local main
curl -u admin:root -X POST http://localhost:6363/api/pull/admin/mydb \
  -H "Content-Type: application/json" \
  -H "Authorization-Remote: Basic YWRtaW46cm9vdA==" \
  -d '{"remote": "origin", "remote_branch": "main"}'

# 3. Verify the new data is present
curl -u admin:root "http://localhost:6363/api/document/admin/mydb?type=Product&as_list=true"

Schema and instance separation

Push and pull transport instance data only — schema changes are not synchronised automatically. You must maintain schema consistency manually across instances.

To push schemas along with instance data, pass "push_prefixes": true in the push request (see Push with prefixes).


Operational technology environments

Git-for-Data is useful in environments with strict network segmentation (IEC 62443, Purdue model) where databases cannot maintain persistent connections. You can:

  1. Clone a database to an isolated environment
  2. Make changes offline
  3. Push changes back when connectivity is available

For environments where the cloud instance cannot reach the local instance, see Manual Reverse Branch Cloning and Transfer Data in Operational Technologies Landscapes.


Next steps

Was this helpful?