From 0cd315be592e3fbd8820f37de3c677d24741b913 Mon Sep 17 00:00:00 2001
From: Lars Frost <larsf@fsmpi.rwth-aachen.de>
Date: Tue, 19 Nov 2024 13:18:13 +0100
Subject: [PATCH] Add slides for push/fetch/pull and branches

---
 materials/icons/computer_black.svg |   1 +
 materials/icons/host_black.svg     |   1 +
 materials/slides/remotes.typ       | 314 +++++++++++++++++++
 materials/slides/team.typ          | 468 ++++++++++++++++++++++++++++-
 4 files changed, 783 insertions(+), 1 deletion(-)
 create mode 100644 materials/icons/computer_black.svg
 create mode 100644 materials/icons/host_black.svg
 create mode 100644 materials/slides/remotes.typ

diff --git a/materials/icons/computer_black.svg b/materials/icons/computer_black.svg
new file mode 100644
index 0000000..40b5073
--- /dev/null
+++ b/materials/icons/computer_black.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#000000"><path d="M40-120v-80h880v80H40Zm120-120q-33 0-56.5-23.5T80-320v-440q0-33 23.5-56.5T160-840h640q33 0 56.5 23.5T880-760v440q0 33-23.5 56.5T800-240H160Zm0-80h640v-440H160v440Zm0 0v-440 440Z"/></svg>
\ No newline at end of file
diff --git a/materials/icons/host_black.svg b/materials/icons/host_black.svg
new file mode 100644
index 0000000..c1d228b
--- /dev/null
+++ b/materials/icons/host_black.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#000000"><path d="M160-120q-33 0-56.5-23.5T80-200v-560q0-33 23.5-56.5T160-840h200q33 0 56.5 23.5T440-760v560q0 33-23.5 56.5T360-120H160Zm440 0q-33 0-56.5-23.5T520-200v-560q0-33 23.5-56.5T600-840h200q33 0 56.5 23.5T880-760v560q0 33-23.5 56.5T800-120H600Zm-440-80h200v-560H160v560Zm440 0h200v-560H600v560ZM200-360h120v-80H200v80Zm440 0h120v-80H640v80ZM200-480h120v-80H200v80Zm440 0h120v-80H640v80ZM200-600h120v-80H200v80Zm440 0h120v-80H640v80ZM160-200h200-200Zm440 0h200-200Z"/></svg>
\ No newline at end of file
diff --git a/materials/slides/remotes.typ b/materials/slides/remotes.typ
new file mode 100644
index 0000000..5b3743f
--- /dev/null
+++ b/materials/slides/remotes.typ
@@ -0,0 +1,314 @@
+#import "@preview/touying:0.5.3": *
+#import themes.metropolis: *
+
+#import "@preview/cetz:0.3.1"
+#import "@preview/fletcher:0.5.2" as fletcher: node, edge
+#import "@preview/ctheorems:1.1.3": *
+#import "@preview/numbly:0.1.0": numbly
+#import "@preview/codly:1.0.0": *
+
+== Gemeinsame Remotes
+#let new-color = rgb("#2a838f")
+#let label-font-size = 10pt
+#let n(pos, label, name, mode) = {
+  if mode == "vanished" {
+    node(pos, text(label, font: "DejaVu Sans Mono", size: label-font-size, vanish-color), name: name, radius: 10pt, stroke: vanish-color)
+  } else if mode == "new" {
+    node(pos, text(label, font: "DejaVu Sans Mono", size: label-font-size, new-color), name: name, radius: 10pt, stroke: new-color)
+  } else {
+    node(pos, text(label, font: "DejaVu Sans Mono", size: label-font-size), name: name, radius: 10pt)
+  }
+}
+#let e(from, to, mode) = {
+  if mode == "vanished" {
+    edge(from, to, "-|>", stroke: vanish-color)
+  } else if mode == "new" {
+    edge(from, to, "-|>", stroke: new-color)
+  } else {
+    edge(from, to, "-|>")
+  }
+}
+#let arrow(from, to, mode, label) = {
+  if mode == "vanished" {
+    edge(from, to, "-|>", label: label, stroke: vanish-color)
+  } else if mode == "new" {
+    edge(from, to, "-|>", label: text(label, stroke: new-color), stroke: new-color)
+  } else {
+    edge(from, to, "-|>")
+  }
+}
+#let pointer(from, to, label, mode) = {
+  if mode == "vanished" {
+    edge(from, to, "-|>", text(label, font: "DejaVu Sans Mono", size: label-font-size, fill: vanish-color), stroke: vanish-color, label-pos: 0, label-anchor: "south", label-fill: none)
+  } else if mode == "new" {
+    edge(from, to, "-|>", text(label, font: "DejaVu Sans Mono", size: label-font-size, fill: new-color), stroke: new-color, label-pos: 0, label-anchor: "south", label-fill: none)
+  } else {
+    edge(from, to, "-|>", text(label, font: "DejaVu Sans Mono", size: label-font-size), label-pos: 0, label-anchor: "south", label-fill: none)
+  }
+}
+#let client(label) = grid(image("/icons/computer_black.svg", height: 26pt), label)
+#let host = grid(image("/icons/host_black.svg", height: 30pt), text("origin", size: 14pt))
+#let graph1(x, y, b, name, feat, feat-text, main, main-text, merge, merge-text) = {
+  node((x, y), name: name, [
+    #fletcher.diagram(
+      node-stroke: 1pt,
+      spacing: 25pt,
+      node-corner-radius: 4pt,
+      render: (grid, nodes, edges, options) => {
+        cetz.canvas({cetz.draw.rect((-0.1, -0.1), (8.3, 4.3), stroke: none); fletcher.draw-diagram(grid, nodes, edges, debug: options.debug)})
+      },
+      {
+        if main {
+          pointer((4, -0.5), label(b + "G"), main-text, "normal")
+        } else {
+          fletcher.hide({
+            pointer((4, -0.5), label(b + "G"), main-text, "normal")
+          })
+        }
+        if feat {
+          pointer((4, -2.5), label(b + "F"), feat-text, "normal")
+        } else {
+          fletcher.hide({
+            pointer((4, -2.5), label(b + "F"), feat-text, "normal")
+          })
+        }
+        if merge {
+          pointer((5, -1.0), label(b + "M"), merge-text, "normal")
+        } else {
+          fletcher.hide({
+            pointer((5, -1.0), label(b + "M"), merge-text, "normal")
+          })
+        }
+        n((1, 0), `B`, label(b + "B"), "normal")
+        let mode = "normal"
+        n((2, 0), `C`, label(b + "C"), mode)
+        e(label(b + "C"), label(b + "B"), mode)
+        n((3, 0), `D`, label(b + "D"), mode)
+        e(label(b + "D"), label(b + "C"), mode)
+        if feat {
+          n((3, -2), `E`, label(b + "E"), mode)
+          e(label(b + "E"), label(b + "C"), mode)
+          n((4, -2), `F`, label(b + "F"), mode)
+          e(label(b + "F"), label(b + "E"), mode)
+        } else {
+          fletcher.hide({
+            n((3, -2), `E`, label(b + "E"), mode)
+            e(label(b + "E"), label(b + "C"), mode)
+            n((4, -2), `F`, label(b + "F"), mode)
+            e(label(b + "F"), label(b + "E"), mode)
+          })
+        }
+        n((4, 0), "G", label(b + "G"), mode)
+        e(label(b + "G"), label(b + "D"), mode)
+        if merge {
+          n((5, 0), "M", label(b + "M"), mode)
+          e(label(b + "M"), label(b + "F"), mode)
+          e(label(b + "M"), label(b + "G"), mode)
+        } else {
+          fletcher.hide({
+            n((5, 0), "M", label(b + "M"), mode)
+            e(label(b + "M"), label(b + "F"), mode)
+            e(label(b + "M"), label(b + "G"), mode)
+          })
+        }
+      }
+    )
+  ])
+}
+
+#slide(repeat: 10, self => [
+  #let (uncover, only, alternatives) = utils.methods(self)
+  #align(center + top,
+    alternatives[
+      #fletcher.diagram(
+        node-stroke: 1pt,
+        spacing: 0pt,
+        node-corner-radius: 4pt,
+        node-inset: 4pt,
+        {
+          node((0, 2), [#client("Lars")], stroke: none, name: <Lars>)
+          graph1(0, 3, "L", <L>, false, "feat-phi", true, "HEAD->main,\norigin/main", false, none)
+
+          node((2, 2), [#client("Kevin")], stroke: none, name: <Kevin>)
+          fletcher.hide({
+            graph1(2, 3, "K", <K>, false, "feat-phi", true, "HEAD->main,\norigin/main", false, none)
+          })
+
+          node((1, 0), [#host], stroke: none, name: <Host>)
+          fletcher.hide({
+            graph1(1, 1, "H", <H>, false, "feat-phi", true, "main", false, none)
+          })
+        }
+      )
+    ][
+      #fletcher.diagram(
+        node-stroke: 1pt,
+        spacing: 0pt,
+        node-corner-radius: 4pt,
+        node-inset: 4pt,
+        {
+          node((0, 2), [#client("Lars")], stroke: none, name: <Lars>)
+          graph1(0, 3, "L", <L>, false, "feat-phi", true, "HEAD->main,\norigin/main", false, none)
+
+          node((2, 2), [#client("Kevin")], stroke: none, name: <Kevin>)
+          fletcher.hide({
+            graph1(2, 3, "K", <K>, false, "feat-phi", true, "HEAD->main,\norigin/main", false, none)
+          })
+
+          node((1, 0), [#host], stroke: none, name: <Host>)
+          graph1(1, 1, "H", <H>, false, "feat-phi", true, "main", false, none)
+
+          arrow(<L>, <H>, "new", "push")
+        }
+      )
+    ][
+      #fletcher.diagram(
+        node-stroke: 1pt,
+        spacing: 0pt,
+        node-corner-radius: 4pt,
+        node-inset: 4pt,
+        {
+          node((0, 2), [#client("Lars")], stroke: none, name: <Lars>)
+          graph1(0, 3, "L", <L>, false, "feat-phi", true, "HEAD->main,\norigin/main", false, none)
+
+          node((2, 2), [#client("Kevin")], stroke: none, name: <Kevin>)
+          graph1(2, 3, "K", <K>, false, "feat-phi", true, "HEAD->main,\norigin/main", false, none)
+
+          node((1, 0), [#host], stroke: none, name: <Host>)
+          graph1(1, 1, "H", <H>, false, "feat-phi", true, "main", false, none)
+
+          arrow(<H>, <K>, "new", "pull")
+        }
+      )
+    ][
+      #fletcher.diagram(
+        node-stroke: 1pt,
+        spacing: 0pt,
+        node-corner-radius: 4pt,
+        node-inset: 4pt,
+        {
+          node((0, 2), [#client("Lars")], stroke: none, name: <Lars>)
+          graph1(0, 3, "L", <L>, false, "feat-phi", true, "HEAD->main,\norigin/main", false, none)
+
+          node((2, 2), [#client("Kevin")], stroke: none, name: <Kevin>)
+          graph1(2, 3, "K", <K>, true, "feat-phi", true, "HEAD->main,\norigin/main", false, none)
+
+          node((1, 0), [#host], stroke: none, name: <Host>)
+          graph1(1, 1, "H", <H>, false, "feat-phi", true, "main", false, none)
+        }
+      )
+    ][
+      #fletcher.diagram(
+        node-stroke: 1pt,
+        spacing: 0pt,
+        node-corner-radius: 4pt,
+        node-inset: 4pt,
+        {
+          node((0, 2), [#client("Lars")], stroke: none, name: <Lars>)
+          graph1(0, 3, "L", <L>, false, "feat-phi", true, "HEAD->main,\norigin/main", false, none)
+
+          node((2, 2), [#client("Kevin")], stroke: none, name: <Kevin>)
+          graph1(2, 3, "K", <K>, true, "feat-phi, origin/feat-phi", true, "HEAD->main,\norigin/main", false, none)
+
+          node((1, 0), [#host], stroke: none, name: <Host>)
+          graph1(1, 1, "H", <H>, true, "feat-phi", true, "main", false, none)
+
+          arrow(<K>, <H>, "new", "push")
+        }
+      )
+    ][
+      #fletcher.diagram(
+        node-stroke: 1pt,
+        spacing: 0pt,
+        node-corner-radius: 4pt,
+        node-inset: 4pt,
+        {
+          node((0, 2), [#client("Lars")], stroke: none, name: <Lars>)
+          graph1(0, 3, "L", <L>, true, "origin/feat-phi", true, "HEAD->main,\norigin/main", false, none)
+
+          node((2, 2), [#client("Kevin")], stroke: none, name: <Kevin>)
+          graph1(2, 3, "K", <K>, true, "feat-phi, origin/feat-phi", true, "HEAD->main,\norigin/main", false, none)
+
+          node((1, 0), [#host], stroke: none, name: <Host>)
+          graph1(1, 1, "H", <H>, true, "feat-phi", true, "main", false, none)
+
+          arrow(<H>, <L>, "new", "fetch")
+        }
+      )
+    ][
+      #fletcher.diagram(
+        node-stroke: 1pt,
+        spacing: 0pt,
+        node-corner-radius: 4pt,
+        node-inset: 4pt,
+        {
+          node((0, 2), [#client("Lars")], stroke: none, name: <Lars>)
+          graph1(0, 3, "L", <L>, true, "origin/feat-phi", true, "HEAD->main,\norigin/main", false, none)
+
+          node((2, 2), [#client("Kevin")], stroke: none, name: <Kevin>)
+          graph1(2, 3, "K", <K>, true, "feat-phi, origin/feat-phi", true, "origin/main", true, "HEAD->main")
+
+          node((1, 0), [#host], stroke: none, name: <Host>)
+          graph1(1, 1, "H", <H>, true, "feat-phi", true, "main", false, none)
+        }
+      )
+    ][
+      #fletcher.diagram(
+        node-stroke: 1pt,
+        spacing: 0pt,
+        node-corner-radius: 4pt,
+        node-inset: 4pt,
+        {
+          node((0, 2), [#client("Lars")], stroke: none, name: <Lars>)
+          graph1(0, 3, "L", <L>, true, "origin/feat-phi", true, "HEAD->main,\norigin/main", false, none)
+
+          node((2, 2), [#client("Kevin")], stroke: none, name: <Kevin>)
+          graph1(2, 3, "K", <K>, true, "feat-phi, origin/feat-phi", false, none, true, "HEAD->main,\norigin/main")
+
+          node((1, 0), [#host], stroke: none, name: <Host>)
+          graph1(1, 1, "H", <H>, true, "feat-phi", false, none, true, "main")
+
+          arrow(<K>, <H>, "new", "push")
+        }
+      )
+    ][
+      #fletcher.diagram(
+        node-stroke: 1pt,
+        spacing: 0pt,
+        node-corner-radius: 4pt,
+        node-inset: 4pt,
+        {
+          node((0, 2), [#client("Lars")], stroke: none, name: <Lars>)
+          graph1(0, 3, "L", <L>, true, "origin/feat-phi", true, "HEAD->main", true, "origin/main")
+
+          node((2, 2), [#client("Kevin")], stroke: none, name: <Kevin>)
+          graph1(2, 3, "K", <K>, true, "feat-phi, origin/feat-phi", false, none, true, "HEAD->main,\norigin/main")
+
+          node((1, 0), [#host], stroke: none, name: <Host>)
+          graph1(1, 1, "H", <H>, true, "feat-phi", false, none, true, "main")
+
+          arrow(<H>, <L>, "new", "fetch")
+        }
+      )
+    ][
+      #fletcher.diagram(
+        node-stroke: 1pt,
+        spacing: 0pt,
+        node-corner-radius: 4pt,
+        node-inset: 4pt,
+        {
+          node((0, 2), [#client("Lars")], stroke: none, name: <Lars>)
+          graph1(0, 3, "L", <L>, true, "origin/feat-phi", false, none, true, "HEAD->main,\norigin/main")
+
+          node((2, 2), [#client("Kevin")], stroke: none, name: <Kevin>)
+          graph1(2, 3, "K", <K>, true, "feat-phi, origin/feat-phi", false, none, true, "HEAD->main,\norigin/main")
+
+          node((1, 0), [#host], stroke: none, name: <Host>)
+          graph1(1, 1, "H", <H>, true, "feat-phi", false, none, true, "main")
+
+          arrow(<H>, <L>, "new", "pull")
+        }
+      )
+    ]
+  )
+])
\ No newline at end of file
diff --git a/materials/slides/team.typ b/materials/slides/team.typ
index 31640d3..8b5f2b1 100644
--- a/materials/slides/team.typ
+++ b/materials/slides/team.typ
@@ -23,4 +23,470 @@
 ]
 
 == Motivation
-#align(center, image("/images/parallel.png", height: 100%))
\ No newline at end of file
+#align(center, image("/images/parallel.png", height: 100%))
+
+== Pointer
+#let vanish-color = luma(0, 30%)
+#let new-color = rgb("#2a838f")
+#let label-font-size = 14pt
+#let n(pos, label, name, mode) = {
+  if mode == "vanished" {
+    node(pos, text(label, font: "DejaVu Sans Mono", size: label-font-size, vanish-color), name: name, radius: 1em, stroke: vanish-color)
+  } else if mode == "new" {
+    node(pos, text(label, font: "DejaVu Sans Mono", size: label-font-size, new-color), name: name, radius: 1em, stroke: new-color)
+  } else {
+    node(pos, text(label, font: "DejaVu Sans Mono", size: label-font-size), name: name, radius: 1em)
+  }
+}
+#let e(from, to, mode) = {
+  if mode == "vanished" {
+    edge(from, to, "-|>", stroke: vanish-color)
+  } else if mode == "new" {
+    edge(from, to, "-|>", stroke: new-color)
+  } else {
+    edge(from, to, "-|>")
+  }
+}
+#let pointer(from, to, label, mode) = {
+  if mode == "vanished" {
+    edge(from, to, "-|>", text(label, font: "DejaVu Sans Mono", size: label-font-size, fill: vanish-color), stroke: vanish-color, label-pos: 0, label-anchor: "south", label-fill: none)
+  } else if mode == "new" {
+    edge(from, to, "-|>", text(label, font: "DejaVu Sans Mono", size: label-font-size, fill: new-color), stroke: new-color, label-pos: 0, label-anchor: "south", label-fill: none)
+  } else {
+    edge(from, to, "-|>", text(label, font: "DejaVu Sans Mono", size: label-font-size), label-pos: 0, label-anchor: "south", label-fill: none)
+  }
+}
+
+#let v1(mode) = {
+    n((0, 0), `A`, <A>, mode)
+    n((1, 0), `B`, <B>, mode)
+    e(<B>, <A>, mode)
+}
+
+#let v2(mode) = {
+    n((2, 0), `C`, <C>, mode)
+    e(<C>, <B>, mode)
+}
+
+#let v3(mode) = {
+    n((3, 0), `D`, <D>, mode)
+    e(<D>, <C>, mode)
+}
+
+#let v4(mode) = {
+    n((3, -1), `E`, <E>, mode)
+    e(<E>, <C>, mode)
+    n((4, -1), `F`, <F>, mode)
+    e(<F>, <E>, mode)
+}
+
+#let v5(mode) = {
+  n((4, 0), "G", <G>, mode)
+  e(<G>, <D>, mode)
+}
+
+#let m(mode) = {
+  n((5, 0), "M", <M>, mode)
+  e(<M>, <F>, mode)
+  e(<M>, <G>, mode)
+}
+
+#let rebase1(mode) = {
+  n((5, 0), `E*`, <RE>, mode)
+  e(<RE>, <G>, mode)
+}
+
+#let rebase2(mode) = {
+  n((6, 0), `F*`, <RF>, mode)
+  e(<RF>, <RE>, mode)
+}
+
+
+#slide(repeat: 10, self => [
+  #let (uncover, only, alternatives) = utils.methods(self)
+  #grid(columns: 1fr, rows: (auto, 1fr),
+    align(center,
+      alternatives[
+        `git init && git commit && git commit`
+      ][
+        `git tag v0.1`
+      ][
+        `git commit`
+      ][
+        `git branch feat-phi`
+      ][
+        `git commit`
+      ][
+        `git checkout feat-phi`
+      ][
+        `git commit && git commit`
+      ][
+        `git checkout main`
+      ][
+        `git commit`
+      ][
+        `git reset feat-phi~1`
+      ]
+    ),
+    alternatives[
+      #fletcher.diagram(
+        node-stroke: 1pt,
+        spacing: 100pt,
+        node-corner-radius: 4pt,
+        {
+          pointer((1, -0.3), <B>, "HEAD -> main", "new")
+          v1("new")
+          fletcher.hide({
+            v2("normal")
+            v3("normal")
+            v4("normal")
+            v5("normal")
+          })
+        }
+      )
+    ][
+      #fletcher.diagram(
+        node-stroke: 1pt,
+        spacing: 100pt,
+        node-corner-radius: 4pt,
+        {
+          pointer((1, -0.3), <B>, "HEAD -> main, (tag: v0.1)", "new")
+          v1("normal")
+          fletcher.hide({
+            v2("normal")
+            v3("normal")
+            v4("normal")
+            v5("normal")
+          })
+        }
+      )
+    ][
+      #fletcher.diagram(
+        node-stroke: 1pt,
+        spacing: 100pt,
+        node-corner-radius: 4pt,
+        {
+          pointer((2, -0.5), <C>, "HEAD -> main", "new")
+          pointer((1, -0.3), <B>, "(tag: v0.1)", "normal")
+          v1("normal")
+          v2("new")
+          fletcher.hide({
+            v3("normal")
+            v4("normal")
+            v5("normal")
+          })
+        }
+      )
+    ][
+      #fletcher.diagram(
+        node-stroke: 1pt,
+        spacing: 100pt,
+        node-corner-radius: 4pt,
+        {
+          pointer((2, -0.5), <C>, "HEAD -> main, feat-phi", "new")
+          pointer((1, -0.3), <B>, "(tag: v0.1)", "normal")
+          v1("normal")
+          v2("normal")
+        }
+      )
+    ][
+      #fletcher.diagram(
+        node-stroke: 1pt,
+        spacing: 100pt,
+        node-corner-radius: 4pt,
+        {
+          pointer((3, -0.3), <D>, "HEAD -> main", "new")
+          pointer((2, -0.5), <C>, "feat-phi", "normal")
+          pointer((1, -0.3), <B>, "(tag: v0.1)", "normal")
+          v1("normal")
+          v2("normal")
+          v3("new")
+        }
+      )
+    ][
+      #fletcher.diagram(
+        node-stroke: 1pt,
+        spacing: 100pt,
+        node-corner-radius: 4pt,
+        {
+          pointer((3, -0.3), <D>, "main", "normal")
+          pointer((2, -0.5), <C>, "HEAD -> feat-phi", "new")
+          pointer((1, -0.3), <B>, "(tag: v0.1)", "normal")
+          v1("normal")
+          v2("normal")
+          v3("normal")
+        }
+      )
+    ][
+      #fletcher.diagram(
+        node-stroke: 1pt,
+        spacing: 100pt,
+        node-corner-radius: 4pt,
+        {
+          pointer((3, -0.3), <D>, "main", "normal")
+          pointer((4, -1.3), <F>, "HEAD -> feat-phi", "new")
+          pointer((1, -0.3), <B>, "(tag: v0.1)", "normal")
+          v1("normal")
+          v2("normal")
+          v3("normal")
+          v4("new")
+        }
+      )
+    ][
+      #fletcher.diagram(
+        node-stroke: 1pt,
+        spacing: 100pt,
+        node-corner-radius: 4pt,
+        {
+          pointer((3, -0.3), <D>, "HEAD -> main", "new")
+          pointer((4, -1.3), <F>, "feat-phi", "normal")
+          pointer((1, -0.3), <B>, "(tag: v0.1)", "normal")
+          v1("normal")
+          v2("normal")
+          v3("normal")
+          v4("normal")
+          fletcher.hide({
+            v5("normal")
+          })
+        }
+      )
+    ][
+      #fletcher.diagram(
+        node-stroke: 1pt,
+        spacing: 100pt,
+        node-corner-radius: 4pt,
+        {
+          pointer((4, -0.3), <G>, "HEAD -> main", "new")
+          pointer((4, -1.3), <F>, "feat-phi", "normal")
+          pointer((1, -0.3), <B>, "(tag: v0.1)", "normal")
+          v1("normal")
+          v2("normal")
+          v3("normal")
+          v4("normal")
+          v5("new")
+        }
+      )
+    ][
+      #fletcher.diagram(
+        node-stroke: 1pt,
+        spacing: 100pt,
+        node-corner-radius: 4pt,
+        {
+          pointer((3, -1.3), <E>, `HEAD -> main`, "new")
+          pointer((4, -1.3), <F>, `feat-phi`, "normal")
+          pointer((1, -0.3), <B>, `(tag: v0.1)`, "normal")
+          v1("normal")
+          v2("normal")
+          v3("vanished")
+          v4("normal")
+          v5("vanished")
+          fletcher.hide({
+          })
+        }
+      )
+    ]
+  )
+])
+
+== Pointers
+#v(1fr)
+=== Tag
+- `git tag <tag-name>`
+- Unveränderbarer Pointer. `HEAD` kann nicht auf Tags zeigen.
+#v(1fr)
+=== Branch
+- `git branch <branch-name>` oder `git checkout -b <branch-name>`
+- Veränderbarer Pointer. `HEAD` kann auf Branches zeigen und beide bewegen sich bei `git commit` mit.
+#v(1fr)
+
+== Merge
+#slide(repeat: 3, self => [
+  #let (uncover, only, alternatives) = utils.methods(self)
+  #grid(columns: 1fr, rows: (auto, 1fr),
+    align(center,
+      alternatives[
+        
+      ][
+        `git merge feat-phi`
+      ]
+    ),
+    alternatives[
+      #fletcher.diagram(
+        node-stroke: 1pt,
+        spacing: 60pt,
+        node-corner-radius: 4pt,
+        {
+          pointer((4, -0.3), <G>, "HEAD -> main", "normal")
+          pointer((4, -1.3), <F>, "feat-phi", "normal")
+          pointer((1, -0.3), <B>, "(tag: v0.1)", "normal")
+          v1("normal")
+          v2("normal")
+          v3("normal")
+          v4("normal")
+          v5("normal")
+          fletcher.hide({
+          })
+        }
+      )
+    ][
+      #fletcher.diagram(
+        node-stroke: 1pt,
+        spacing: 60pt,
+        node-corner-radius: 4pt,
+        {
+          pointer((5, -0.6), <M>, "HEAD -> main", "new")
+          pointer((4, -1.3), <F>, "feat-phi", "normal")
+          pointer((1, -0.3), <B>, "(tag: v0.1)", "normal")
+          v1("normal")
+          v2("normal")
+          v3("normal")
+          v4("normal")
+          v5("normal")
+          m("new")
+          fletcher.hide({
+          })
+        }
+      )
+    ]
+  )
+])
+
+== Rebase
+#slide(repeat: 5, self => [
+  #let (uncover, only, alternatives) = utils.methods(self)
+  #grid(columns: 1fr, rows: (auto, 1fr),
+    align(center,
+      alternatives[
+        
+      ][
+        `git rebase main`
+      ][
+        `git rebase main (1/3)`
+      ][
+        `git rebase main (2/3)`
+      ][
+        `git rebase main (3/3)`
+      ]
+    ),
+    alternatives[
+      #fletcher.diagram(
+        node-stroke: 1pt,
+        spacing: 60pt,
+        node-corner-radius: 4pt,
+        {
+          pointer((4, -0.3), <G>, "main", "normal")
+          pointer((4, -1.3), <F>, "HEAD -> feat-phi", "normal")
+          pointer((1, -0.3), <B>, "(tag: v0.1)", "normal")
+          v1("normal")
+          v2("normal")
+          v3("normal")
+          v4("normal")
+          v5("normal")
+          fletcher.hide({
+          })
+        }
+      )
+    ][
+      #fletcher.diagram(
+        node-stroke: 1pt,
+        spacing: 60pt,
+        node-corner-radius: 4pt,
+        {
+          pointer((4, -0.3), <G>, "main", "normal")
+          pointer((4, -1.3), <F>, "HEAD -> feat-phi", "normal")
+          pointer((1, -0.3), <B>, "(tag: v0.1)", "normal")
+          node((120pt, 200pt), [Plan: ```
+            pick E
+            pick F
+            update-ref feat-phi  
+          ```], shape: rect)
+          v1("normal")
+          v2("normal")
+          v3("normal")
+          v4("normal")
+          v5("normal")
+          fletcher.hide({
+          })
+        }
+      )
+    ][
+      #fletcher.diagram(
+        node-stroke: 1pt,
+        spacing: 60pt,
+        node-corner-radius: 4pt,
+        {
+          pointer((4, -0.3), <G>, "main", "normal")
+          pointer((5, -0.3), <RE>, "HEAD", "new")
+          pointer((4, -1.3), <F>, "feat-phi", "normal")
+          pointer((1, -0.3), <B>, "(tag: v0.1)", "normal")
+          node((120pt, 200pt), [Plan: ```
+            > pick E
+            pick F
+            update-ref feat-phi  
+          ```], shape: rect)
+          v1("normal")
+          v2("normal")
+          v3("normal")
+          v4("normal")
+          v5("normal")
+          rebase1("new")
+          fletcher.hide({
+          })
+        }
+      )
+    ][
+      #fletcher.diagram(
+        node-stroke: 1pt,
+        spacing: 60pt,
+        node-corner-radius: 4pt,
+        {
+          pointer((4, -0.3), <G>, "main", "normal")
+          pointer((6, -0.3), <RF>, "HEAD", "new")
+          pointer((4, -1.3), <F>, "feat-phi", "normal")
+          pointer((1, -0.3), <B>, "(tag: v0.1)", "normal")
+          node((120pt, 200pt), [Plan: ```
+            pick E
+            > pick F
+            update-ref feat-phi  
+          ```], shape: rect)
+          v1("normal")
+          v2("normal")
+          v3("normal")
+          v4("normal")
+          v5("normal")
+          rebase1("normal")
+          rebase2("new")
+          fletcher.hide({
+          })
+        }
+      )
+    ][
+      #fletcher.diagram(
+        node-stroke: 1pt,
+        spacing: 60pt,
+        node-corner-radius: 4pt,
+        {
+          pointer((4, -0.3), <G>, "main", "normal")
+          pointer((6, -0.3), <RF>, "HEAD -> feat-phi", "new")
+          pointer((1, -0.3), <B>, "(tag: v0.1)", "normal")
+          node((120pt, 200pt), [Plan: ```
+            pick E
+            pick F
+            > update-ref feat-phi
+          ```], shape: rect)
+          v1("normal")
+          v2("normal")
+          v3("normal")
+          v4("vanished")
+          v5("normal")
+          rebase1("normal")
+          rebase2("normal")
+          fletcher.hide({
+          })
+        }
+      )
+    ]
+  )
+])
+
+#include "remotes.typ"
\ No newline at end of file
-- 
GitLab