doc: remembering-renames.adoc: fix asciidoc warnings

Both asciidoc and ascidoctor issue warnings about 'list item index: expected n got n-1' for n=1->9 on lines 13, 15, 17, 20, 23, 25, 29, 31 and 33. In asciidoc, numbered lists must start at one, whereas this file has a list starting at zero. Also, asciidoc and asciidoctor warn about 'section title out of sequence: expected level 1, got level 2' on line 38. (asciidoc only complains about the first instance of this, while asciidoctor complains about them all, on lines 94, 141, 142, 184, 185, 257, 288, 289, 290, 397, 424, 485, 486 and 487). These warnings stem from the section titles not being correctly nested within a document/chapter title. In order to address the first set of warnings, simply renumber the list from one to nine, rather than zero to eight. This also requires altering the text which refers to the section numbers, including other section titles. In order to address the second set of warnings, change the section title syntax from '=== title ===' to '== title ==', effectively reducing the nesting level of the title by one. Also, some of the titles are given over multiple lines (they are very long), with an title '===' prefix on each line. This leads to them being treated as separate sections with no body text (as you can see from the line numbers given for the asciidoctor warnings, above). So, for these titles, turn them into a single (long) line of text. In addition to the warnings, address some other formatting issues: - the ascii branch diagrams didn't format correctly on asciidoctor so include them in a literal block. - several blocks of text were intended to be formatted 'as is' but were not included in a literal block. - in section 8, format the (A)->(D) in the text description as a literal with `` marks, since (C) is rendered as a copyright symbol in html otherwise. - in section 9, a sub-list of two items is not formatted as such. change the '*' introducer to '**' to correct the sub-list format. Signed-off-by: Ramsay Jones <ramsay@ramsayjones.plus.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Ramsay Jones committed Oct 16, 2025 at 21:02 UTC 4fa0e4d02cc624f2286b661d5c8c17a75515e66c
1 file changed +78 -42
Documentation/technical/remembering-renames.adoc
+78 -42
@@ -10,32 +10,32 @@ history as an optimization, assuming all merges are automatic and clean
10
11 Outline:
12
13 - 0. Assumptions
13 + 1. Assumptions
14
15 - 1. How rebasing and cherry-picking work
15 + 2. How rebasing and cherry-picking work
16
17 - 2. Why the renames on MERGE_SIDE1 in any given pick are *always* a
17 + 3. Why the renames on MERGE_SIDE1 in any given pick are *always* a
18 superset of the renames on MERGE_SIDE1 for the next pick.
19
20 - 3. Why any rename on MERGE_SIDE1 in any given pick is _almost_ always also
20 + 4. Why any rename on MERGE_SIDE1 in any given pick is _almost_ always also
21 a rename on MERGE_SIDE1 for the next pick
22
23 - 4. A detailed description of the counter-examples to #3.
23 + 5. A detailed description of the counter-examples to #4.
24
25 - 5. Why the special cases in #4 are still fully reasonable to use to pair
25 + 6. Why the special cases in #5 are still fully reasonable to use to pair
26 up files for three-way content merging in the merge machinery, and why
27 they do not affect the correctness of the merge.
28
29 - 6. Interaction with skipping of "irrelevant" renames
29 + 7. Interaction with skipping of "irrelevant" renames
30
31 - 7. Additional items that need to be cached
31 + 8. Additional items that need to be cached
32
33 - 8. How directory rename detection interacts with the above and why this
33 + 9. How directory rename detection interacts with the above and why this
34 optimization is still safe even if merge.directoryRenames is set to
35 "true".
36
37
38 -=== 0. Assumptions ===
38 +== 1. Assumptions ==
39
40 There are two assumptions that will hold throughout this document:
41
@@ -44,8 +44,8 @@ There are two assumptions that will hold throughout this document:
44
45 * All merges are fully automatic
46
47 -and a third that will hold in sections 2-5 for simplicity, that I'll later
48 -address in section 8:
47 +and a third that will hold in sections 3-6 for simplicity, that I'll later
48 +address in section 9:
49
50 * No directory renames occur
51
@@ -77,9 +77,9 @@ conflicts that the user needs to resolve), the cache of renames is not
77 stored on disk, and thus is thrown away as soon as the rebase or cherry
78 pick stops for the user to resolve the operation.
79
80 -The third assumption makes sections 2-5 simpler, and allows people to
80 +The third assumption makes sections 3-6 simpler, and allows people to
81 understand the basics of why this optimization is safe and effective, and
82 -then I can go back and address the specifics in section 8. It is probably
82 +then I can go back and address the specifics in section 9. It is probably
83 also worth noting that if directory renames do occur, then the default of
84 merge.directoryRenames being set to "conflict" means that the operation
85 will stop for users to resolve the conflicts and the cache will be thrown
@@ -88,22 +88,26 @@ reason we need to address directory renames specifically, is that some
88 users will have set merge.directoryRenames to "true" to allow the merges to
89 continue to proceed automatically. The optimization is still safe with
90 this config setting, but we have to discuss a few more cases to show why;
91 -this discussion is deferred until section 8.
91 +this discussion is deferred until section 9.
92
93
94 -=== 1. How rebasing and cherry-picking work ===
94 +== 2. How rebasing and cherry-picking work ==
95
96 Consider the following setup (from the git-rebase manpage):
97
98 +------------
99 A---B---C topic
100 /
101 D---E---F---G main
102 +------------
103
104 After rebasing or cherry-picking topic onto main, this will appear as:
105
106 +------------
107 A'--B'--C' topic
108 /
109 D---E---F---G main
110 +------------
111
112 The way the commits A', B', and C' are created is through a series of
113 merges, where rebase or cherry-pick sequentially uses each of the three
@@ -111,6 +115,7 @@ A-B-C commits in a special merge operation. Let's label the three commits
115 in the merge operation as MERGE_BASE, MERGE_SIDE1, and MERGE_SIDE2. For
116 this picture, the three commits for each of the three merges would be:
117
118 +....
119 To create A':
120 MERGE_BASE: E
121 MERGE_SIDE1: G
@@ -125,6 +130,7 @@ To create C':
130 MERGE_BASE: B
131 MERGE_SIDE1: B'
132 MERGE_SIDE2: C
133 +....
134
135 Sometimes, folks are surprised that these three-way merges are done. It
136 can be useful in understanding these three-way merges to view them in a
@@ -138,8 +144,7 @@ Conceptually the two statements above are the same as a three-way merge of
144 B, B', and C, at least the parts before you decide to record a commit.
145
146
141 -=== 2. Why the renames on MERGE_SIDE1 in any given pick are always a ===
142 -=== superset of the renames on MERGE_SIDE1 for the next pick. ===
147 +== 3. Why the renames on MERGE_SIDE1 in any given pick are always a superset of the renames on MERGE_SIDE1 for the next pick. ==
148
149 The merge machinery uses the filenames it is fed from MERGE_BASE,
150 MERGE_SIDE1, and MERGE_SIDE2. It will only move content to a different
@@ -156,6 +161,7 @@ filename under one of three conditions:
161 First, let's remember what commits are involved in the first and second
162 picks of the cherry-pick or rebase sequence:
163
164 +....
165 To create A':
166 MERGE_BASE: E
167 MERGE_SIDE1: G
@@ -165,6 +171,7 @@ To create B':
171 MERGE_BASE: A
172 MERGE_SIDE1: A'
173 MERGE_SIDE2: B
174 +....
175
176 So, in particular, we need to show that the renames between E and G are a
177 superset of those between A and A'.
@@ -181,11 +188,11 @@ are a subset of those between E and G. Equivalently, all renames between E
188 and G are a superset of those between A and A'.
189
190
184 -=== 3. Why any rename on MERGE_SIDE1 in any given pick is _almost_ ===
185 -=== always also a rename on MERGE_SIDE1 for the next pick. ===
191 +== 4. Why any rename on MERGE_SIDE1 in any given pick is _almost_ always also a rename on MERGE_SIDE1 for the next pick. ==
192
193 Let's again look at the first two picks:
194
195 +....
196 To create A':
197 MERGE_BASE: E
198 MERGE_SIDE1: G
@@ -195,17 +202,25 @@ To create B':
202 MERGE_BASE: A
203 MERGE_SIDE1: A'
204 MERGE_SIDE2: B
205 +....
206
207 Now let's look at any given rename from MERGE_SIDE1 of the first pick, i.e.
208 any given rename from E to G. Let's use the filenames 'oldfile' and
209 'newfile' for demonstration purposes. That first pick will function as
210 follows; when the rename is detected, the merge machinery will do a
211 three-way content merge of the following:
212 +
213 +....
214 E:oldfile
215 G:newfile
216 A:oldfile
217 +....
218 +
219 and produce a new result:
220 +
221 +....
222 A':newfile
223 +....
224
225 Note above that I've assumed that E->A did not rename oldfile. If that
226 side did rename, then we most likely have a rename/rename(1to2) conflict
@@ -254,19 +269,21 @@ were detected as renames, A:oldfile and A':newfile should also be
269 detectable as renames almost always.
270
271
257 -=== 4. A detailed description of the counter-examples to #3. ===
272 +== 5. A detailed description of the counter-examples to #4. ==
273
259 -We already noted in section 3 that rename/rename(1to1) (i.e. both sides
274 +We already noted in section 4 that rename/rename(1to1) (i.e. both sides
275 renaming a file the same way) was one counter-example. The more
276 interesting bit, though, is why did we need to use the "almost" qualifier
277 when stating that A:oldfile and A':newfile are "almost" always detectable
278 as renames?
279
265 -Let's repeat an earlier point that section 3 made:
280 +Let's repeat an earlier point that section 4 made:
281
282 +....
283 A':newfile was created by applying the changes between E:oldfile and
284 G:newfile to A:oldfile. The changes between E:oldfile and G:newfile were
285 <50% of the size of E:oldfile.
286 +....
287
288 If those changes that were <50% of the size of E:oldfile are also <50% of
289 the size of A:oldfile, then A:oldfile and A':newfile will be detectable as
@@ -276,18 +293,21 @@ still somehow merge cleanly), then traditional rename detection would not
293 detect A:oldfile and A':newfile as renames.
294
295 Here's an example where that can happen:
296 +
297 * E:oldfile had 20 lines
298 * G:newfile added 10 new lines at the beginning of the file
299 * A:oldfile kept the first 3 lines of the file, and deleted all the rest
300 +
301 then
302 +
303 +....
304 => A':newfile would have 13 lines, 3 of which matches those in A:oldfile.
284 -E:oldfile -> G:newfile would be detected as a rename, but A:oldfile and
285 -A':newfile would not be.
305 + E:oldfile -> G:newfile would be detected as a rename, but A:oldfile and
306 + A':newfile would not be.
307 +....
308
309
288 -=== 5. Why the special cases in #4 are still fully reasonable to use to ===
289 -=== pair up files for three-way content merging in the merge machinery, ===
290 -=== and why they do not affect the correctness of the merge. ===
310 +== 6. Why the special cases in #5 are still fully reasonable to use to pair up files for three-way content merging in the merge machinery, and why they do not affect the correctness of the merge. ==
311
312 In the rename/rename(1to1) case, A:newfile and A':newfile are not renames
313 since they use the *same* filename. However, files with the same filename
@@ -295,14 +315,14 @@ are obviously fine to pair up for three-way content merging (the merge
315 machinery has never employed break detection). The interesting
316 counter-example case is thus not the rename/rename(1to1) case, but the case
317 where A did not rename oldfile. That was the case that we spent most of
298 -the time discussing in sections 3 and 4. The remainder of this section
318 +the time discussing in sections 4 and 5. The remainder of this section
319 will be devoted to that case as well.
320
321 So, even if A:oldfile and A':newfile aren't detectable as renames, why is
322 it still reasonable to pair them up for three-way content merging in the
323 merge machinery? There are multiple reasons:
324
305 - * As noted in sections 3 and 4, the diff between A:oldfile and A':newfile
325 + * As noted in sections 4 and 5, the diff between A:oldfile and A':newfile
326 is *exactly* the same as the diff between E:oldfile and G:newfile. The
327 latter pair were detected as renames, so it seems unlikely to surprise
328 users for us to treat A:oldfile and A':newfile as renames.
@@ -394,7 +414,7 @@ cases 1 and 3 seem to provide as good or better behavior with the
414 optimization than without.
415
416
397 -=== 6. Interaction with skipping of "irrelevant" renames ===
417 +== 7. Interaction with skipping of "irrelevant" renames ==
418
419 Previous optimizations involved skipping rename detection for paths
420 considered to be "irrelevant". See for example the following commits:
@@ -421,24 +441,27 @@ detection -- though we can limit it to the paths for which we have not
441 already detected renames.
442
443
424 -=== 7. Additional items that need to be cached ===
444 +== 8. Additional items that need to be cached ==
445
446 It turns out we have to cache more than just renames; we also cache:
447
448 +....
449 A) non-renames (i.e. unpaired deletes)
450 B) counts of renames within directories
451 C) sources that were marked as RELEVANT_LOCATION, but which were
452 downgraded to RELEVANT_NO_MORE
453 D) the toplevel trees involved in the merge
454 +....
455
456 These are all stored in struct rename_info, and respectively appear in
457 +
458 * cached_pairs (along side actual renames, just with a value of NULL)
459 * dir_rename_counts
460 * cached_irrelevant
461 * merge_trees
462
440 -The reason for (A) comes from the irrelevant renames skipping
441 -optimization discussed in section 6. The fact that irrelevant renames
463 +The reason for `(A)` comes from the irrelevant renames skipping
464 +optimization discussed in section 7. The fact that irrelevant renames
465 are skipped means we only get a subset of the potential renames
466 detected and subsequent commits may need to run rename detection on
467 the upstream side on a subset of the remaining renames (to get the
@@ -447,23 +470,24 @@ deletes are involved in rename detection too, we don't want to
470 repeatedly check that those paths remain unpaired on the upstream side
471 with every commit we are transplanting.
472
450 -The reason for (B) is that diffcore_rename_extended() is what
473 +The reason for `(B)` is that diffcore_rename_extended() is what
474 generates the counts of renames by directory which is needed in
475 directory rename detection, and if we don't run
476 diffcore_rename_extended() again then we need to have the output from
477 it, including dir_rename_counts, from the previous run.
478
456 -The reason for (C) is that merge-ort's tree traversal will again think
479 +The reason for `(C)` is that merge-ort's tree traversal will again think
480 those paths are relevant (marking them as RELEVANT_LOCATION), but the
481 fact that they were downgraded to RELEVANT_NO_MORE means that
482 dir_rename_counts already has the information we need for directory
483 rename detection. (A path which becomes RELEVANT_CONTENT in a
484 subsequent commit will be removed from cached_irrelevant.)
485
463 -The reason for (D) is that is how we determine whether the remember
486 +The reason for `(D)` is that is how we determine whether the remember
487 renames optimization can be used. In particular, remembering that our
488 sequence of merges looks like:
489
490 +....
491 Merge 1:
492 MERGE_BASE: E
493 MERGE_SIDE1: G
@@ -475,6 +499,7 @@ sequence of merges looks like:
499 MERGE_SIDE1: A'
500 MERGE_SIDE2: B
501 => Creates B'
502 +....
503
504 It is the fact that the trees A and A' appear both in Merge 1 and in
505 Merge 2, with A as a parent of A' that allows this optimization. So
@@ -482,12 +507,11 @@ we store the trees to compare with what we are asked to merge next
507 time.
508
509
485 -=== 8. How directory rename detection interacts with the above and ===
486 -=== why this optimization is still safe even if ===
487 -=== merge.directoryRenames is set to "true". ===
510 +== 9. How directory rename detection interacts with the above and why this optimization is still safe even if merge.directoryRenames is set to "true". ==
511
512 As noted in the assumptions section:
513
514 +....
515 """
516 ...if directory renames do occur, then the default of
517 merge.directoryRenames being set to "conflict" means that the operation
@@ -497,11 +521,13 @@ As noted in the assumptions section:
521 is that some users will have set merge.directoryRenames to "true" to
522 allow the merges to continue to proceed automatically.
523 """
524 +....
525
526 Let's remember that we need to look at how any given pick affects the next
527 one. So let's again use the first two picks from the diagram in section
528 one:
529
530 +....
531 First pick does this three-way merge:
532 MERGE_BASE: E
533 MERGE_SIDE1: G
@@ -513,6 +539,7 @@ one:
539 MERGE_SIDE1: A'
540 MERGE_SIDE2: B
541 => creates B'
542 +....
543
544 Now, directory rename detection exists so that if one side of history
545 renames a directory, and the other side adds a new file to the old
@@ -545,7 +572,7 @@ while considering all of these cases:
572 concerned; see the assumptions section). Two interesting sub-notes
573 about these counts:
574
548 - * If we need to perform rename-detection again on the given side (e.g.
575 + ** If we need to perform rename-detection again on the given side (e.g.
576 some paths are relevant for rename detection that weren't before),
577 then we clear dir_rename_counts and recompute it, making use of
578 cached_pairs. The reason it is important to do this is optimizations
@@ -556,7 +583,7 @@ while considering all of these cases:
583 easiest way to "fix up" dir_rename_counts in such cases is to just
584 recompute it.
585
559 - * If we prune rename/rename(1to1) entries from the cache, then we also
586 + ** If we prune rename/rename(1to1) entries from the cache, then we also
587 need to update dir_rename_counts to decrement the counts for the
588 involved directory and any relevant parent directories (to undo what
589 update_dir_rename_counts() in diffcore-rename.c incremented when the
@@ -578,6 +605,7 @@ in order:
605
606 Case 1: MERGE_SIDE1 renames old dir, MERGE_SIDE2 adds new file to old dir
607
608 +....
609 This case looks like this:
610
611 MERGE_BASE: E, Has olddir/
@@ -595,10 +623,13 @@ Case 1: MERGE_SIDE1 renames old dir, MERGE_SIDE2 adds new file to old dir
623 * MERGE_SIDE1 has cached olddir/newfile -> newdir/newfile
624 Given the cached rename noted above, the second merge can proceed as
625 expected without needing to perform rename detection from A -> A'.
626 +....
627
628 Case 2: MERGE_SIDE1 renames old dir, MERGE_SIDE2 renames file into old dir
629
630 +....
631 This case looks like this:
632 +
633 MERGE_BASE: E oldfile, olddir/
634 MERGE_SIDE1: G oldfile, olddir/ -> newdir/
635 MERGE_SIDE2: A oldfile -> olddir/newfile
@@ -617,9 +648,11 @@ Case 2: MERGE_SIDE1 renames old dir, MERGE_SIDE2 renames file into old dir
648
649 Given the cached rename noted above, the second merge can proceed as
650 expected without needing to perform rename detection from A -> A'.
651 +....
652
653 Case 3: MERGE_SIDE1 adds new file to old dir, MERGE_SIDE2 renames old dir
654
655 +....
656 This case looks like this:
657
658 MERGE_BASE: E, Has olddir/
@@ -635,9 +668,11 @@ Case 3: MERGE_SIDE1 adds new file to old dir, MERGE_SIDE2 renames old dir
668 In this case, with the optimization, note that after the first commit there
669 were no renames on MERGE_SIDE1, and any renames on MERGE_SIDE2 are tossed.
670 But the second merge didn't need any renames so this is fine.
671 +....
672
673 Case 4: MERGE_SIDE1 renames file into old dir, MERGE_SIDE2 renames old dir
674
675 +....
676 This case looks like this:
677
678 MERGE_BASE: E, Has olddir/
@@ -658,6 +693,7 @@ Case 4: MERGE_SIDE1 renames file into old dir, MERGE_SIDE2 renames old dir
693
694 Given the cached rename noted above, the second merge can proceed as
695 expected without needing to perform rename detection from A -> A'.
696 +....
697
698 Finally, I'll just note here that interactions with the
699 skip-irrelevant-renames optimization means we sometimes don't detect