gitgraph.php 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. <?php
  2. require("user.inc.php");
  3. require("template.inc.php");
  4. tpl_header();
  5. ?>
  6. <h2>The .gitgraph command</h2>
  7. <p>Here's a grammar of the language in ABNF syntax (don't get too hung up on
  8. the parsing ambiguities, please, I'm sure you'll understand what I mean).
  9. <p><strong>Don't like grammars?</strong> Don't worry, I have examples below
  10. you can crib from, including explanations.
  11. <p>Like grammars? Never seen ABNF before? Don't worry, it's easy to understand
  12. if you know the basic ideas behind grammars. Most things are self-explanatory,
  13. just the weird number/asterisk prefixes might need some explaining. Basically
  14. <code>a*b</code> is the same as a <code>{a,b}</code> suffix in most of today's
  15. regular expression dialects (both <code>a</code> and <code>b</code> are
  16. optional, as always), and an <code>a</code> prefix is the same as a
  17. <code>{a}</code> suffix in regex.
  18. <pre><code class="abnf">
  19. UALPHA = %x41-5A
  20. IDENT = ALPHA / DIGIT / "-" / "/" / "."
  21. SPACE = 1*WSP
  22. literal-string = DQUOTE *(%x00-21 / %x23-FF) DQUOTE ; strings can contain anything except double quotes; no escaping mechanism
  23. dimmed = "?"
  24. derived = "'"
  25. commit-id = 1*(IDENT) [derived] [dimmed]
  26. ref-id = 1*IDENT
  27. auto-commit-id = (UALPHA / DIGIT) *IDENT [derived] [dimmed]
  28. kw-align = ("align" / "a") SPACE
  29. kw-branch = ("branch" / "b") SPACE
  30. kw-commit = ("commit" / "c") SPACE
  31. kw-dashed = ("dashed" / "-")
  32. kw-dim = ("dim" / "d")
  33. kw-dotted = ("dotted" / ".")
  34. kw-edge = ("edge" / "e") SPACE
  35. kw-label = ("label" / "l") SPACE
  36. kw-merge = ("merge" / "m") SPACE
  37. kw-mergeto = ("mergeto" / "m") SPACE
  38. kw-remote = ("remote" / "r") SPACE
  39. kw-symref = ("symref" / "s") SPACE
  40. kw-tag = ("tag" / "t") SPACE
  41. kw-up = ("up" / "u") SPACE
  42. graph = ".gitgraph" SPACE definition *(*WSP ";" *WSP definition) *WSP
  43. definition = cluster-def / align-def / commit-def / edge-def / merge-def / symref-def / up-def
  44. cluster-def = ""
  45. align-def = kw-align commit-id 1*(SPACE commit-id)
  46. commit-def = (kw-commit commit / commit-short) *(SPACE commit)
  47. commit = commit-id *WSP [commit-attrs]
  48. commit-short = auto-commit-id *WSP [commit-attrs]
  49. commit-attrs = "[" *WSP commit-attr *(SPACE commit-attr) *WSP "]"
  50. commit-attr = cattr-branch / cattr-label / cattr-mergeto / cattr-remote / cattr-tag
  51. cattr-branch = kw-branch ref-id
  52. cattr-label = kw-label (1*IDENT / literal-string)
  53. cattr-mergeto = kw-mergeto commit-id
  54. cattr-remote = kw-remote ref-id
  55. cattr-tag = kw-tag ref-id
  56. edge-def = kw-edge commit-id commit-id edge-attrs
  57. edge-attrs = edge-attr *(SPACE edge-attr)
  58. edge-attr = eattr-dashed / eattr-dim / eattr-dotted / eattr-label
  59. eattr-dashed = kw-dashed
  60. eattr-dim = kw-dim
  61. eattr-dotted = kw-dotted
  62. eattr-label = kw-label (1*IDENT / literal-string)
  63. merge-def = kw-merge commit-id 2*(SPACE commit-id)
  64. symref-def = kw-symref ref-id / "HEAD" [dimmed]
  65. up-def = kw-up commit-id 1*(SPACE commit-id)
  66. </code></pre>
  67. <h3>Examples</h3>
  68. <p>We'll be working our way up here. (Line breaks inserted for clarity, of
  69. course on IRC you can't use any.)
  70. <table class="large">
  71. <tr><th>Code</th><th>Generated graph</th></tr>
  72. <tr><td><pre class="wrap">
  73. .gitgraph A B C
  74. </pre></td><td><img src="/g/NT.png"></td></tr>
  75. <tr><td><pre class="wrap">
  76. .gitgraph A B C;
  77. D E F[mergeto C]
  78. </pre>
  79. <p>My first merge, yay!
  80. </td><td><img src="/g/NU.png"></td></tr>
  81. <tr><td><pre class="wrap">
  82. .gitgraph A B C;;
  83. D E F[mergeto C]
  84. </pre>
  85. <p>More spacing because the empty definition starts a cluster.
  86. </td><td><img src="/g/NV.png"></td></tr>
  87. <tr><td><pre class="wrap">
  88. .gitgraph A B C;;
  89. D E F[mergeto C];
  90. align A D
  91. </pre>
  92. <p>Maybe we want to align the two root commits at the same level...
  93. </td><td><img src="/g/OC.png"></td></tr>
  94. <tr><td><pre class="wrap">
  95. .gitgraph A B C[branch master?];;
  96. A' B' C'[branch master]
  97. </pre>
  98. <p>Three new features at once!
  99. <ul>
  100. <li>We add branch labels to some commits.
  101. <li>The question mark <em>dims</em> a commit or pretty much anything,
  102. typically to show an old version/state.
  103. <li><code>A</code> and <code>A'</code> are automatically linked to visualize
  104. commit rewriting, e.g. rebases.
  105. </ul>
  106. <p>The cluster split (<code>;;</code>) helps the layouting &ndash; in this
  107. case it helped Graphviz render the two histories in the correct order.
  108. However, this is a little hit-and-miss.
  109. </td><td><img src="/g/OD.png"></td></tr>
  110. <tr><td><pre class="wrap">
  111. .gitgraph A B C[tag v0.1 remote origin/master]
  112. </pre>
  113. <p>We can do some other types of references, too.
  114. </td><td><img src="/g/NY.png"></td></tr>
  115. <tr><td><pre class="wrap">
  116. .gitgraph A B C[branch master remote origin/master];
  117. HEAD? master;
  118. symref FETCH_HEAD origin/master;;
  119. A D E[branch test];
  120. HEAD test
  121. </pre>
  122. <p>New lessons:
  123. <ul>
  124. <li>We can draw a dimmed HEAD and a proper one; easy!
  125. <li>HEAD is a special case of a symbolic ref; the "symref" keyword is needed
  126. if you want to draw symbolic refs with other names.
  127. <li>Two series of commits can share commits. The first usage determines
  128. where it is rendered. Generally you can reuse commit names virtually
  129. everywhere.
  130. <li>It really pays off putting any related refs in the same cluster.
  131. Experiment with putting the <code>;;</code> in any different place and
  132. you'll see what I mean.
  133. </ul></td><td><img src="/g/N-.png"></td></tr>
  134. <tr><td><pre class="wrap">
  135. .gitgraph A[label "I like really long commit titles"] B C;
  136. A D E
  137. </pre>
  138. <p>If you want to make a commit description super verbose, you can put it as a
  139. label and still reuse the commit's original name in other parts of the
  140. definition.
  141. </td><td><img src="/g/O0.png"></td></tr>
  142. <tr><td><pre class="wrap">
  143. .gitgraph A B;
  144. merge C B ... X[label ...];
  145. edge C X label "this history is boring" dashed;;
  146. F; G; edge G F
  147. </pre>
  148. <p>Thought I didn't have you covered with exotic features like octopus merges?
  149. Hah, think again.
  150. <p>Also, notice how I can just "make up" commits as children for the merge and
  151. they will be auto-created. Whenever you mention a commit somewhere that isn't
  152. part of a sequence, it will be created as an (otherwise) unlinked commit,
  153. until you do something else that links it up.
  154. <p>You noticed the elliptical commits, I'm sure. Basically you can use "..."
  155. once to automatically create a differently-rendered fake commit that suggests
  156. that there are more commits than the graph shows. If you want to use it a
  157. second time, well, two commits can't have the same name, hence the label trick
  158. which achieves the same look.
  159. <p>Finally, you can use the "edge" command to add a label to an existing edge.
  160. It will not automatically create a new edge, though, as can be seen in the
  161. right part of the example. (We can also style edges using the keywords
  162. "dashed", "dim" and "dotted".)
  163. </td><td><img src="/g/Pc.png"></td></tr>
  164. <tr><th colspan="2">Troubleshooting example</th></tr>
  165. <tr><td><p>Attempt 1:
  166. <pre class="wrap">
  167. .gitgraph A B C[branch origin/master?] D? E? F?[branch master?];
  168. C G H I[branch origin/master];
  169. I D' E' F'[branch master]
  170. </pre>
  171. <p>This looks a little chaotic, doesn't it? How can we fix that? Well, ideally
  172. D-F and D'-F' would be aligned on the same level, right? Let's try that
  173. next...
  174. </td><td><img src="/g/OL.png"></td></tr>
  175. <tr><td><p>Attempt 2:
  176. <pre class="wrap">
  177. .gitgraph A B C[branch origin/master?] D? E? F?[branch master?];
  178. C G H I[branch origin/master];
  179. I D' E' F'[branch master];
  180. <strong>align D? D'</strong>
  181. </pre>
  182. <p>Wow, that's even worse! (Spoiler: if we repeat the same for E and F, it
  183. doesn't get much better...)
  184. <p>Fortunately there's a different approach if we take a step back. We told
  185. Graphviz that D should be above C (due to the arrow between them) and D'
  186. should be above I. Can't we tell it that D should be above I, too? Yes we can!
  187. Let's check it out:
  188. </td><td><img src="/g/OM.png"></td></tr>
  189. <tr><td><p>Attempt 3:
  190. <pre class="wrap">
  191. .gitgraph A B C[branch origin/master?] D? E? F?[branch master?];
  192. C G H I[branch origin/master];
  193. I D' E' F'[branch master];
  194. <strong>up I D?</strong>
  195. </pre>
  196. <p>Say, that looks quite decent. Let's stick with this one.
  197. </td><td><img src="/g/OR.png"></td></tr>
  198. </table>
  199. <p>Some more remarks without examples:
  200. <ul>
  201. <li>Commits and all ref types share the same namespace. You can't have a
  202. commit and a branch that are both called <code>master</code>, for example.
  203. <li>You can use the <code>edge</code> keyword to link arbitrary nodes if you
  204. really want to, but please don't. I'm not sure my sanity will survive that.
  205. </ul>
  206. <script src="hljs/highlight.pack.js"></script>
  207. <script>hljs.highlightAll();</script>
  208. <?php tpl_footer();