@@ -415,6 +415,310 @@ git commit -sm "fixup! release: add Mac OSX installer build" path/to/file
415415
416416## Rebasing Workflow
417417
418+ Rebases are the bread and butter of Git for Windows: topic branches are
419+ rebased every time upstream Git releases a new version. This section covers
420+ the workflow for managing downstream patches through repeated rebases.
421+
422+ ### Merging-Rebases
423+
424+ Git for Windows uses "merging-rebases" to maintain downstream patches. Unlike
425+ a flat series of commits, the downstream changes are organized as topic
426+ branches merged together, preserving the logical grouping of related changes.
427+
428+ Each integration branch (` main ` , ` shears/next ` , ` shears/seen ` ) contains a
429+ marker commit with the message "Start the merging-rebase to \< version\> ". This
430+ commit separates upstream history from downstream patches. Reference it with:
431+
432+ ``` bash
433+ # Find the marker commit
434+ git log --oneline --grep=" Start the merging-rebase" -1
435+
436+ # Reference it using commit message search syntax
437+ origin/main^{/Start.the.merging-rebase}
438+ ```
439+
440+ When working with merging-rebases:
441+
442+ - ** Downstream patches start after the marker** : Use
443+ ` origin/main^{/Start.the.merging-rebase}..origin/main ` to see all
444+ downstream commits
445+ - ** Topic branches are merged, not rebased flat** : Each logical feature or
446+ fix is a branch merged into the integration branch
447+ - ** Merge commits are preserved** : The rebase recreates the merge structure
448+ on top of the new upstream base
449+
450+ To compare downstream patches before and after a rebase:
451+
452+ ``` bash
453+ # Compare the old and new downstream patch series
454+ git range-diff \
455+ old-base^{/Start.the.merging-rebase}..old-branch \
456+ new-base^{/Start.the.merging-rebase}..new-branch
457+ ```
458+
459+ ### Starting a Merging-Rebase
460+
461+ To rebase the downstream patches onto a new upstream version, create a marker
462+ commit and use it as the base for an interactive rebase:
463+
464+ ``` bash
465+ # Variables for the commit message
466+ tag=v2.53.0
467+ # The previous marker - this becomes the exclusion point for --onto
468+ previousMergeOid=$( git rev-parse origin/main^{/Start.the.merging-rebase})
469+ tagOid=$( git rev-parse " $tag " )
470+ tipOid=$( git rev-parse origin/main)
471+
472+ # Create the marker commit with two parents: the tag and the current tip
473+ markerOid=$( git commit-tree " $tag ^{tree}" -p " $tag " -p " $tipOid " -m " Start the merging-rebase to $tag
474+
475+ This commit starts the rebase of $previousMergeOid to $tagOid " )
476+
477+ # Graft the marker to appear as if it has only the tag as parent
478+ git replace --graft " $markerOid " " $tag "
479+
480+ # Use the marker as the base for rebasing (only commits after previousMergeOid)
481+ git rebase -r --onto " $markerOid " " $previousMergeOid " origin/main
482+
483+ # After the rebase completes, delete the replace ref
484+ git replace -d " $markerOid "
485+ ```
486+
487+ The marker commit is created with two parents: the upstream tag and the
488+ current branch tip. The ` git replace --graft ` makes Git see only the tag as
489+ parent during the rebase, allowing the downstream commits to be cleanly
490+ rebased onto the new upstream. After the rebase completes, the replace ref
491+ is deleted to clean up.
492+
493+ #### The shears/* Branches
494+
495+ Upstream Git has four integration branches: ` seen ` , ` next ` , ` master ` , and
496+ ` maint ` . Git for Windows maintains a corresponding ` shears/* ` branch for each
497+ (` shears/seen ` , ` shears/next ` , ` shears/master ` , ` shears/maint ` ) that
498+ continuously rebases Git for Windows' ` main ` onto the respective upstream
499+ branch.
500+
501+ These branches are updated incrementally rather than from scratch, avoiding
502+ re-resolution of merge conflicts. The update process leverages reachability:
503+
504+ 1 . ** Integrate new downstream commits** : If ` origin/main ` has commits not yet
505+ in the shears branch, rebase them on top (using ` -r ` to preserve branch
506+ structure). Update the marker commit's message and second parent.
507+
508+ 2 . ** Integrate new upstream commits** : If the upstream branch has commits not
509+ yet integrated, rebase onto the new upstream tip. Update the marker commit
510+ accordingly.
511+
512+ The marker commit's second parent always points to the current ` origin/main `
513+ tip, making it trivial to identify what downstream commits are included.
514+ Similarly, the marker's first parent (the upstream base) shows exactly which
515+ upstream version is integrated.
516+
517+ ### When to Skip a Patch
518+
519+ Use ` git rebase --skip ` when the patch is already in the new base:
520+
521+ - ** Upstreamed** : The patch was accepted upstream and is now in ` seen `
522+ - ** Backported** : A fix we backported is now included in the upstream base
523+ - ** Superseded** : HEAD already contains evolved code that includes this
524+ change
525+
526+ Signs to skip rather than resolve: HEAD has the functionality, the
527+ conflict would discard the patch entirely, or ` git range-diff ` shows
528+ the downstream and upstream patches are equivalent.
529+
530+ To find the corresponding upstream commit for a conflicting patch:
531+
532+ ``` bash
533+ git range-diff --left-only REBASE_HEAD^! REBASE_HEAD..
534+ ```
535+
536+ ### Resolving Merge Conflicts
537+
538+ When resolving merge conflicts during a rebase (especially when squashing
539+ fixups), the goal is to ** apply the minimal surgical change** that the
540+ patch intended, not to reconstruct entire functions or add duplicate code.
541+
542+ #### 1. Understand What the Patch Wants
543+
544+ First, examine the patch being applied:
545+
546+ ``` bash
547+ git show REBASE_HEAD
548+ ```
549+
550+ Look at the actual changes (lines starting with ` - ` and ` + ` ):
551+ - What lines are being removed?
552+ - What lines are being added?
553+ - What is the context (function name, nearby code)?
554+
555+ ** Key insight** : The patch shows the * intent* ---a specific small change to
556+ make. Focus on this, not on the conflict markers' content.
557+
558+ ** Code movement detection** : If the patch shows large changes, check with
559+ ` --ignore-space-change ` :
560+
561+ ``` bash
562+ git show < conflicted-commit> --ignore-space-change
563+ ```
564+
565+ This reveals whether the commit is primarily ** moving code** (lots of
566+ whitespace changes) or making ** logic changes** (actual code modifications).
567+ When code was moved and re-indented, focus only on the non-whitespace
568+ changes when resolving the conflict.
569+
570+ #### 2. Understand Where the Code Is Now
571+
572+ The conflict occurred because the code moved or changed since the patch was
573+ created. Find where that code actually exists now:
574+
575+ ``` bash
576+ # If the patch was changing a specific pattern, find all occurrences
577+ git grep -n " pattern from patch"
578+
579+ # View the conflicted file around those locations
580+ ```
581+
582+ ** Common mistake** : Assuming the conflict markers show you what to do. They
583+ do not---they just show where Git got confused.
584+
585+ #### 3. Apply the Surgical Change
586+
587+ Make ** only** the change the patch intended, but in the current location:
588+
589+ - If the patch adds ` --abbrev=12 ` to a range-diff call, find where that
590+ range-diff call is NOW and add it there
591+ - If the patch changes a ` .split() ` pattern, find where that pattern is NOW
592+ and change it
593+ - Do not copy entire functions from the conflict markers
594+ - Do not create duplicates
595+
596+ #### 4. Remove ALL Conflict Markers
597+
598+ Conflict markers make the file invalid code:
599+ ```
600+ <<<<<<< HEAD
601+ =======
602+ >>>>>>> commit-hash
603+ ```
604+
605+ ** All three types of markers must be completely removed.**
606+
607+ #### 5. Verify the Resolution
608+
609+ ** Critical** : After staging your resolution, verify it matches the patch
610+ intent:
611+
612+ ``` bash
613+ # Compare your staged changes to the original patch
614+ git diff --cached
615+ git rebase --show-current-patch
616+
617+ # Or more directly, compare to REBASE_HEAD
618+ git diff --cached
619+ git show REBASE_HEAD
620+
621+ # For code that was moved/re-indented, ignore whitespace
622+ git diff --cached --ignore-space-change
623+ git show REBASE_HEAD --ignore-space-change
624+ ```
625+
626+ ** Verify, verify, verify** : The output of ` git diff --cached ` should
627+ correspond closely to the diff in ` git show REBASE_HEAD ` . The line numbers
628+ and context will differ (because code moved), but the actual changes (the
629+ ` - ` and ` + ` lines) should match the patch intent.
630+
631+ ** After completing a rebase** , always verify the final result:
632+
633+ ``` bash
634+ # Compare tree before and after rebase
635+ git diff @{1}
636+
637+ # Shows what changed in each rebased commit
638+ git range-diff @{1}...
639+ ```
640+
641+ If the rebase was onto the same base commit (e.g., squashing fixups), the
642+ ` git diff @{1} ` should be empty---this proves the rebase only reorganized
643+ commits without changing the end result. If the rebase was onto a new base
644+ commit (e.g., rebasing onto a new upstream release), the diff should match
645+ the difference between the old and new base commits, modulo any changes
646+ from upstreamed or backported patches. The ` git range-diff @{1}... ` shows
647+ the intended amendments (like adding ` --abbrev=12 ` ) were correctly applied
648+ to each commit.
649+
650+ ### Conflict Resolution Red Flags
651+
652+ These indicate you are doing it wrong:
653+
654+ - Your diff adds hundreds of lines when the patch only changed 3
655+ - Conflict markers remain in the file
656+ - Functions appear twice in the file
657+ - You added ` <<<<<<< HEAD ` or ` ======= ` to the staged changes
658+ - Syntax check fails after resolution
659+
660+ ### Key Conflict Resolution Lessons
661+
662+ 1 . ** Context changes, intent does not** - The patch's line numbers are
663+ wrong, but the change is right
664+ 2 . ** Conflict markers lie** - They show you where Git got confused, not
665+ what you should do
666+ 3 . ** One change at a time** - If the patch adds one line, your resolution
667+ should add one line
668+ 4 . ** Verify, verify, verify** - ` git diff --cached ` should match
669+ ` git show REBASE_HEAD ` (modulo context)
670+ 5 . ** Post-rebase verification** - ` git diff @{1} ` (empty) and
671+ ` git range-diff @{1}... ` (shows amendments)
672+ 6 . ** Ignore whitespace for code moves** - Use ` --ignore-space-change ` to
673+ see the actual logic changes when code was moved and re-indented
674+ 7 . ** When in doubt, look at the range-diff** - ` git range-diff ` shows if
675+ you matched the intent
676+
677+ ### Useful Rebase Tools
678+
679+ - ` git rebase --show-current-patch ` - See what change is being applied
680+ - ` git show REBASE_HEAD ` - Alternative to above, works better with
681+ ` --ignore-space-change `
682+ - ` git show <commit> --ignore-space-change ` - See only logic changes, not
683+ whitespace/indentation
684+ - ` git grep -n "pattern" ` - Find where code moved to
685+ - ` git log -L <start>,<end>:<file> REBASE_HEAD..HEAD ` - See how upstream
686+ modified a line range since the original patch; invaluable for
687+ understanding how conflicting lines changed
688+ - ` git diff --cached ` - After staging resolution, verify it matches
689+ REBASE_HEAD
690+ - ` git diff @{1} ` - After rebase, compare tree before/after
691+ - ` git range-diff @{1}... ` - After rebase, verify intended changes were made
692+ - ` git range-diff A^! B^! ` - Compare original patch to your resolution
693+
694+ ### Leveraging Rerere
695+
696+ Git's "reuse recorded resolution" (` rerere ` ) feature automatically records
697+ how you resolve conflicts and replays those resolutions when the same
698+ conflict recurs. This is invaluable for repeated rebases where the same
699+ downstream patches conflict with similar upstream changes.
700+
701+ When you see ` Staged 'file' using previous resolution ` , Git has applied a
702+ previously recorded resolution. Always verify these auto-resolutions are
703+ still correct---upstream context may have changed enough that the old
704+ resolution no longer applies cleanly.
705+
706+ To enable rerere:
707+ ``` bash
708+ git config --global rerere.enabled true
709+ ```
710+
711+ ### Automation Tips
712+
713+ When running rebases in automated or scripted contexts, disable the pager
714+ to avoid hangs:
715+
716+ ``` bash
717+ GIT_PAGER=cat git range-diff ...
718+ # or
719+ git --no-pager log ...
720+ ```
721+
418722### Fixup Commits
419723
420724Downstream patches sometimes require adjustment due to changes in the
0 commit comments