1 \documentclass[a4paper,leqno]{strayman}
3 \let\numberwithin=\notdef
11 \renewcommand{\ge}{\geqslant}
12 \renewcommand{\le}{\leqslant}
13 \newcommand{\nge}{\ngeqslant}
14 \newcommand{\nle}{\nleqslant}
16 \newcommand{\has}{\sqsupseteq}
17 \newcommand{\isin}{\sqsubseteq}
19 \newcommand{\nothaspatch}{\mathrel{\,\not\!\not\relax\haspatch}}
20 \newcommand{\notpatchisin}{\mathrel{\,\not\!\not\relax\patchisin}}
21 \newcommand{\haspatch}{\sqSupset}
22 \newcommand{\patchisin}{\sqSubset}
24 \newif\ifhidehack\hidehackfalse
25 \DeclareRobustCommand\hidefromedef[2]{%
26 \hidehacktrue\ifhidehack#1\else#2\fi\hidehackfalse}
27 \newcommand{\pa}[1]{\hidefromedef{\varmathbb{#1}}{#1}}
29 \newcommand{\set}[1]{\mathbb{#1}}
30 \newcommand{\pay}[1]{\pa{#1}^+}
31 \newcommand{\pan}[1]{\pa{#1}^-}
33 \newcommand{\p}{\pa{P}}
34 \newcommand{\py}{\pay{P}}
35 \newcommand{\pn}{\pan{P}}
37 \newcommand{\pr}{\pa{R}}
38 \newcommand{\pry}{\pay{R}}
39 \newcommand{\prn}{\pan{R}}
41 %\newcommand{\hasparents}{\underaccent{1}{>}}
42 %\newcommand{\hasparents}{{%
43 % \declareslashed{}{_{_1}}{0}{-0.8}{>}\slashed{>}}}
44 \newcommand{\hasparents}{>_{\mkern-7.0mu _1}}
45 \newcommand{\areparents}{<_{\mkern-14.0mu _1\mkern+5.0mu}}
47 \renewcommand{\implies}{\Rightarrow}
48 \renewcommand{\equiv}{\Leftrightarrow}
49 \renewcommand{\land}{\wedge}
50 \renewcommand{\lor}{\vee}
52 \newcommand{\pancs}{{\mathcal A}}
53 \newcommand{\pends}{{\mathcal E}}
55 \newcommand{\pancsof}[2]{\pancs ( #1 , #2 ) }
56 \newcommand{\pendsof}[2]{\pends ( #1 , #2 ) }
58 \newcommand{\merge}[4]{{\mathcal M}(#1,#2,#3,#4)}
59 %\newcommand{\merge}[4]{{#2 {{\frac{ #1 }{ #3 } #4}}}}
61 \newcommand{\patch}{{\mathcal P}}
62 \newcommand{\base}{{\mathcal B}}
64 \newcommand{\patchof}[1]{\patch ( #1 ) }
65 \newcommand{\baseof}[1]{\base ( #1 ) }
67 \newcommand{\eqn}[2]{ #2 \tag*{\mbox{\bf #1}} }
68 \newcommand{\corrolary}[1]{ #1 \tag*{\mbox{\it Corrolary.}} }
70 %\newcommand{\bigforall}{\mathop{\hbox{\huge$\forall$}}}
71 \newcommand{\bigforall}{%
73 {\hbox{\huge$\forall$}}%
74 {\hbox{\Large$\forall$}}%
75 {\hbox{\normalsize$\forall$}}%
76 {\hbox{\scriptsize$\forall$}}}%
79 \newcommand{\Largeexists}{\mathop{\hbox{\Large$\exists$}}}
80 \newcommand{\Largenexists}{\mathop{\hbox{\Large$\nexists$}}}
82 \newcommand{\qed}{\square}
83 \newcommand{\proof}[1]{{\it Proof.} #1 $\qed$}
85 \newcommand{\gathbegin}{\begin{gather} \tag*{}}
86 \newcommand{\gathnext}{\\ \tag*{}}
89 \newcommand{\false}{f}
97 \desclabelstyle{\nextlinelabel}
99 \item[ $ C \hasparents \set X $ ]
100 The parents of commit $C$ are exactly the set
104 $C$ is a descendant of $D$ in the git commit
105 graph. This is a partial order, namely the transitive closure of
106 $ D \in \set X $ where $ C \hasparents \set X $.
108 \item[ $ C \has D $ ]
109 Informally, the tree at commit $C$ contains the change
110 made in commit $D$. Does not take account of deliberate reversions by
111 the user or reversion, rebasing or rewinding in
112 non-Topbloke-controlled branches. For merges and Topbloke-generated
113 anticommits or re-commits, the ``change made'' is only to be thought
114 of as any conflict resolution. This is not a partial order because it
117 \item[ $ \p, \py, \pn $ ]
118 A patch $\p$ consists of two sets of commits $\pn$ and $\py$, which
119 are respectively the base and tip git branches. $\p$ may be used
120 where the context requires a set, in which case the statement
121 is to be taken as applying to both $\py$ and $\pn$.
122 All these sets are distinct. Hence:
124 \item[ $ \patchof{ C } $ ]
125 Either $\p$ s.t. $ C \in \p $, or $\bot$.
126 A function from commits to patches' sets $\p$.
128 \item[ $ \pancsof{C}{\set P} $ ]
129 $ \{ A \; | \; A \le C \land A \in \set P \} $
130 i.e. all the ancestors of $C$
131 which are in $\set P$.
133 \item[ $ \pendsof{C}{\set P} $ ]
134 $ \{ E \; | \; E \in \pancsof{C}{\set P}
135 \land \mathop{\not\exists}_{A \in \pancsof{C}{\set P}}
136 E \neq A \land E \le A \} $
137 i.e. all $\le$-maximal commits in $\pancsof{C}{\set P}$.
139 \item[ $ \baseof{C} $ ]
140 $ \pendsof{C}{\pn} = \{ \baseof{C} \} $ where $ C \in \py $.
141 A partial function from commits to commits.
142 See Unique Base, below.
144 \item[ $ C \haspatch \p $ ]
145 $\displaystyle \bigforall_{D \in \py} D \isin C \equiv D \le C $.
146 ~ Informally, $C$ has the contents of $\p$.
148 \item[ $ C \nothaspatch \p $ ]
149 $\displaystyle \bigforall_{D \in \py} D \not\isin C $.
150 ~ Informally, $C$ has none of the contents of $\p$.
152 Non-Topbloke commits are $\nothaspatch \p$ for all $\p$; if a Topbloke
153 patch is applied to a non-Topbloke branch and then bubbles back to
154 the Topbloke patch itself, we hope that git's merge algorithm will
155 DTRT or that the user will no longer care about the Topbloke patch.
157 \item[ $\displaystyle \merge{C}{L}{M}{R} $ ]
158 The contents of a git merge result:
160 $\displaystyle D \isin C \equiv
162 (D \isin L \land D \isin R) \lor D = C : & \true \\
163 (D \not\isin L \land D \not\isin R) \land D \neq C : & \false \\
164 \text{otherwise} : & D \not\isin M
172 We maintain these each time we construct a new commit. \\
174 C \has D \implies C \ge D
176 \[\eqn{Unique Base:}{
177 \bigforall_{C \in \py} \pendsof{C}{\pn} = \{ B \}
179 \[\eqn{Tip Contents:}{
180 \bigforall_{C \in \py} D \isin C \equiv
181 { D \isin \baseof{C} \lor \atop
182 (D \in \py \land D \le C) }
184 \[\eqn{Base Acyclic:}{
185 \bigforall_{B \in \pn} D \isin B \implies D \notin \py
188 \bigforall_{C,\p} C \haspatch \p \lor C \nothaspatch \p
190 \[\eqn{Foreign Inclusion:}{
191 \bigforall_{D \text{ s.t. } \patchof{D} = \bot} D \isin C \equiv D \leq C
194 \section{Some lemmas}
196 \[ \eqn{Exclusive Tip Contents:}{
197 \bigforall_{C \in \py}
198 \neg \Bigl[ D \isin \baseof{C} \land ( D \in \py \land D \le C )
201 Ie, the two limbs of the RHS of Tip Contents are mutually exclusive.
204 Let $B = \baseof{C}$ in $D \isin \baseof{C}$. Now $B \in \pn$.
205 So by Base Acyclic $D \isin B \implies D \notin \py$.
208 \bigforall_{C \in \py} D \isin C \equiv
210 D \in \py : & D \le C \\
211 D \not\in \py : & D \isin \baseof{C}
215 \[ \eqn{Tip Self Inpatch:}{
216 \bigforall_{C \in \py} C \haspatch \p
218 Ie, tip commits contain their own patch.
221 Apply Exclusive Tip Contents to some $D \in \py$:
222 $ \bigforall_{C \in \py}\bigforall_{D \in \py}
223 D \isin C \equiv D \le C $
226 \[ \eqn{Exact Ancestors:}{
227 \bigforall_{ C \hasparents \set{R} }
229 ( \mathop{\hbox{\huge{$\vee$}}}_{R \in \set R} D \le R )
233 \[ \eqn{Transitive Ancestors:}{
234 \left[ \bigforall_{ E \in \pendsof{C}{\set P} } E \le M \right] \equiv
235 \left[ \bigforall_{ A \in \pancsof{C}{\set P} } A \le M \right]
239 The implication from right to left is trivial because
240 $ \pends() \subset \pancs() $.
241 For the implication from left to right:
242 by the definition of $\mathcal E$,
243 for every such $A$, either $A \in \pends()$ which implies
244 $A \le M$ by the LHS directly,
245 or $\exists_{A' \in \pancs()} \; A' \neq A \land A \le A' $
246 in which case we repeat for $A'$. Since there are finitely many
247 commits, this terminates with $A'' \in \pends()$, ie $A'' \le M$
248 by the LHS. And $A \le A''$.
250 \[ \eqn{Calculation Of Ends:}{
251 \bigforall_{C \hasparents \set A}
252 \pendsof{C}{\set P} =
254 \Bigl[ \Largeexists_{A \in \set A}
255 E \in \pendsof{A}{\set P} \Bigr] \land
256 \Bigl[ \Largenexists_{B \in \set A}
257 E \neq B \land E \le B \Bigr]
262 \subsection{No Replay for Merge Results}
264 If we are constructing $C$, given
272 No Replay is preserved. {\it Proof:}
274 \subsubsection{For $D=C$:} $D \isin C, D \le C$. OK.
276 \subsubsection{For $D \isin L \land D \isin R$:}
277 $D \isin C$. And $D \isin L \implies D \le L \implies D \le C$. OK.
279 \subsubsection{For $D \neq C \land D \not\isin L \land D \not\isin R$:}
282 \subsubsection{For $D \neq C \land (D \isin L \equiv D \not\isin R)
283 \land D \not\isin M$:}
284 $D \isin C$. Also $D \isin L \lor D \isin R$ so $D \le L \lor D \le
287 \subsubsection{For $D \neq C \land (D \isin L \equiv D \not\isin R)
293 \section{Commit annotation}
295 We annotate each Topbloke commit $C$ with:
299 \baseof{C}, \text{ if } C \in \py
302 \text{ either } C \haspatch \pa{Q} \text{ or } C \nothaspatch \pa{Q}
304 \bigforall_{\pay{Q} \not\ni C} \pendsof{C}{\pay{Q}}
307 We do not annotate $\pendsof{C}{\py}$ for $C \in \py$. Doing so would
308 make it wrong to make plain commits with git because the recorded $\pends$
309 would have to be updated. The annotation is not needed because
310 $\forall_{\py \ni C} \; \pendsof{C}{\py} = \{C\}$.
312 \section{Simple commit}
314 A simple single-parent forward commit $C$ as made by git-commit.
316 \tag*{} C \hasparents \{ A \} \\
317 \tag*{} \patchof{C} = \patchof{A} \\
318 \tag*{} D \isin C \equiv D \isin A \lor D = C
321 \subsection{No Replay}
324 \subsection{Unique Base}
325 If $A, C \in \py$ then $\baseof{C} = \baseof{A}$. $\qed$
327 \subsection{Tip Contents}
328 We need to consider only $A, C \in \py$. From Tip Contents for $A$:
329 \[ D \isin A \equiv D \isin \baseof{A} \lor ( D \in \py \land D \le A ) \]
330 Substitute into the contents of $C$:
331 \[ D \isin C \equiv D \isin \baseof{A} \lor ( D \in \py \land D \le A )
333 Since $D = C \implies D \in \py$,
334 and substituting in $\baseof{C}$, this gives:
335 \[ D \isin C \equiv D \isin \baseof{C} \lor
336 (D \in \py \land D \le A) \lor
337 (D = C \land D \in \py) \]
338 \[ \equiv D \isin \baseof{C} \lor
339 [ D \in \py \land ( D \le A \lor D = C ) ] \]
340 So by Exact Ancestors:
341 \[ D \isin C \equiv D \isin \baseof{C} \lor ( D \in \py \land D \le C
345 \subsection{Base Acyclic}
347 Need to consider only $A, C \in \pn$.
349 For $D = C$: $D \in \pn$ so $D \not\in \py$. OK.
351 For $D \neq C$: $D \isin C \equiv D \isin A$, so by Base Acyclic for
352 $A$, $D \isin C \implies D \not\in \py$. $\qed$
354 \subsection{Coherence and patch inclusion}
356 Need to consider $D \in \py$
358 \subsubsection{For $A \haspatch P, D = C$:}
364 $ D \isin C \equiv \ldots \lor \true \text{ so } D \haspatch C $.
366 \subsubsection{For $A \haspatch P, D \neq C$:}
367 Ancestors: $ D \le C \equiv D \le A $.
369 Contents: $ D \isin C \equiv D \isin A \lor f $
370 so $ D \isin C \equiv D \isin A $.
373 \[ A \haspatch P \implies C \haspatch P \]
375 \subsubsection{For $A \nothaspatch P$:}
377 Firstly, $C \not\in \py$ since if it were, $A \in \py$.
380 Now by contents of $A$, $D \notin A$, so $D \notin C$.
383 \[ A \nothaspatch P \implies C \nothaspatch P \]
386 \subsection{Foreign inclusion:}
388 If $D = C$, trivial. For $D \neq C$:
389 $D \isin C \equiv D \isin A \equiv D \le A \equiv D \le C$. $\qed$
393 Given $L, R^+, R^-$ where
394 $R^+ \in \pry, R^- = \baseof{R^+}$.
395 Construct $C$ which has $\pr$ removed.
396 Used for removing a branch dependency.
398 C \hasparents \{ L \}
400 \patchof{C} = \patchof{L}
402 \merge{C}{L}{R^+}{R^-}
405 \subsection{Conditions}
407 \[ \eqn{ Unique Tip }{
408 \pendsof{L}{\pry} = \{ R^+ \}
410 \[ \eqn{ Currently Included }{
417 \subsection{No Replay}
419 By Unique Tip, $R^+ \le L$. By definition of $\base$, $R^- \le R^+$
420 so $R^- \le L$. So $R^+ \le C$ and $R^- \le C$ and No Replay for
421 Merge Results applies. $\qed$
423 \subsection{Desired Contents}
425 \[ $D \isin C \equiv [ D \not\in \pry \land D \isin L$ ] \lor D = C \]
428 \subsubsection{For $D = C$:}
430 Trivially $D \isin C$. OK.
432 \subsubsection{For $D \not\le C$:}
436 \subsubsection{For $D \in R^+$:}
437 By Currently Included,
439 \subsection{Unique Base}
441 Need to consider only $C \in \py$, ie $L \in \py$.
447 Merge commits $L$ and $R$ using merge base $M$ ($M < L, M < R$):
449 C \hasparents \{ L, R \}
451 \patchof{C} = \patchof{L}
456 \subsection{Conditions}
458 \[ \eqn{ Tip Merge }{
461 R \in \py : & \baseof{R} \ge \baseof{L}
462 \land [\baseof{L} = M \lor \baseof{L} = \baseof{M}] \\
463 R \in \pn : & R \ge \baseof{L}
464 \land M = \baseof{L} \\
465 \text{otherwise} : & \false
469 \subsection{No Replay}
471 See No Replay for Merge Results.
473 \subsection{Unique Base}
475 Need to consider only $C \in \py$, ie $L \in \py$,
476 and calculate $\pendsof{C}{\pn}$. So we will consider some
477 putative ancestor $A \in \pn$ and see whether $A \le C$.
479 By Exact Ancestors for C, $A \le C \equiv A \le L \lor A \le R \lor A = C$.
480 But $C \in py$ and $A \in \pn$ so $A \neq C$.
481 Thus $A \le C \equiv A \le L \lor A \le R$.
483 By Unique Base of L and Transitive Ancestors,
484 $A \le L \equiv A \le \baseof{L}$.
486 \subsubsection{For $R \in \py$:}
488 By Unique Base of $R$ and Transitive Ancestors,
489 $A \le R \equiv A \le \baseof{R}$.
491 But by Tip Merge condition on $\baseof{R}$,
492 $A \le \baseof{L} \implies A \le \baseof{R}$, so
493 $A \le \baseof{R} \lor A \le \baseof{L} \equiv A \le \baseof{R}$.
494 Thus $A \le C \equiv A \le \baseof{R}$.
495 That is, $\baseof{C} = \baseof{R}$.
497 \subsubsection{For $R \in \pn$:}
499 By Tip Merge condition on $R$,
500 $A \le \baseof{L} \implies A \le R$, so
501 $A \le R \lor A \le \baseof{L} \equiv A \le R$.
502 Thus $A \le C \equiv A \le R$.
503 That is, $\baseof{C} = R$.