From 68736ff549afc1201fe729a28aa962ea1d6af13c Mon Sep 17 00:00:00 2001 From: Martin Vuk Date: Tue, 9 Dec 2025 06:27:31 +0100 Subject: [PATCH 1/4] Fiddling with positions --- git-figure.typ | 135 ++++++++++++++++++++++++++++++------------------- 1 file changed, 84 insertions(+), 51 deletions(-) diff --git a/git-figure.typ b/git-figure.typ index b954069..10a3e4f 100644 --- a/git-figure.typ +++ b/git-figure.typ @@ -3,67 +3,100 @@ #import "@preview/fletcher:0.5.8" as fletcher: diagram, node, edge #import fletcher.shapes: house, chevron, pill, hexagon -#let commit-node(coord, hash, ..args) = node(coord, raw(hash), shape: pill, fill: orange.lighten(10%), stroke: none, ..args) -#let commit-object(coord, hash, name, ..args) = node(coord, align(left, [#text(size: 8pt, gray.darken(50%), raw(hash))\ #name]), corner-radius: 7pt, fill: orange.lighten(10%), stroke: none, ..args) +#let commit-color = green +#let tag-color = orange +#let branch-color = purple +#let thin = 0.5pt; +#let thindotted = (thickness: thin, dash: "dotted"); +#let thindashed = (thickness: thin, dash: "dashed"); +#let commit-node(coord, hash, ..args) = node(coord, raw(hash), shape: pill, fill: commit-color.lighten(50%), stroke: thin, ..args) +#let commit-object(coord, hash, name, ..args) = node(coord, align(left, [#text(size: 8pt, gray.darken(50%), raw(hash))\ #name]), corner-radius: 7pt, fill: commit-color.lighten(50%), stroke: none, ..args) +#let tree-object(coord, hash, ..args) = commit-object(coord, hash, [tree], width: 2cm, fill: blue.lighten(50%), ..args) +#let file-object(coord, hash, name, ..args) = commit-object(coord, hash, name, width: 2cm, fill: gray.lighten(50%), ..args) #diagram(debug: 1, node-stroke: 2pt, edge-stroke: 1pt, { - let thin = 0.5pt; - let thindashed = (thickness: thin, dash: "dashed"); - let store = (1, 7) + let store = (0.3, 6.7) + let (co1, co2) = { + let x = 0.2 + let y = store.at(1) + ((x, y+0.5), (x, y+1)) + } + let (tree1, tree2) = { + let x = 1.2 + ((x, co1.at(1)), (x, co2.at(1))) + } + let (f1, f2, f3) = { + let x = 2.2; + let y = store.at(1) + ((x, y), (x, y + 0.5), (x, y + 1)) + } let (A, B, C, D, E, F, G) = ((2, 6), (2, 5), (2, 4), (2, 3), (2, 2), (2, 1), (2, 0)) let (B1, B2) = ((3, 4.5), (3, 3.5)) let (E1, E2, E3) = ((3, 1.5), (3, 0.5), (3, -0.5)) - let (Br1, Br2) = ((G.at(0)-0.5, G.at(1)), (E2.at(0)-0.5, E2.at(1))) + let (Br1, Br2) = ((F.at(0)-0.5, F.at(1)), (E2.at(0)-0.5, E2.at(1))) let (T1, T2) = ((E.at(0)-0.5, E.at(1)), (B.at(0)-0.5, B.at(1))) - let refs = (3, 8) + let refs = (2.7, store.at(1)) let tags = (0.5, 3) let commit = (3.7, 2.5) - let branches = (1.2, -1) - let stage =(3.7, -1) + let branches = (0.5, 0) + let stage =(3.7, 0) let mc = (2.5, D.at(1)-0.5) - commit-object(store, "e264a1", [second commit]) - commit-object((store.at(0), store.at(1)+0.3), "16f29", [first commit], width: 2.8cm) - node(store, [Content addressable object store], width: 3cm, stroke: none, - enclose:((store.at(0), store.at(1)), (store.at(0)+1, store.at(1)+2))) - //node(A, [A 16f299], shape: pill, name: ) + //node(store, [Content addressable object store], stroke: none, width: 4cm) + commit-object(co1, "e264a1", [second commit]) + commit-object(co2, "16f29", [first commit], width: 2.8cm) + tree-object(tree1, "16f29") + tree-object(tree2, "16f29") + file-object(f1, "16f29", [`new content`]) + file-object(f2, "16f29", [`unchanged`]) + file-object(f3, "16f29", [`first content`]) + edge(tree1, f2, [`bar.txt`], "->", label-angle: auto) + edge(tree1, f1, [`foo.txt`], "->", label-angle: auto) + edge(tree2, f2, [`bar.txt`], "->", label-angle: auto) + edge(tree2, f3, [`foo.txt`], "->", label-angle: auto) + edge(co2, tree2, "->") + edge(co1, tree1, "->") + + + + //node(store, width: 5cm, stroke: thin, enclose:(co1, f3, f1)) + commit-node(A, "A 16f299") - node(B, [B 16f299], shape: pill) - node(C, [C 16f299], shape: pill) - node(D, [D 16f299], shape: pill) - node(E, [E 16f299], shape: pill) - node(F, [F 16f299], shape: pill) - node(G, [16f299], shape: pill) + commit-node(B, "B 16f299") + commit-node(C, "C 16f299") + commit-node(D, "D 16f299") + commit-node(E, "E 16f299") + commit-node(F, "F 16f299") // merge commit node(mc, [Merge commit\ #text(size: 8pt)[commit with two parents]], stroke: thin, corner-radius: 10pt) // merged branch - node(B1, [B1 16f299], shape: pill) - node(B2, [B2 16f299], shape: pill) + commit-node(B1, "B1 16f299") + commit-node(B2, "B2 16f299") // unmerged branch - node(E1, [E1 16f299], shape: pill) - node(E2, [E2 16f299], shape: pill) - node(E3, [E3 16f299], shape: pill, stroke: (dash: "dashed")) + commit-node(E1, "E1 16f299") + commit-node(E2, "E2 16f299") + commit-node(E3, "E3 16f299", fill: none, stroke: thindashed) // branches - node(Br1, [main], shape: hexagon, stroke: purple) - node(Br2, [hotfix], shape: hexagon, stroke: purple) + node(Br1, [main], shape: hexagon, stroke: branch-color) + node(Br2, [hotfix], shape: hexagon, stroke: branch-color) // tags - node(T1, [v-1.0], shape: chevron, stroke: green) - node(T2, [v-1.1], shape: chevron, stroke: green) + node(T1, [v-1.0], shape: chevron, stroke: tag-color) + node(T2, [v-1.1], shape: chevron, stroke: tag-color) // refs - node(refs, stroke: none, snap: false, enclose: (refs, (refs.at(0)+2, refs.at(0)+2)), - table(columns: 1, align: left, [*References* (`.git/refs`)], [*Tags* (`.git/refs/tags`)\ `tag-1`: `8dd6d4b...`], [*Branches* (`.git/refs/heads`) \ `main`: `8dd6d4b...`\ + node(refs, stroke: none, snap: false, enclose: (refs, (refs.at(0)+2, refs.at(1)+2)), + table(columns: 1, stroke: thin, align: left+top, [*References* (`.git/refs`)], [*Tags* (`.git/refs/tags`)\ `tag-1`: `8dd6d4b...`], [*Branches* (`.git/refs/heads`) \ `main`: `8dd6d4b...`\ `feature-1`: `8dd6d4b...`\ `hotfix`: `8dd6d4b...`]) ) - node(branches, [#text(stroke: purple.darken(50%))[BRANCH]\ #text[reference that moves when commiting canges]], - stroke: thin, corner-radius: 10pt, inset: 0pt, width: 1cm, enclose: ( + node(branches, [#text(branch-color.darken(20%))[*BRANCH*]\ #text[reference that moves along when commiting canges]], + stroke: thin, corner-radius: 10pt, inset: 5pt, width: 3cm) /*, enclose: ( (branches.at(0)-0.5, branches.at(1)), - (branches.at(0)+0.5, branches.at(1)))) - node(tags, [#text(stroke: green.darken(50%))[TAG]\ reference that don't move], + (branches.at(0)+1, branches.at(1))))*/ + node(tags, [#text(tag-color)[*TAG*]\ reference that don't move], stroke: thin, corner-radius: 10pt, inset: 0pt, width: 1cm, enclose: ((tags.at(0)-0.5, tags.at(1)), (tags.at(0)+1, tags.at(1)))) node(stage, [*Staging area*\ #text(size: 8pt)[filesystem snapshot that will be commited in the next commit]], stroke: thindashed, corner-radius: 10pt, width: 3cm) node(commit, [ - *COMMIT*\ snapshot of filesystem tree in object store\ + #text(commit-color)[*COMMIT*]\ snapshot of filesystem tree in object store\ #rect[ ``` tree 65c47fee... @@ -75,20 +108,20 @@ Add bar.txt ```] ], width:5cm, stroke: thin, corner-radius: 10pt) node((G.at(0)+0.4, G.at(1) - 0.3), [*Version history*\ - #text(size: 8pt)[ - Commits are nodes in _Directed Acyclic Graph (DAG)_ that describes version history - ]], stroke:none, width: 5cm) - node(A, snap: false, enclose: (A, E3), stroke: thindashed, width: 3cm) - let ic = (A.at(0)-0.6, A.at(1)+0.2); + #align(left, text(size: 8pt)[ + _Directed Acyclic Graph (DAG)_ describes version history. + Commits are nodes in DAG, while an edge connect a commit with its parent. + ])], stroke:none, width: 5cm) + node(A, snap: false, enclose: (A, E3), stroke: thindashed, width: 3cm, fill: gray.lighten(70%)) + let ic = (A.at(0)+0.7, A.at(1)-0.2); node(ic, [Initial commit], shape: pill, stroke: thin) - edge(ic, A, stroke: thin) + edge(ic, A, stroke: thindotted) // history edge(B, A, "->") edge(C, B, "->") edge(D, C, "->") edge(E, D, "->") edge(F, E, "->") - edge(G, F, "->") // merged branch edge(B1, B, "->", layer: 1, label: [parent of], label-angle: auto) edge(B2, B1, "->") @@ -98,17 +131,17 @@ Add bar.txt edge(E2, E1, "->") edge(E3, E2, "->", stroke: (dash: "dashed")) // refs - edge(Br1, G) + edge(Br1, F) edge(Br2, E2) edge(T1, E) edge(T2, B) - edge(Br1, branches, stroke: thin) - edge(Br2, branches, stroke: thin) - edge(T1, tags, stroke: thin) - edge(T2, tags, stroke: thin) - edge(commit, E, stroke: thin) - edge(stage, E3, stroke: thindashed) + edge(Br1, branches, stroke: thindotted) + edge(Br2, branches, stroke: thindotted) + edge(T1, tags, stroke: thindotted) + edge(T2, tags, stroke: thindotted) + edge(commit, E, stroke: thindotted) + edge(stage, E3, stroke: thindotted) edge((-0.5, A.at(1)), (-0.5, G.at(1)), "->", label: [time], label-side: left, label-angle: 90deg) - edge(mc, D, stroke: thin) + edge(mc, D, stroke: thindotted) } ) \ No newline at end of file From b946ffd6b4dd1de96961cc1f2592d2ce8c74aaac Mon Sep 17 00:00:00 2001 From: Martin Vuk Date: Wed, 10 Dec 2025 03:48:19 +0100 Subject: [PATCH 2/4] Fiddling with positions --- git-figure.typ | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/git-figure.typ b/git-figure.typ index 10a3e4f..f76002f 100644 --- a/git-figure.typ +++ b/git-figure.typ @@ -16,7 +16,7 @@ #diagram(debug: 1, node-stroke: 2pt, edge-stroke: 1pt, { - let store = (0.3, 6.7) + let store = (0.6, 6.7) let (co1, co2) = { let x = 0.2 let y = store.at(1) @@ -36,13 +36,13 @@ let (E1, E2, E3) = ((3, 1.5), (3, 0.5), (3, -0.5)) let (Br1, Br2) = ((F.at(0)-0.5, F.at(1)), (E2.at(0)-0.5, E2.at(1))) let (T1, T2) = ((E.at(0)-0.5, E.at(1)), (B.at(0)-0.5, B.at(1))) - let refs = (2.7, store.at(1)) + let refs = (3.5, store.at(1)) let tags = (0.5, 3) - let commit = (3.7, 2.5) + let commit = (3.8, 2.5) let branches = (0.5, 0) let stage =(3.7, 0) let mc = (2.5, D.at(1)-0.5) - //node(store, [Content addressable object store], stroke: none, width: 4cm) + node(store, [Content addressable object store], stroke: none, width: 4cm) commit-object(co1, "e264a1", [second commit]) commit-object(co2, "16f29", [first commit], width: 2.8cm) tree-object(tree1, "16f29") @@ -59,7 +59,7 @@ - //node(store, width: 5cm, stroke: thin, enclose:(co1, f3, f1)) + node(store, stroke: thin, enclose:(co1, f3, f1)) commit-node(A, "A 16f299") commit-node(B, "B 16f299") @@ -83,17 +83,19 @@ node(T1, [v-1.0], shape: chevron, stroke: tag-color) node(T2, [v-1.1], shape: chevron, stroke: tag-color) // refs - node(refs, stroke: none, snap: false, enclose: (refs, (refs.at(0)+2, refs.at(1)+2)), - table(columns: 1, stroke: thin, align: left+top, [*References* (`.git/refs`)], [*Tags* (`.git/refs/tags`)\ `tag-1`: `8dd6d4b...`], [*Branches* (`.git/refs/heads`) \ `main`: `8dd6d4b...`\ + node(refs, stroke: thin, inset:5pt, snap: false, enclose: (refs, (refs.at(0)+1, refs.at(1)+1)), + align(left, [ + *References* (`.git/refs`)\ *Tags* (`.git/refs/tags`)\ `tag-1`: `8dd6d4b...`\ *Branches* (`.git/refs/heads`) \ `main`: `8dd6d4b...`\ `feature-1`: `8dd6d4b...`\ - `hotfix`: `8dd6d4b...`]) - ) + `hotfix`: `8dd6d4b...` + ]) + ) node(branches, [#text(branch-color.darken(20%))[*BRANCH*]\ #text[reference that moves along when commiting canges]], - stroke: thin, corner-radius: 10pt, inset: 5pt, width: 3cm) /*, enclose: ( + stroke: thin, corner-radius: 10pt, inset: 5pt, width: 4cm) /*, enclose: ( (branches.at(0)-0.5, branches.at(1)), (branches.at(0)+1, branches.at(1))))*/ node(tags, [#text(tag-color)[*TAG*]\ reference that don't move], - stroke: thin, corner-radius: 10pt, inset: 0pt, width: 1cm, enclose: ((tags.at(0)-0.5, tags.at(1)), (tags.at(0)+1, tags.at(1)))) + stroke: thin, corner-radius: 10pt, inset: 5pt, width: 4cm)/*, enclose: ((tags.at(0)-0.5, tags.at(1)), (tags.at(0)+1, tags.at(1))))*/ node(stage, [*Staging area*\ #text(size: 8pt)[filesystem snapshot that will be commited in the next commit]], stroke: thindashed, corner-radius: 10pt, width: 3cm) node(commit, [ #text(commit-color)[*COMMIT*]\ snapshot of filesystem tree in object store\ From ec79d9e0c7169bc12909f7411e4d67b6db069647 Mon Sep 17 00:00:00 2001 From: Martin Vuk Date: Wed, 10 Dec 2025 04:52:35 +0100 Subject: [PATCH 3/4] Reorganize positioning --- git-figure.typ | 125 ++++++++++++++++++++++++++++--------------------- 1 file changed, 71 insertions(+), 54 deletions(-) diff --git a/git-figure.typ b/git-figure.typ index f76002f..d28f519 100644 --- a/git-figure.typ +++ b/git-figure.typ @@ -9,34 +9,47 @@ #let thin = 0.5pt; #let thindotted = (thickness: thin, dash: "dotted"); #let thindashed = (thickness: thin, dash: "dashed"); -#let commit-node(coord, hash, ..args) = node(coord, raw(hash), shape: pill, fill: commit-color.lighten(50%), stroke: thin, ..args) -#let commit-object(coord, hash, name, ..args) = node(coord, align(left, [#text(size: 8pt, gray.darken(50%), raw(hash))\ #name]), corner-radius: 7pt, fill: commit-color.lighten(50%), stroke: none, ..args) -#let tree-object(coord, hash, ..args) = commit-object(coord, hash, [tree], width: 2cm, fill: blue.lighten(50%), ..args) -#let file-object(coord, hash, name, ..args) = commit-object(coord, hash, name, width: 2cm, fill: gray.lighten(50%), ..args) +#let commit-node(coord, hash, ..args) = node( + coord, raw(hash), shape: pill, fill: commit-color.lighten(50%), stroke: thin, ..args) +#let commit-object(coord, hash, name, ..args) = node( + coord, align(left, [#text(size: 8pt, gray.darken(50%), raw(hash))\ #name]), + corner-radius: 7pt, fill: commit-color.lighten(50%), stroke: none, ..args) +#let tree-object(coord, hash, ..args) = commit-object(coord, hash, [tree], + width: 2cm, fill: blue.lighten(50%), ..args) +#let file-object(coord, hash, name, ..args) = commit-object(coord, hash, name, + width: 2cm, fill: gray.lighten(50%), ..args) #diagram(debug: 1, node-stroke: 2pt, edge-stroke: 1pt, { - let store = (0.6, 6.7) + let x_0 = 2 + let x_delta = 1 + let x_1 = x_0 + 1.5 + /*let store = (2cm, 2cm) let (co1, co2) = { - let x = 0.2 + let x = 2cm let y = store.at(1) - ((x, y+0.5), (x, y+1)) + ((x, y+1.5cm), (x, y+1.5cm)) } let (tree1, tree2) = { - let x = 1.2 + let x = 3.2cm ((x, co1.at(1)), (x, co2.at(1))) } let (f1, f2, f3) = { - let x = 2.2; + let x = 4.2cm; let y = store.at(1) - ((x, y), (x, y + 0.5), (x, y + 1)) - } + ((x, y), (x, y + 0.5cm), (x, y + 1cm)) + }*/ let (A, B, C, D, E, F, G) = ((2, 6), (2, 5), (2, 4), (2, 3), (2, 2), (2, 1), (2, 0)) let (B1, B2) = ((3, 4.5), (3, 3.5)) let (E1, E2, E3) = ((3, 1.5), (3, 0.5), (3, -0.5)) - let (Br1, Br2) = ((F.at(0)-0.5, F.at(1)), (E2.at(0)-0.5, E2.at(1))) - let (T1, T2) = ((E.at(0)-0.5, E.at(1)), (B.at(0)-0.5, B.at(1))) - let refs = (3.5, store.at(1)) + let (Br1, Br2) = ((F.at(0)-1, F.at(1)), (E2.at(0)-1, E2.at(1))) + let (T1, T2) = ((E.at(0)-1, E.at(1)), (B.at(0)-1, B.at(1))) + let (Ah, Bh, Ch, Dh, Eh, Fh, Gh) = ("0a3d36", "ce2d1d", "0459b3", "b62527", "93f4ee", "7b67bd", "a6eb69") + let (B1h, B2h) = ("2e4289", "7ed6de") + let (E1h, E2h, E3h) = ("aa083c", "3f28d1", "2e9986") + //e05dcdcb48cd0772313f") + /* + let refs = (12cm, store.at(1)) let tags = (0.5, 3) let commit = (3.8, 2.5) let branches = (0.5, 0) @@ -58,32 +71,43 @@ edge(co1, tree1, "->") - node(store, stroke: thin, enclose:(co1, f3, f1)) - - commit-node(A, "A 16f299") - commit-node(B, "B 16f299") - commit-node(C, "C 16f299") - commit-node(D, "D 16f299") - commit-node(E, "E 16f299") - commit-node(F, "F 16f299") + */ + commit-node(A, Ah, name: ) + commit-node(B, Bh, name: ) + commit-node(C, Ch, name: ) + commit-node(D, Dh, name: ) + commit-node(E, Eh, name: ) + commit-node(F, Fh, name: ) // merge commit - node(mc, [Merge commit\ #text(size: 8pt)[commit with two parents]], stroke: thin, corner-radius: 10pt) + //node(mc, [Merge commit\ #text(size: 8pt)[commit with two parents]], stroke: thin, corner-radius: 10pt) // merged branch - commit-node(B1, "B1 16f299") - commit-node(B2, "B2 16f299") + commit-node((rel: (1, -0.5), to: ), B1h, name: ) + commit-node((rel: (0, -1), to: ), B2h, name: ) // unmerged branch - commit-node(E1, "E1 16f299") - commit-node(E2, "E2 16f299") - commit-node(E3, "E3 16f299", fill: none, stroke: thindashed) + commit-node((rel: (1, -0.5), to: ), E1h, name: ) + commit-node((rel: (0, -1), to: ), E2h, name: ) + commit-node((rel: (0, -1), to: ), E3h, fill: none, stroke: thindashed, name: ) // branches - node(Br1, [main], shape: hexagon, stroke: branch-color) - node(Br2, [hotfix], shape: hexagon, stroke: branch-color) + node((rel: (-1, 0), to: ), [main], shape: hexagon, stroke: branch-color, name:
) + edge(
, , "->", stroke: thin) + node((rel: (-2, 0), to: ), [hotfix], shape: hexagon, stroke: branch-color, name: ) + edge(, , "->", stroke: thin) // tags - node(T1, [v-1.0], shape: chevron, stroke: tag-color) - node(T2, [v-1.1], shape: chevron, stroke: tag-color) + node((rel: (-1, 0), to: ), [v-1.0], shape: chevron, stroke: tag-color, name: ) + edge(, , "->", stroke: thin) + node((rel: (-1, 0), to: ), [v-1.1], shape: chevron, stroke: tag-color, name: ) + edge(, , "->", stroke: thin) + // enclose the tree + node((rel: (0, -1), to: ), [*Version history*\ + #align(left, text(size: 8pt)[ + _Directed Acyclic Graph (DAG)_ describes version history. + Commits are nodes in DAG, while an edge connect a commit with its parent. + ])], stroke:none, width: 5cm, name: ) + node(snap: false, enclose: (, , ), stroke: thindashed, width: 3cm, fill: gray.lighten(70%)) // refs - node(refs, stroke: thin, inset:5pt, snap: false, enclose: (refs, (refs.at(0)+1, refs.at(1)+1)), + /* + node(refs, stroke: thin, inset:5pt, snap: false, enclose: (refs, (refs.at(0)+1cm, refs.at(1)+1cm)), align(left, [ *References* (`.git/refs`)\ *Tags* (`.git/refs/tags`)\ `tag-1`: `8dd6d4b...`\ *Branches* (`.git/refs/heads`) \ `main`: `8dd6d4b...`\ `feature-1`: `8dd6d4b...`\ @@ -109,34 +133,26 @@ committer MV ") - edge(C, B, "->") - edge(D, C, "->") - edge(E, D, "->") - edge(F, E, "->") + edge(, , "->") + edge(, , "->") + edge(, , "->") + edge(, , "->") + edge(, , "->") // merged branch - edge(B1, B, "->", layer: 1, label: [parent of], label-angle: auto) - edge(B2, B1, "->") - edge(D, B2, "->") + edge(, , "->", layer: 1, label: [parent of], label-angle: auto) + edge(, , "->") + edge(, , "->") // unmerged branch - edge(E1, E, "->") - edge(E2, E1, "->") - edge(E3, E2, "->", stroke: (dash: "dashed")) + edge(, , "->") + edge(, , "->") + edge(, , "->", stroke: (dash: "dashed")) // refs - edge(Br1, F) - edge(Br2, E2) - edge(T1, E) - edge(T2, B) + /* edge(Br1, branches, stroke: thindotted) edge(Br2, branches, stroke: thindotted) edge(T1, tags, stroke: thindotted) @@ -145,5 +161,6 @@ Add bar.txt edge(stage, E3, stroke: thindotted) edge((-0.5, A.at(1)), (-0.5, G.at(1)), "->", label: [time], label-side: left, label-angle: 90deg) edge(mc, D, stroke: thindotted) + */ } ) \ No newline at end of file From e1dcc1bf5e93a4fc754e93bc1f65e99be6dafeeb Mon Sep 17 00:00:00 2001 From: Martin Vuk Date: Wed, 10 Dec 2025 06:38:14 +0100 Subject: [PATCH 4/4] Much improved version of the diagram --- git-figure.pdf | Bin 0 -> 46670 bytes git-figure.typ | 100 +++++++++++++++++++++++++++++++------------------ 2 files changed, 63 insertions(+), 37 deletions(-) create mode 100644 git-figure.pdf diff --git a/git-figure.pdf b/git-figure.pdf new file mode 100644 index 0000000000000000000000000000000000000000..818188d8ae1e5ceb32cdc08726aef7d549c632e9 GIT binary patch literal 46670 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", label-angle: auto) - edge(tree1, f1, [`foo.txt`], "->", label-angle: auto) - edge(tree2, f2, [`bar.txt`], "->", label-angle: auto) - edge(tree2, f3, [`foo.txt`], "->", label-angle: auto) + edge(co2, tree2, "->") edge(co1, tree1, "->") @@ -74,13 +69,18 @@ node(store, stroke: thin, enclose:(co1, f3, f1)) */ commit-node(A, Ah, name: ) + node((rel:(-1, 0), to: ), [Initial commit], corner-radius: 10pt, stroke: thin, name:) + edge(, , stroke: thindotted) commit-node(B, Bh, name: ) commit-node(C, Ch, name: ) commit-node(D, Dh, name: ) + node((rel: (0.5, -0.5), to: ), [Merge commit\ #text(size: 8pt)[commit with two parents]], stroke: thin, + corner-radius: 10pt, name: ) + edge(, , stroke: thindotted) + commit-node(E, Eh, name: ) commit-node(F, Fh, name: ) // merge commit - //node(mc, [Merge commit\ #text(size: 8pt)[commit with two parents]], stroke: thin, corner-radius: 10pt) // merged branch commit-node((rel: (1, -0.5), to: ), B1h, name: ) commit-node((rel: (0, -1), to: ), B2h, name: ) @@ -105,6 +105,35 @@ Commits are nodes in DAG, while an edge connect a commit with its parent. ])], stroke:none, width: 5cm, name: ) node(snap: false, enclose: (, , ), stroke: thindashed, width: 3cm, fill: gray.lighten(70%)) + // branch cloud + node((rel: (-0.5, -1), to: ), [#text(branch-color.darken(20%), smallcaps[*Branches*])\ references that moves along when commiting canges], + stroke: thin, corner-radius: 10pt, inset: 5pt, width: 4cm, name: ) + edge(, , corner: left, stroke: thindotted) + edge(,
, corner: left, stroke: thindotted) + // tag cloud + node((rel: (-0.5, 1.5), to: ), [#text(tag-color, smallcaps[*Tags*])\ references that don't move], + stroke: thin, corner-radius: 10pt, inset: 5pt, width: 4cm, name: ) + edge(, , corner: right, stroke: thindotted) + edge(, , corner: left, stroke: thindotted) + // staging area + node((rel: (1, 0), to: ), [#smallcaps[*Staging area*]\ #text(size: 8pt)[filesystem snapshot that will be commited in + the next commit]], stroke: thindashed, corner-radius: 10pt, width: 3cm, name: ) + edge(, , stroke: thindotted) + // commit + node((rel: (1, 0.5), to: ), [ + #text(commit-color, smallcaps[*Commit*])\ #align(left)[snapshot of filesystem tree in object store]\ + #table(columns: 1, fill: commit-color.lighten(50%), align: left, [commit hash: #raw(E1h)], + raw(block: true, " +tree 65c47fee +parent 16f299 +author MV ) + edge(, , corner: right, stroke: thindotted) // refs /* node(refs, stroke: thin, inset:5pt, snap: false, enclose: (refs, (refs.at(0)+1cm, refs.at(1)+1cm)), @@ -114,27 +143,13 @@ `hotfix`: `8dd6d4b...` ]) ) - node(branches, [#text(branch-color.darken(20%))[*BRANCH*]\ #text[reference that moves along when commiting canges]], - stroke: thin, corner-radius: 10pt, inset: 5pt, width: 4cm) /*, enclose: ( + /*, enclose: ( (branches.at(0)-0.5, branches.at(1)), (branches.at(0)+1, branches.at(1))))*/ - node(tags, [#text(tag-color)[*TAG*]\ reference that don't move], - stroke: thin, corner-radius: 10pt, inset: 5pt, width: 4cm)/*, enclose: ((tags.at(0)-0.5, tags.at(1)), (tags.at(0)+1, tags.at(1))))*/ - node(stage, [*Staging area*\ #text(size: 8pt)[filesystem snapshot that will be commited in the next commit]], stroke: thindashed, corner-radius: 10pt, width: 3cm) - node(commit, [ - #text(commit-color)[*COMMIT*]\ snapshot of filesystem tree in object store\ - #rect[ - ``` -tree 65c47fee... -parent 16f299... -author MV , , "->") edge(, , "->") edge(, , "->", stroke: (dash: "dashed")) - // refs - /* - edge(Br1, branches, stroke: thindotted) - edge(Br2, branches, stroke: thindotted) - edge(T1, tags, stroke: thindotted) - edge(T2, tags, stroke: thindotted) - edge(commit, E, stroke: thindotted) - edge(stage, E3, stroke: thindotted) - edge((-0.5, A.at(1)), (-0.5, G.at(1)), "->", label: [time], label-side: left, label-angle: 90deg) - edge(mc, D, stroke: thindotted) - */ + // object store + let obj_store = (rel: (-0.5, 1), to: ) + node((rel: (4cm, -2.2cm), to: ), align(left)[Content addressable object store \ #raw(".git/objects")], stroke: none, snap: false ) + commit-object((rel: (1.5, 2), to: ), E1h, [second commit], name: ) + commit-object((rel: (1.5, 3), to: ), "16f29a", [first commit], width: 2.8cm, name: ) + tree-object((rel:(-1, 0), to: ), tree1h, name:) + edge(, , stroke: thin, "->") + tree-object((rel:(-1, 0), to: ), "e05dcd", name: ) + edge(, , stroke: thin, "->") + file-object((rel:(-1, -1), to: ), "cb48cd", [`new content`], name: ) + file-object((rel:(-1, 0), to: ), "077231", [`unchanged`], name: ) + file-object((rel:(-1, 1), to: ), "d1bc32", [`first content`], name: ) + edge(, , [`bar.txt`], "->", label-angle: auto, stroke: thin) + edge(, , [`foo.txt`], "->", label-angle: auto, stroke: thin) + edge(, , [`bar.txt`], "->", label-angle: auto, stroke: thin) + edge(, , [`foo.txt`], "->", label-angle: auto, stroke: thin) + node((rel: (0, 0.5), to:), enclose: (, , ), stroke: thindashed, corner-radius: 5pt, + fill: gray.lighten(70%), snap: false, layer: -2) + // time direction + edge((0.2, 2.5), (0.2, 1), "->", label: [time], label-side: left, label-angle: 90deg, + stroke: thindashed) + edge(, , stroke: thin, "->", corner: right) } ) \ No newline at end of file