1 \documentclass[a4paper,leqno]{strayman}
2 \let\numberwithin=\notdef
10 \renewcommand{\ge}{\geqslant}
11 \renewcommand{\le}{\leqslant}
13 \newcommand{\has}{\sqsupseteq}
14 \newcommand{\isin}{\sqsubseteq}
16 \newcommand{\nothaspatch}{\mathrel{\,\not\!\not\relax\haspatch}}
17 \newcommand{\notpatchisin}{\mathrel{\,\not\!\not\relax\patchisin}}
18 \newcommand{\haspatch}{\sqSupset}
19 \newcommand{\patchisin}{\sqSubset}
21 \newcommand{\set}[1]{\mathbb #1}
22 \newcommand{\pa}[1]{\varmathbb #1}
23 \newcommand{\pay}[1]{\pa{#1}^+}
24 \newcommand{\pan}[1]{\pa{#1}^-}
26 \newcommand{\p}{\pa{P}}
27 \newcommand{\py}{\pay{P}}
28 \newcommand{\pn}{\pan{P}}
30 %\newcommand{\hasparents}{\underaccent{1}{>}}
31 %\newcommand{\hasparents}{{%
32 % \declareslashed{}{_{_1}}{0}{-0.8}{>}\slashed{>}}}
33 \newcommand{\hasparents}{>_{\mkern-7.0mu _1}}
34 \newcommand{\areparents}{<_{\mkern-14.0mu _1\mkern+5.0mu}}
36 \renewcommand{\implies}{\Rightarrow}
37 \renewcommand{\equiv}{\Leftrightarrow}
38 \renewcommand{\land}{\wedge}
39 \renewcommand{\lor}{\vee}
41 \newcommand{\pancs}{{\mathcal A}}
42 \newcommand{\pends}{{\mathcal E}}
44 \newcommand{\pancsof}[2]{\pancs ( #1 , #2 ) }
45 \newcommand{\pendsof}[2]{\pends ( #1 , #2 ) }
47 \newcommand{\patchof}[1]{{\mathcal P} ( #1 ) }
48 \newcommand{\baseof}[1]{{\mathcal B} ( #1 ) }
50 \newcommand{\eqn}[2]{ #2 \tag*{\mbox{\bf #1}} }
51 \newcommand{\corrolary}[1]{ #1 \tag*{\mbox{\it Corrolary.}} }
53 %\newcommand{\bigforall}{\mathop{\hbox{\huge$\forall$}}}
54 \newcommand{\bigforall}{%
56 {\hbox{\huge$\forall$}}%
57 {\hbox{\Large$\forall$}}%
58 {\hbox{\normalsize$\forall$}}%
59 {\hbox{\scriptsize$\forall$}}}%
63 \newcommand{\qed}{\square}
64 \newcommand{\proof}[1]{{\it Proof.} #1 $\qed$}
72 \desclabelstyle{\nextlinelabel}
74 \item[ $ C \hasparents \set X $ ]
75 The parents of commit $C$ are exactly the set
79 $C$ is a descendant of $D$ in the git commit
80 graph. This is a partial order, namely the transitive closure of
81 $ D \in \set X $ where $ C \hasparents \set X $.
84 Informally, the tree at commit $C$ contains the change
85 made in commit $D$. Does not take account of deliberate reversions by
86 the user or reversion, rebasing or rewinding in
87 non-Topbloke-controlled branches. For merges and Topbloke-generated
88 anticommits or re-commits, the ``change made'' is only to be thought
89 of as any conflict resolution. This is not a partial order because it
92 \item[ $ \p, \py, \pn $ ]
93 A patch $\p$ consists of two sets of commits $\pn$ and $\py$, which
94 are respectively the base and tip git branches. $\p$ may be used
95 where the context requires a set, in which case the statement
96 is to be taken as applying to both $\py$ and $\pn$.
97 All these sets are distinct. Hence:
99 \item[ $ \patchof{ C } $ ]
100 Either $\p$ s.t. $ C \in \p $, or $\bot$.
101 A function from commits to patches' sets $\p$.
103 \item[ $ \pancsof{C}{\set P} $ ]
104 $ \{ A \; | \; A \le C \land A \in \set P \} $
105 i.e. all the ancestors of $C$
106 which are in $\set P$.
108 \item[ $ \pendsof{C}{\set P} $ ]
109 $ \{ E \; | \; E \in \pancsof{C}{\set P}
110 \land \mathop{\not\exists}_{A \in \pancsof{C}{\set P}}
111 A \neq E \land E \le A \} $
112 i.e. all $\le$-maximal commits in $\pancsof{C}{\set P}$.
114 \item[ $ \baseof{C} $ ]
115 $ \pendsof{C}{\pn} = \{ \baseof{C} \} $ where $ C \in \py $.
116 A partial function from commits to commits.
117 See Unique Base, below.
119 \item[ $ C \haspatch \p $ ]
120 $\displaystyle \bigforall_{D \in \py} D \isin C \equiv D \le C $.
121 ~ Informally, $C$ has the contents of $\p$.
123 \item[ $ C \nothaspatch \p $ ]
124 $\displaystyle \bigforall_{D \in \py} D \not\isin C $.
125 ~ Informally, $C$ has none of the contents of $\p$.
127 Non-Topbloke commits are $\nothaspatch \p$ for all $\p$; if a Topbloke
128 patch is applied to a non-Topbloke branch and then bubbles back to
129 the Topbloke patch itself, we hope that git's merge algorithm will
130 DTRT or that the user will no longer care about the Topbloke patch.
136 We maintain these each time we construct a new commit. \\
138 C \has D \implies C \ge D
140 \[\eqn{Unique Base:}{
141 \bigforall_{C \in \py} \pendsof{C}{\pn} = \{ B \}
143 \[\eqn{Tip Contents:}{
144 \bigforall_{C \in \py} D \isin C \equiv
145 { D \isin \baseof{C} \lor \atop
146 (D \in \py \land D \le C) }
148 \[\eqn{Base Acyclic:}{
149 \bigforall_{B \in \pn} D \isin B \implies D \notin \py
152 \bigforall_{C,\p} C \haspatch \p \lor C \nothaspatch \p
154 \[\eqn{Foreign Inclusion:}{
155 \bigforall_{D \text{ s.t. } \patchof{D} = \bot} D \isin C \equiv D \leq C
158 \section{Some lemmas}
160 \[ \eqn{Exclusive Tip Contents:}{
161 \bigforall_{C \in \py}
162 \neg \Bigl[ D \isin \baseof{C} \land ( D \in \py \land D \le C )
165 Ie, the two limbs of the RHS of Tip Contents are mutually exclusive.
168 Let $B = \baseof{C}$ in $D \isin \baseof{C}$. Now $B \in \pn$.
169 So by Base Acyclic $D \isin B \implies D \notin \py$.
172 \bigforall_{C \in \py} D \isin C \equiv
174 D \in \py : & D \le C \\
175 D \not\in \py : & D \isin \baseof{C}
179 \[ \eqn{Tip Self Inpatch:}{
180 \bigforall_{C \in \py} C \haspatch \p
182 Ie, tip commits contain their own patch.
185 Apply Exclusive Tip Contents to some $D \in \py$:
186 $ \bigforall_{C \in \py}\bigforall_{D \in \py}
187 D \isin C \equiv D \le C $
190 \[ \eqn{Exact Ancestors:}{
191 \bigforall_{ C \hasparents \set{R} }
193 ( \mathop{\hbox{\huge{$\vee$}}}_{R \in \set R} D \le R )
197 \[ \eqn{Transitive Ancestors:}{
198 \left[ \bigforall_{ E \in \pendsof{C}{\set P} } E \le M \right] \equiv
199 \left[ \bigforall_{ A \in \pancsof{C}{\set P} } A \le M \right]
203 The implication from right to left is trivial because
204 $ \pends() \subset \pancs() $.
205 For the implication from left to right:
206 by the definition of $\mathcal E$,
207 for every such $A$, either $A \in \pends()$ which implies
208 $A \le M$ by the LHS directly,
209 or $\exists_{A' \in \pancs()} \; A' \neq A \land A \le A' $
210 in which case we repeat for $A'$. Since there are finitely many
211 commits, this terminates with $A'' \in \pends()$, ie $A'' \le M$
212 by the LHS. And $A \le A''$.
215 \section{Commit annotation}
217 We annotate each Topbloke commit $C$ with:
219 \tag*{} \patchof{C} \\
220 \tag*{} \baseof{C}, \text{ if } C \in \py \\
221 \tag*{} \bigforall_{\pa{Q}}
222 \text{ either } C \haspatch \pa{Q} \text{ or } C \nothaspatch \pa{Q} \\
223 \tag*{} \bigforall_{\pay{Q} \not\ni C} \pendsof{C}{\pay{Q}}
226 We do not annotate $\pendsof{C}{\py}$ for $C \in \py$. Doing so would
227 make it wrong to make plain commits with git because the recorded $\pends$
228 would have to be updated. The annotation is not needed because
229 $\forall_{\py \ni C} \; \pendsof{C}{\py} = \{C\}$.
231 \section{Simple commit}
233 A simple single-parent forward commit $C$ as made by git-commit.
235 \tag*{} C \hasparents \{ A \} \\
236 \tag*{} \patchof{C} = \patchof{A} \\
237 \tag*{} D \isin C \equiv D \isin A \lor D = C
240 \subsection{No Replay}
243 \subsection{Unique Base}
244 If $A, C \in \py$ then $\baseof{C} = \baseof{A}$. $\qed$
246 \subsection{Tip Contents}
247 We need to consider only $A, C \in \py$. From Tip Contents for $A$:
248 \[ D \isin A \equiv D \isin \baseof{A} \lor ( D \in \py \land D \le A ) \]
249 Substitute into the contents of $C$:
250 \[ D \isin C \equiv D \isin \baseof{A} \lor ( D \in \py \land D \le A )
252 Since $D = C \implies D \in \py$,
253 and substituting in $\baseof{C}$, this gives:
254 \[ D \isin C \equiv D \isin \baseof{C} \lor
255 (D \in \py \land D \le A) \lor
256 (D = C \land D \in \py) \]
257 \[ \equiv D \isin \baseof{C} \lor
258 [ D \in \py \land ( D \le A \lor D = C ) ] \]
259 So by Exact Ancestors:
260 \[ D \isin C \equiv D \isin \baseof{C} \lor ( D \in \py \land D \le C
264 \subsection{Base Acyclic}
266 Need to consider only $A, C \in \pn$.
268 For $D = C$: $D \in \pn$ so $D \not\in \py$. OK.
270 For $D \neq C$: $D \isin C \equiv D \isin A$, so by Base Acyclic for
271 $A$, $D \isin C \implies D \not\in \py$. $\qed$
273 \subsection{Coherence}
275 \subsubsection{For $A \haspatch P, D = C$:}
276 \[ D \isin C \equiv \ldots \lor t \text{ so } D \haspatch C \]
280 \section{Test more symbols}
284 $ C \nothaspatch \p $
288 $ \p \notpatchisin C $
290 $ \{ B \} \areparents C $