Skip to content

Graphite

Graphite is an optional source for g2g, never a requirement. Where a repository already uses it, g2g can read the stacks it describes, adopt them into its own graph, and mirror its own structure back. These commands live under g2g graphite so that someone who does not use Graphite never has to read about them.

Once g2g adopts a branch it stops asking Graphite about it, so without these commands gt log would keep showing a structure that is quietly wrong.

Terminal window
g2g graphite mirror # what would it take for Graphite to agree?
g2g graphite mirror --apply
g2g graphite mirror --prune --apply # also untrack, in Graphite, what g2g does not record
g2g graphite adopt # adopt what Graphite declares into g2g's graph
g2g graphite adopt --apply

Neither command ever removes a branch from g2g’s graph. They keep the two records in step; they do not hand ownership over. A branch can sit in g2g’s graph, be tracked by Graphite, and appear in a GitHub stack all at once. See Sources for which record answers for a branch.

Both refuse outright in a repository that does not already use Graphite. Reading Graphite’s forest is what enrols a repository, so even a preview has to stop first. No g2g command enrols a repository, including the one that writes Graphite.

Adopting and mirroring are not a symmetric pair, and adopting then mirroring does not return you to where you started. A record in g2g’s graph carries a fork point, the parent’s tip when the edge was written, which is what lets restack work out which commits are a branch’s own. Graphite has nowhere to put it. So adopting manufactures a fork point for each branch, and mirroring has to throw it away.

graphite adopt graphite mirror
Writes g2g’s graph only Graphite only
Re-running additive; never undoes brings Graphite to the same answer again
On disagreement refuses overwrites Graphite; that is the job
Who answers for the branch afterwards g2g unchanged

graphite adopt records what Graphite declares, so g2g can answer for those branches and restack them. It writes only g2g’s graph, and it is additive: it adds the edges g2g lacks, and refuses a branch g2g already records under a different parent rather than silently reverting a deliberate change. That makes it safe to re-run when someone tracks a new branch in gt.

It is not guessing. Graphite declares each parent, so the rule that track never chooses a parent is not being relaxed; the declaration is the answer. Branches Graphite names that this checkout lacks are skipped, since recording one would put a branch in the graph that no command could act on.

Adoption is the authority claim. Afterwards g2g answers for everything it adopted, and --from graphite is how you see Graphite’s view of those branches again:

Terminal window
g2g status --from graphite # Graphite's record, drawn in g2g's format
g2g github status --from graphite # and its pull requests, as Graphite groups them

Graphite is read whole, so graphite adopt takes neither --branch nor --scope. A branch g2g records as a declared trunk is treated as a disagreement rather than recorded under the parent Graphite shows for it (see Shape the stack for declared trunks).

To adopt a stack from its pull requests instead, see Adopting a published stack.

graphite mirror reconciles Graphite so it records what g2g’s graph records, about the branches g2g knows, and leaves everything else in Graphite alone. It writes only Graphite, and it is the only command that does. g2g keeps answering for every branch it already answered for.

g2g’s graph and Graphite What the mirror does
g2g has an edge Graphite lacks gt track --parent <p>
the two disagree about a parent gt track --parent <p>, reparenting it
Graphite has an edge g2g lacks nothing, unless --prune

It works on the whole forest, branch by branch, and needs no pull request, push or network. It names each branch explicitly to gt, so it never checks anything out. Graphite requires a --parent it already tracks, so writes go parents before children, and a g2g root Graphite has never heard of blocks the mirror rather than being invented: only gt init establishes a Graphite trunk, and enrolling a repository is not this command’s business.

--prune also untracks, in Graphite, the branches g2g’s graph does not record. It is opt-in, because “this branch’s work has landed” is certain and “Graphite knows a branch we do not” is not: it is just as likely to be one you tracked in gt on purpose. A prune also refuses a branch whose child g2g does know, because gt untrack takes the whole subtree with it, and the rest are pruned deepest first. --prune is the only way the mirror removes anything from Graphite, and g2g’s graph is never changed.

See design-docs/source-alignment.md for the reasoning behind both directions, and Compatibility and storage for the Graphite versions g2g supports.