<https://docs.linkeddatahub.com/reference/versioning/>
        a       <https://w3id.org/atomgraph/linkeddatahub/document-hierarchy#Item>;
        <http://www.w3.org/1999/02/22-rdf-syntax-ns#_1>
                <https://docs.linkeddatahub.com/reference/versioning/#content>;
        <http://purl.org/dc/terms/created>
                "2026-09-29T09:52:26.885Z"^^<http://www.w3.org/2001/XMLSchema#dateTime>;
        <http://purl.org/dc/terms/creator>
                <https://admin.linkeddatahub.com/acl/agents/5ba81960-d511-4a3b-8b9a-cb5bb278dd95/#this>;
        <http://purl.org/dc/terms/description>
                "Git-backed document versioning with Memento access to the history";
        <http://purl.org/dc/terms/title>
                "Versioning";
        <http://rdfs.org/sioc/ns#has_container>
                <https://docs.linkeddatahub.com/reference/>;
        <http://www.w3.org/ns/auth/acl#owner>
                <https://admin.linkeddatahub.com/acl/agents/5ba81960-d511-4a3b-8b9a-cb5bb278dd95/#this> .

<https://docs.linkeddatahub.com/reference/versioning/#content>
        a       <https://w3id.org/atomgraph/linkeddatahub#XHTML>;
        <http://www.w3.org/1999/02/22-rdf-syntax-ns#value>
                "<div xmlns=\"http://www.w3.org/1999/xhtml\">\n    <p class=\"ldh-body-lg\">Git-backed document versioning with Memento access to the history</p>\n    <p>A dataspace can be configured to mirror every document write into a GitHub repository. The synchronization goes through the\n        GitHub REST API (<samp>api.github.com</samp>), so it is specific to GitHub rather than generic Git. Every write becomes a commit\n        authored with the writing agent's WebID, so the repository holds a complete, attributable history of the dataspace's documents.</p>\n    <p>The history is accessible over HTTP through the standard <a href=\"https://datatracker.ietf.org/doc/html/rfc7089\" target=\"_blank\">Memento (RFC 7089)</a>\n        protocol — historical versions, a TimeMap, and datetime negotiation through a TimeGate — as well as through the\n        <a href=\"../../user-guide/version-history/\">version history dialog</a> in the user interface and the\n        <a href=\"../command-line-interface/\">command line interface</a>.</p>\n    <div>\n        <h2 id=\"setup\">Setup</h2>\n        <p>Versioning is enabled per dataspace:</p>\n        <ol>\n            <li>Create a GitHub repository to hold the version history, and a <a href=\"https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens\" target=\"_blank\">fine-grained personal access token</a> with read/write access to that repository's contents</li>\n            <li>In <samp>config/system.trig</samp>, point the dataspace at a repository description with <code>lds:versioningRepository</code>:\n                <pre>&lt;urn:linkeddatahub:apps/end-user&gt;\n{\n    &lt;urn:linkeddatahub:apps/end-user&gt; a lds:EndUserDataspace ;\n        lds:service &lt;urn:linkeddatahub:services/end-user&gt; ;\n        lds:versioningRepository &lt;urn:linkeddatahub:versioning/end-user&gt; .\n}\n\n&lt;urn:linkeddatahub:versioning/end-user&gt;\n{\n    &lt;urn:linkeddatahub:versioning/end-user&gt; a doap:GitRepository ;\n        doap:location &lt;https://github.com/OWNER/REPO&gt; ;\n        github:branch \"main\" ;\n        github:pathPrefix \"graphs\" .\n}</pre>\n                The <code>github:</code> terms come from the <code>https://w3id.org/atomgraph/linkeddatahub/services/github#</code> namespace;\n                <code>github:branch</code> defaults to <samp>main</samp> and <code>github:pathPrefix</code> to <samp>graphs</samp>.\n            </li>\n            <li>Add the access token to <samp>secrets/credentials.trig</samp> (and make sure the <samp>credentials</samp> secret is enabled in <samp>docker-compose.yml</samp>):\n                <pre>@prefix a: &lt;https://w3id.org/atomgraph/core#&gt; .\n\n&lt;urn:linkeddatahub:versioning/end-user&gt;\n{\n    &lt;urn:linkeddatahub:versioning/end-user&gt; a:authToken \"github_pat_...\" .\n}</pre>\n            </li>\n            <li>Restart LinkedDataHub</li>\n        </ol>\n        <p>From then on, every successful document write in the dataspace is committed to the repository. Writes from different documents\n            share one commit chain per branch. A conflicting commit is retried rather than dropped, so concurrent writers do not lose versions.\n            Each document is stored as a sorted N-Triples file under the configured path prefix — Northwind order 10248 as\n            <samp>graphs/orders/10248.nt</samp>:</p>\n        <pre>&lt;https://localhost:4443/orders/10248/&gt; &lt;http://purl.org/dc/terms/title&gt; \"10248\" .\n&lt;https://localhost:4443/orders/10248/#this&gt; &lt;https://schema.org/identifier&gt; \"10248\" .\n&lt;https://localhost:4443/orders/10248/#this&gt; &lt;https://schema.org/orderDate&gt; \"1996-07-04\"^^&lt;http://www.w3.org/2001/XMLSchema#date&gt; .\n…</pre>\n        <p>To disable versioning, remove the <code>lds:versioningRepository</code> triple and restart — the repository configuration is read at startup.</p>\n    </div>\n    <div>\n        <h2 id=\"snapshots\">Historical versions</h2>\n        <p><code>GET</code> with the <code>?version=&lt;commit-sha&gt;</code> query parameter serves the document as it was at that commit. The\n            response carries a <code>Memento-Datetime</code> header with the commit datetime, the commit SHA as the <code>ETag</code>, and immutable\n            <code>Cache-Control</code> — a historical version never changes.</p>\n        <p>Historical versions are read-only: only <code>acl:Read</code> is advertised in the <code>Link</code> headers and write methods answer\n            <code>405 Method Not Allowed</code>. In the user interface a historical version page shows a notice banner with a link back to the current version.</p>\n        <p>Historical versions are also outside the scope of SPARQL: the dataspace's RDF dataset holds only the current version of every\n            document, while the history lives solely in the Git repository. Queries on the <a href=\"../http-api/#sparql\">SPARQL endpoint</a>\n            therefore always answer over the latest versions.</p>\n        <pre>GET /orders/10248/?version=8c9f2b1 HTTP/1.1\nHost: localhost:4443\nAccept: text/turtle\n\nHTTP/1.1 200 OK\nContent-Type: text/turtle\nMemento-Datetime: Tue, 01 Sep 2026 14:03:59 GMT\nETag: \"8c9f2b1\"\nCache-Control: public, max-age=31536000, immutable\nLink: &lt;https://localhost:4443/orders/10248/&gt;; rel=\"original\"</pre>\n    </div>\n    <div>\n        <h2 id=\"timemap\">TimeMap</h2>\n        <p><code>GET</code> with the <code>?timemap</code> query parameter serves the document's version history. In RDF formats the TimeMap is described\n            with <a href=\"https://www.w3.org/TR/prov-o/\" target=\"_blank\">PROV-O</a>: a <code>prov:Collection</code> of <code>prov:Entity</code> mementos, each\n            <code>prov:specializationOf</code> the document, <code>prov:generatedAtTime</code> its commit datetime, and <code>prov:wasRevisionOf</code> its\n            predecessor. Requesting <code>application/link-format</code> serves the serialization RFC 7089 requires.</p>\n        <p>Order 10248's history with two versions, as PROV-O:</p>\n        <pre>@prefix prov: &lt;http://www.w3.org/ns/prov#&gt; .\n@prefix xsd:  &lt;http://www.w3.org/2001/XMLSchema#&gt; .\n\n&lt;https://localhost:4443/orders/10248/?timemap&gt; a prov:Collection ;\n    prov:hadMember &lt;https://localhost:4443/orders/10248/?version=4d1e7aa&gt;,\n        &lt;https://localhost:4443/orders/10248/?version=8c9f2b1&gt; .\n\n&lt;https://localhost:4443/orders/10248/?version=4d1e7aa&gt; a prov:Entity ;\n    prov:specializationOf &lt;https://localhost:4443/orders/10248/&gt; ;\n    prov:generatedAtTime \"2026-08-30T10:12:04Z\"^^xsd:dateTime .\n\n&lt;https://localhost:4443/orders/10248/?version=8c9f2b1&gt; a prov:Entity ;\n    prov:specializationOf &lt;https://localhost:4443/orders/10248/&gt; ;\n    prov:generatedAtTime \"2026-09-01T14:03:59Z\"^^xsd:dateTime ;\n    prov:wasRevisionOf &lt;https://localhost:4443/orders/10248/?version=4d1e7aa&gt; .</pre>\n        <p>and the same TimeMap as <code>application/link-format</code>:</p>\n        <pre>&lt;https://localhost:4443/orders/10248/&gt;;rel=\"original\",\n&lt;https://localhost:4443/orders/10248/?timemap&gt;;rel=\"self\";type=\"application/link-format\",\n&lt;https://localhost:4443/orders/10248/?version=4d1e7aa&gt;;rel=\"memento\";datetime=\"Sun, 30 Aug 2026 10:12:04 GMT\",\n&lt;https://localhost:4443/orders/10248/?version=8c9f2b1&gt;;rel=\"memento\";datetime=\"Tue, 01 Sep 2026 14:03:59 GMT\"</pre>\n        <p>A TimeMap of a document with no versions answers <code>404 Not Found</code>. A non-versioned document answers <code>406 Not Acceptable</code>\n            when <code>application/link-format</code> is requested.</p>\n        <p>The Memento hypermedia uses IANA-registered relation types: the document advertises its <code>timemap</code> and <code>timegate</code> in\n            <code>Link</code> headers, a historical version links back to the document with <code>rel=original</code>, and the TimeMap identifies itself with\n            <code>rel=self</code>.</p>\n    </div>\n    <div>\n        <h2 id=\"timegate\">TimeGate</h2>\n        <p><code>GET</code> with the <code>?timegate</code> query parameter performs datetime negotiation: the version closest to the\n            <code>Accept-Datetime</code> request header is answered with <code>302 Found</code> and its URI in <code>Location</code>, with ties resolved\n            towards the more recent version. Without <code>Accept-Datetime</code>, the most recent version is selected. The response carries\n            <code>Vary: accept-datetime</code>.</p>\n        <pre>GET /orders/10248/?timegate HTTP/1.1\nHost: localhost:4443\nAccept-Datetime: Mon, 31 Aug 2026 00:00:00 GMT\n\nHTTP/1.1 302 Found\nLocation: https://localhost:4443/orders/10248/?version=4d1e7aa\nVary: accept-datetime\nLink: &lt;https://localhost:4443/orders/10248/&gt;; rel=\"original\"</pre>\n    </div>\n    <div>\n        <h2 id=\"restore-diff\">Restore and diff</h2>\n        <p>From the <a href=\"../../user-guide/version-history/\">version history dialog</a>, a document can be restored to an earlier version — restoring\n            creates a new commit rather than rewriting history, so the intervening versions remain in the TimeMap — and any two versions can be compared\n            as a diff rendered on the document page.</p>\n    </div>\n    <div>\n        <h2 id=\"management\">Management</h2>\n        <div class=\"ac-tabs or-horizontal\">\n            <div class=\"ac-tablist sz-md va-line\" role=\"tablist\">\n                <button aria-controls=\"user-interface-pane\" aria-selected=\"true\" class=\"ac-tab is-on\" id=\"user-interface-tab\" role=\"tab\" type=\"button\"><span class=\"ac-tab-lbl\">User interface</span></button>\n                <button aria-controls=\"command-line-interface-pane\" aria-selected=\"false\" class=\"ac-tab\" id=\"command-line-interface-tab\" role=\"tab\" type=\"button\"><span class=\"ac-tab-lbl\">Command line interface</span></button>\n            </div>\n            <div aria-labelledby=\"user-interface-tab\" class=\"ac-tabpanel\" id=\"user-interface-pane\" role=\"tabpanel\">\n            <p>The <a href=\"../../user-guide/version-history/\">version history dialog</a> lists a document's versions and drives the restore and diff actions.</p>\n            </div>\n            <div aria-labelledby=\"command-line-interface-tab\" class=\"ac-tabpanel\" hidden=\"hidden\" id=\"command-line-interface-pane\" role=\"tabpanel\">\n            <p><samp>ldh get</samp> exposes a versioned document's TimeMap, TimeGate and historical versions through three mutually exclusive options:</p>\n            <table>\n                <caption class=\"ac-vh\">Version history options</caption>\n                <thead>\n                    <tr>\n                        <th scope=\"col\">Option</th>\n                        <th scope=\"col\">Description</th>\n                    </tr>\n                </thead>\n                <tbody>\n                    <tr>\n                        <th scope=\"row\"><samp>--timemap</samp></th>\n                        <td>The version history (PROV-O in RDF formats, or <code>application/link-format</code> via <samp>--accept</samp>)</td>\n                    </tr>\n                    <tr>\n                        <th scope=\"row\"><samp>--version &lt;sha&gt;</samp></th>\n                        <td>The historical version at the given commit</td>\n                    </tr>\n                    <tr>\n                        <th scope=\"row\"><samp>--timegate</samp></th>\n                        <td>Datetime negotiation; the optional <samp>--datetime</samp> takes an RFC 1123 or ISO 8601 datetime. Prints the negotiated version's URI as the only line on stdout, so it pipes into another <samp>ldh get</samp></td>\n                    </tr>\n                </tbody>\n            </table>\n            </div>\n        </div>\n    </div>\n</div>"^^<http://www.w3.org/1999/02/22-rdf-syntax-ns#XMLLiteral> .
