1 \documentclass[a4paper,leqno]{strayman}
3 \let\numberwithin=\notdef
11 \renewcommand{\ge}{\geqslant}
12 \renewcommand{\le}{\leqslant}
14 \newcommand{\has}{\sqsupseteq}
15 \newcommand{\isin}{\sqsubseteq}
17 \newcommand{\nothaspatch}{\mathrel{\,\not\!\not\relax\haspatch}}
18 \newcommand{\notpatchisin}{\mathrel{\,\not\!\not\relax\patchisin}}
19 \newcommand{\haspatch}{\sqSupset}
20 \newcommand{\patchisin}{\sqSubset}
22 \newif\ifhidehack\hidehackfalse
23 \DeclareRobustCommand\hidefromedef[2]{%
24 \hidehacktrue\ifhidehack#1\else#2\fi\hidehackfalse}
25 \newcommand{\pa}[1]{\hidefromedef{\varmathbb{#1}}{#1}}
27 \newcommand{\set}[1]{\mathbb{#1}}
28 \newcommand{\pay}[1]{\pa{#1}^+}
29 \newcommand{\pan}[1]{\pa{#1}^-}
31 \newcommand{\p}{\pa{P}}
32 \newcommand{\py}{\pay{P}}
33 \newcommand{\pn}{\pan{P}}
35 \newcommand{\pr}{\pa{R}}
36 \newcommand{\pry}{\pay{R}}
37 \newcommand{\prn}{\pan{R}}
39 %\newcommand{\hasparents}{\underaccent{1}{>}}
40 %\newcommand{\hasparents}{{%
41 % \declareslashed{}{_{_1}}{0}{-0.8}{>}\slashed{>}}}
42 \newcommand{\hasparents}{>_{\mkern-7.0mu _1}}
43 \newcommand{\areparents}{<_{\mkern-14.0mu _1\mkern+5.0mu}}
45 \renewcommand{\implies}{\Rightarrow}
46 \renewcommand{\equiv}{\Leftrightarrow}
47 \renewcommand{\land}{\wedge}
48 \renewcommand{\lor}{\vee}
50 \newcommand{\pancs}{{\mathcal A}}
51 \newcommand{\pends}{{\mathcal E}}
53 \newcommand{\pancsof}[2]{\pancs ( #1 , #2 ) }
54 \newcommand{\pendsof}[2]{\pends ( #1 , #2 ) }
56 \newcommand{\patchof}[1]{{\mathcal P} ( #1 ) }
57 \newcommand{\baseof}[1]{{\mathcal B} ( #1 ) }
59 \newcommand{\eqn}[2]{ #2 \tag*{\mbox{\bf #1}} }
60 \newcommand{\corrolary}[1]{ #1 \tag*{\mbox{\it Corrolary.}} }
62 %\newcommand{\bigforall}{\mathop{\hbox{\huge$\forall$}}}
63 \newcommand{\bigforall}{%
65 {\hbox{\huge$\forall$}}%
66 {\hbox{\Large$\forall$}}%
67 {\hbox{\normalsize$\forall$}}%
68 {\hbox{\scriptsize$\forall$}}}%
71 \newcommand{\Largeexists}{\mathop{\hbox{\Large$\exists$}}}
72 \newcommand{\Largenexists}{\mathop{\hbox{\Large$\nexists$}}}
74 \newcommand{\qed}{\square}
75 \newcommand{\proof}[1]{{\it Proof.} #1 $\qed$}
77 \newcommand{\gathbegin}{\begin{gather} \tag*{}}
78 \newcommand{\gathnext}{\\ \tag*{}}
81 \newcommand{\false}{f}
89 \desclabelstyle{\nextlinelabel}
91 \item[ $ C \hasparents \set X $ ]
92 The parents of commit $C$ are exactly the set
96 $C$ is a descendant of $D$ in the git commit
97 graph. This is a partial order, namely the transitive closure of
98 $ D \in \set X $ where $ C \hasparents \set X $.
100 \item[ $ C \has D $ ]
101 Informally, the tree at commit $C$ contains the change
102 made in commit $D$. Does not take account of deliberate reversions by
103 the user or reversion, rebasing or rewinding in
104 non-Topbloke-controlled branches. For merges and Topbloke-generated
105 anticommits or re-commits, the ``change made'' is only to be thought
106 of as any conflict resolution. This is not a partial order because it
109 \item[ $ \p, \py, \pn $ ]
110 A patch $\p$ consists of two sets of commits $\pn$ and $\py$, which
111 are respectively the base and tip git branches. $\p$ may be used
112 where the context requires a set, in which case the statement
113 is to be taken as applying to both $\py$ and $\pn$.
114 All these sets are distinct. Hence:
116 \item[ $ \patchof{ C } $ ]
117 Either $\p$ s.t. $ C \in \p $, or $\bot$.
118 A function from commits to patches' sets $\p$.
120 \item[ $ \pancsof{C}{\set P} $ ]
121 $ \{ A \; | \; A \le C \land A \in \set P \} $
122 i.e. all the ancestors of $C$
123 which are in $\set P$.
125 \item[ $ \pendsof{C}{\set P} $ ]
126 $ \{ E \; | \; E \in \pancsof{C}{\set P}
127 \land \mathop{\not\exists}_{A \in \pancsof{C}{\set P}}
128 E \neq A \land E \le A \} $
129 i.e. all $\le$-maximal commits in $\pancsof{C}{\set P}$.
131 \item[ $ \baseof{C} $ ]
132 $ \pendsof{C}{\pn} = \{ \baseof{C} \} $ where $ C \in \py $.
133 A partial function from commits to commits.
134 See Unique Base, below.
136 \item[ $ C \haspatch \p $ ]
137 $\displaystyle \bigforall_{D \in \py} D \isin C \equiv D \le C $.
138 ~ Informally, $C$ has the contents of $\p$.
140 \item[ $ C \nothaspatch \p $ ]
141 $\displaystyle \bigforall_{D \in \py} D \not\isin C $.
142 ~ Informally, $C$ has none of the contents of $\p$.
144 Non-Topbloke commits are $\nothaspatch \p$ for all $\p$; if a Topbloke
145 patch is applied to a non-Topbloke branch and then bubbles back to
146 the Topbloke patch itself, we hope that git's merge algorithm will
147 DTRT or that the user will no longer care about the Topbloke patch.
153 We maintain these each time we construct a new commit. \\
155 C \has D \implies C \ge D
157 \[\eqn{Unique Base:}{
158 \bigforall_{C \in \py} \pendsof{C}{\pn} = \{ B \}
160 \[\eqn{Tip Contents:}{
161 \bigforall_{C \in \py} D \isin C \equiv
162 { D \isin \baseof{C} \lor \atop
163 (D \in \py \land D \le C) }
165 \[\eqn{Base Acyclic:}{
166 \bigforall_{B \in \pn} D \isin B \implies D \notin \py
169 \bigforall_{C,\p} C \haspatch \p \lor C \nothaspatch \p
171 \[\eqn{Foreign Inclusion:}{
172 \bigforall_{D \text{ s.t. } \patchof{D} = \bot} D \isin C \equiv D \leq C
175 \section{Some lemmas}
177 \[ \eqn{Exclusive Tip Contents:}{
178 \bigforall_{C \in \py}
179 \neg \Bigl[ D \isin \baseof{C} \land ( D \in \py \land D \le C )
182 Ie, the two limbs of the RHS of Tip Contents are mutually exclusive.
185 Let $B = \baseof{C}$ in $D \isin \baseof{C}$. Now $B \in \pn$.
186 So by Base Acyclic $D \isin B \implies D \notin \py$.
189 \bigforall_{C \in \py} D \isin C \equiv
191 D \in \py : & D \le C \\
192 D \not\in \py : & D \isin \baseof{C}
196 \[ \eqn{Tip Self Inpatch:}{
197 \bigforall_{C \in \py} C \haspatch \p
199 Ie, tip commits contain their own patch.
202 Apply Exclusive Tip Contents to some $D \in \py$:
203 $ \bigforall_{C \in \py}\bigforall_{D \in \py}
204 D \isin C \equiv D \le C $
207 \[ \eqn{Exact Ancestors:}{
208 \bigforall_{ C \hasparents \set{R} }
210 ( \mathop{\hbox{\huge{$\vee$}}}_{R \in \set R} D \le R )
214 \[ \eqn{Transitive Ancestors:}{
215 \left[ \bigforall_{ E \in \pendsof{C}{\set P} } E \le M \right] \equiv
216 \left[ \bigforall_{ A \in \pancsof{C}{\set P} } A \le M \right]
220 The implication from right to left is trivial because
221 $ \pends() \subset \pancs() $.
222 For the implication from left to right:
223 by the definition of $\mathcal E$,
224 for every such $A$, either $A \in \pends()$ which implies
225 $A \le M$ by the LHS directly,
226 or $\exists_{A' \in \pancs()} \; A' \neq A \land A \le A' $
227 in which case we repeat for $A'$. Since there are finitely many
228 commits, this terminates with $A'' \in \pends()$, ie $A'' \le M$
229 by the LHS. And $A \le A''$.
231 \[ \eqn{Calculation Of Ends:}{
232 \bigforall_{C \hasparents \set A}
233 \pendsof{C}{\set P} =
235 \Bigl[ \Largeexists_{A \in \set A}
236 E \in \pendsof{A}{\set P} \Bigr] \land
237 \Bigl[ \Largenexists_{B \in \set A}
238 E \neq B \land E \le B \Bigr]
243 \section{Commit annotation}
245 We annotate each Topbloke commit $C$ with:
249 \baseof{C}, \text{ if } C \in \py
252 \text{ either } C \haspatch \pa{Q} \text{ or } C \nothaspatch \pa{Q}
254 \bigforall_{\pay{Q} \not\ni C} \pendsof{C}{\pay{Q}}
257 We do not annotate $\pendsof{C}{\py}$ for $C \in \py$. Doing so would
258 make it wrong to make plain commits with git because the recorded $\pends$
259 would have to be updated. The annotation is not needed because
260 $\forall_{\py \ni C} \; \pendsof{C}{\py} = \{C\}$.
262 \section{Simple commit}
264 A simple single-parent forward commit $C$ as made by git-commit.
266 \tag*{} C \hasparents \{ A \} \\
267 \tag*{} \patchof{C} = \patchof{A} \\
268 \tag*{} D \isin C \equiv D \isin A \lor D = C
271 \subsection{No Replay}
274 \subsection{Unique Base}
275 If $A, C \in \py$ then $\baseof{C} = \baseof{A}$. $\qed$
277 \subsection{Tip Contents}
278 We need to consider only $A, C \in \py$. From Tip Contents for $A$:
279 \[ D \isin A \equiv D \isin \baseof{A} \lor ( D \in \py \land D \le A ) \]
280 Substitute into the contents of $C$:
281 \[ D \isin C \equiv D \isin \baseof{A} \lor ( D \in \py \land D \le A )
283 Since $D = C \implies D \in \py$,
284 and substituting in $\baseof{C}$, this gives:
285 \[ D \isin C \equiv D \isin \baseof{C} \lor
286 (D \in \py \land D \le A) \lor
287 (D = C \land D \in \py) \]
288 \[ \equiv D \isin \baseof{C} \lor
289 [ D \in \py \land ( D \le A \lor D = C ) ] \]
290 So by Exact Ancestors:
291 \[ D \isin C \equiv D \isin \baseof{C} \lor ( D \in \py \land D \le C
295 \subsection{Base Acyclic}
297 Need to consider only $A, C \in \pn$.
299 For $D = C$: $D \in \pn$ so $D \not\in \py$. OK.
301 For $D \neq C$: $D \isin C \equiv D \isin A$, so by Base Acyclic for
302 $A$, $D \isin C \implies D \not\in \py$. $\qed$
304 \subsection{Coherence and patch inclusion}
306 Need to consider $D \in \py$
308 \subsubsection{For $A \haspatch P, D = C$:}
314 $ D \isin C \equiv \ldots \lor \true \text{ so } D \haspatch C $.
316 \subsubsection{For $A \haspatch P, D \neq C$:}
317 Ancestors: $ D \le C \equiv D \le A $.
319 Contents: $ D \isin C \equiv D \isin A \lor f $
320 so $ D \isin C \equiv D \isin A $.
323 \[ A \haspatch P \implies C \haspatch P \]
325 \subsubsection{For $A \nothaspatch P$:}
327 Firstly, $C \not\in \py$ since if it were, $A \in \py$.
330 Now by contents of $A$, $D \notin A$, so $D \notin C$.
333 \[ A \nothaspatch P \implies C \nothaspatch P \]
336 \subsection{Foreign inclusion:}
338 If $D = C$, trivial. For $D \neq C$:
339 $D \isin C \equiv D \isin A \equiv D \le A \equiv D \le C$. $\qed$
343 Given $L, R^+, R^-$ where
344 $\patchof{R^+} = \pry, \patchof{R^-} = \prn$.
345 Construct $C$ which has $\pr$ removed.
346 Used for removing a branch dependency.
348 C \hasparents \{ L \}
350 \patchof{C} = \patchof{L}
354 R \in \py : & \baseof{R} \ge \baseof{L}
355 \land [\baseof{L} = M \lor \baseof{L} = \baseof{M}] \\
356 R \in \pn : & R \ge \baseof{L}
357 \land M = \baseof{L} \\
358 \text{otherwise} : & \false
362 xxx want to prove $D \isin C \equiv D \not\in pry \land D \isin L$.
366 Merge commits $L$ and $R$ using merge base $M$ ($M < L, M < R$):
368 C \hasparents \{ L, R \}
370 \patchof{C} = \patchof{L}
374 (D \isin L \land D \isin R) \lor D = C : & \true \\
375 (D \not\isin L \land D \not\isin R) \land D \neq C : & \false \\
376 \text{otherwise} : & D \not\isin M
380 \subsection{Conditions}
382 \[ \eqn{ Tip Merge }{
385 R \in \py : & \baseof{R} \ge \baseof{L}
386 \land [\baseof{L} = M \lor \baseof{L} = \baseof{M}] \\
387 R \in \pn : & R \ge \baseof{L}
388 \land M = \baseof{L} \\
389 \text{otherwise} : & \false
393 \subsection{No Replay}
395 \subsubsection{For $D=C$:} $D \isin C, D \le C$. OK.
397 \subsubsection{For $D \isin L \land D \isin R$:}
398 $D \isin C$. And $D \isin L \implies D \le L \implies D \le C$. OK.
400 \subsubsection{For $D \neq C \land D \not\isin L \land D \not\isin R$:}
403 \subsubsection{For $D \neq C \land D \not\isin L \land D \not\isin R$:}
406 \subsubsection{For $D \neq C \land (D \isin L \equiv D \not\isin R)
407 \land D \not\isin M$:}
408 $D \isin C$. Also $D \isin L \lor D \isin R$ so $D \le L \lor D \le
411 \subsubsection{For $D \neq C \land (D \isin L \equiv D \not\isin R)
413 $D \not\isin C$. Also $D \isin L \lor D \isin R$ so $D \le L \lor D \le
418 \subsection{Unique Base}
420 Need to consider only $C \in \py$, ie $L \in \py$,
421 and calculate $\pendsof{C}{\pn}$. So we will consider some
422 putative ancestor $A \in \pn$ and see whether $A \le C$.
424 By Exact Ancestors for C, $A \le C \equiv A \le L \lor A \le R \lor A = C$.
425 But $C \in py$ and $A \in \pn$ so $A \neq C$.
426 Thus $A \le C \equiv A \le L \lor A \le R$.
428 By Unique Base of L and Transitive Ancestors,
429 $A \le L \equiv A \le \baseof{L}$.
431 \subsubsection{For $R \in \py$:}
433 By Unique Base of $R$ and Transitive Ancestors,
434 $A \le R \equiv A \le \baseof{R}$.
436 But by Tip Merge condition on $\baseof{R}$,
437 $A \le \baseof{L} \implies A \le \baseof{R}$, so
438 $A \le \baseof{R} \lor A \le \baseof{L} \equiv A \le \baseof{R}$.
439 Thus $A \le C \equiv A \le \baseof{R}$.
440 That is, $\baseof{C} = \baseof{R}$.
442 \subsubsection{For $R \in \pn$:}
444 By Tip Merge condition on $R$,
445 $A \le \baseof{L} \implies A \le R$, so
446 $A \le R \lor A \le \baseof{L} \equiv A \le R$.
447 Thus $A \le C \equiv A \le R$.
448 That is, $\baseof{C} = R$.