Skip to content

PR merge order: recommended sequence to minimize rebase churn #441

Description

@toddr-bot

Context

With 111 open PRs (100 from toddr-bot, 11 community), we need a merge strategy that maximizes value while minimizing rebase churn. This issue provides a recommended merge order based on file-level conflict analysis and CI status.

Methodology: Each PR was scored by how many other open PRs touch the same non-test source files. Lower score = fewer conflicts after merging. CI status was verified for all PRs.

See also: #440 (duplicate PR triage)


Phase 1: Zero-Conflict, Test-Only PRs (merge immediately)

These PRs touch only test files or auxiliary files. Zero source-file conflicts with any other PR. All CI-passing.

PR Title Conflicts CI
#365 regression tests for CHECK bareword handle (GH #246) 0
#398 regression tests for issue #133 (wordlike operator after method call) 0
#427 regression tests for ternary label false positives 0
#355 exclude Ham-DXCC-Lookup from dependent modules test 1
#356 exclude Dist-Zilla-Plugin-Subversion from dependents testing 1

Value: 5 merges with zero rebase risk to any other PR.


Phase 2: Duplicate Resolution (close losers per #440)

Before merging anything else, close the weaker half of each duplicate cluster. Recommended winners:

Keep Close Cluster Rationale
#391 #390 PPI::Exception caller tracking #391 has comprehensive tests; #390 is a subset
#363 #333 UTF-8 decode on use utf8 Identical fix; #333 is CI-failing anyway
#393 #362, #386 Minimum Perl version / IO::String #393 (5.008001 Lancaster) supersedes #362 (5.008); #386 is a subset
#414 #399, #376 Element->namespace / Package block #414 is the most complete implementation
#404 #353 DESTROY cleanup #404 is more targeted; #353 touches more files (14 conflicts)
#388 #307 Whitespace between sigil and identifier #388 is bot-generated against current master, cleaner diff
#438 or #434 the other Encoding for Document->new Human decision needed — #438 (simpler API, CI-failing) vs #434 (richer API, CI-passing). Recommend #434

Closing 9+ PRs reduces the open count and eliminates future conflict sources.


Phase 3: Low-Conflict Bug Fixes (1-5 conflict score, CI-passing)

Merge in this order (ascending conflict score):

Order PR Title Score Files
1 #377 __DATA__ no longer causes incomplete documents 2 4
2 #359 verify BEGIN/UNITCHECK/CHECK/INIT/END behaviour 3 5
3 #391 PPI::Exception unit tests + fix throw() caller tracking 3 2
4 #429 minus operator no longer splits namespaced words 3 2
5 #368 document 'continue' type in Statement::Compound 4 2
6 #375 close double diamond (<<>>) operator 4 3
7 #401 parse qw with comment before first delimiter 4 2
8 #383 recognize %/ as magic variable 5 5
9 #404 stop Node::DESTROY from corrupting still-referenced children 5 2
10 #418 allow passing a string reference to PPI::Dumper->new 5 2
11 #421 declare Perl::Critic < 1.122 as incompatible via x_breaks 5 2
12 #385 normalize file permissions to prevent executable metadata files 5 2

Value: 12 targeted fixes with minimal rebase ripple.


Phase 4: Medium-Conflict Bug Fixes (5-15 conflict score, CI-passing)

These touch core files but are focused enough to merge cleanly in sequence.

4A: Tokenizer operator/parsing fixes (group — share Tokenizer.pm and Whitespace.pm)

Order PR Title Score
1 #387 dot after value-producing token is concat, not float 7
2 #378 treat << as bit shift after numeric tokens 7
3 #380 track repeated regex modifiers like s///ee 7
4 #339 treat // as regexp match after Perl builtins 15
5 #426 recognize regex after map/grep block (RT #75921) 15
6 #431 minus after ) and ] parsed as negative number 20
7 #433 parse hashref after any operator as Constructor (GH #34) 21
8 #366 scan for fat comma in list-embedded curlies (GH #236) 21

4B: Symbol/Magic variable fixes

Order PR Title Score
1 #384 treat @_{} and $_{} as Symbol, not Magic 9
2 #389 stop treating `$:: ` as a magic variable
3 #408 remove code duplication in Token::Magic 9
4 #428 parse $$$a as chained dereferences 10

4C: Statement/Structure fixes

Order PR Title Score
1 #407 implement module_first_arg for Statement::Include 7
2 #370 detect Statement::Variable in open() without parens 21
3 #435 stop Statement::Variable from consuming sibling args in list context 21
4 #436 remove dead guards for Structure without start brace 10
5 #413 allow programmatic creation of PPI::Structure subclasses 6
6 #430 remove inverted condition in Lexer::_add_element label detection 21

4D: Feature tracking / Lexer scoping

Order PR Title Score
1 #335 handle whitespace tokens in feature argument decomposition 7
2 #351 fix feature scoping leak when leaving blocks 21
3 #361 recognize try feature from use experimental 'try' 7

4E: Quote/QuoteLike API consistency

Order PR Title Score
1 #364 add get_delimiters() for qw, qx, q, qq 10
2 #411 make methods on Quote subclasses consistent 7
3 #406 add QuoteLike->string (like Quote has) 10

4F: Misc standalone fixes

PR Title Score
#332 add dotted bitwise operators to Operator.pm POD (CI-FAILING — needs fix) 7
#352 support isa infix operator from Perl 5.32 10
#374 default $word parameter in __current_token_is_forced_word 20
#371 all_tokens() exception message nesting 20
#358 reject all non-string refs in scalar ref input 20
#394 remove unused PPI::Exception::ParserRejection 20
#425 handle NUL and vertical tab characters in source 17
#382 parse [subscript] after ${deref} as Subscript 21
#372 detect readline with variable filehandle after block 15

Phase 5: Feature Additions (higher review burden)

These add new API surface or significant behavior changes. Merge after bugs are clear.

PR Title Score Notes
#424 add Word classification methods from PPIx::Utils 8 High value — internalizes PPIx::Utils methods
#336 add signature() method to Statement::Sub 8 Clean API addition
#409 parse string interpolations via interpolated_fragments() 10 Large (494 additions), new API
#417 parse anonymous subs as PPI::Statement::Sub 22 Significant Lexer change
#346 support Corinna keywords (class, method, field, ADJUST) 29 Large, touches Lexer + Token::Word
#352 support isa infix operator from Perl 5.32 10 New operator type
#432 parse ellipsis ... as PPI::Token::Ellipsis 35 New token class, 9 files
#412 implement perl -x emulation via perl_x option 52 7 files, new Document option
#434 encoding-aware constructor APIs 17 Depends on duplicate resolution with #438
#396 implement PPI::Document::Strict 13 New subclass

Phase 6: Documentation PRs

Low risk but touch overlapping doc areas. Merge after code PRs stabilize.

PR Title Score
#400 document why PPI accepts incomplete documents 13
#397 document best-effort parsing of broken code 17
#367 clarify insert_before/insert_after docs for single element 13
#419 cross-link insert method rules and clarify PDOM explanation 26
#379 document filename param for PPI::Document->new 17

Phase 7: Defer or Needs Discussion

Competing designs (pick one per cluster)

CI-Failing (need fixes before merge)

PR Title Issue
#332 dotted bitwise operators POD CI fail
#333 UTF-8 decode (duplicate of #363) CI fail — just close
#348 reparse section metadata after set_content CI fail
#402 parse qw with backslash delimiters CI fail
#403 add modifier_type() and modifier() CI fail
#405 whitespace-only line token concatenation CI fail
#420 auto-invalidate location cache after mutations CI fail
#438 add encoding parameter to Document->new CI fail

Community PRs (old, no CI, need fresh evaluation)

PR Title Author Recommendation
#49 cmp_document branch moregan Close — subsumed by #146
#79 Fix insert_{after,before} hartzell Evaluate against #392
#146 Cmp document functions moregan Large (71 conflicts), evaluate independently
#151 Allow statements in insert operations karenetheridge Large (56 conflicts), evaluate against #392
#172 Cache directory permissions zhurs Small fix buried in large diff (71 conflicts)
#182 actual filename attribute van-de-bugger Conflicts with #379
#186 byte offsets for Tokens ksurent Conflicts with #415 (character offsets)
#190 multi-line subroutine attribute params edenhochbaum Needs rebase (31 conflicts)
#250 parse format as single token ? 20 conflicts, old
#306 tidy everything wchristian 101 conflicts — do NOT merge until all else is done
#307 variables with spaces after sigil wchristian Duplicate of #388 — close
#357 factor out feature set stack mauke 21 conflicts, related to #351

Cross-cutting mega-PRs (merge LAST if at all)

PR Title Score Files Changed
#395 add use warnings to all library modules 102 98
#338 use dzil Pod::Weaver for POD 101 92
#306 tidy everything 101 large

These three PRs conflict with virtually every other PR. Merge them dead last, after all targeted PRs are in. Even then, they'll need complete rebases. Consider if #395 (use warnings) can be done incrementally per-module instead.


Summary: Recommended Merge Sequence

1. Close 9+ duplicates (Phase 2)                    → reduces PR count to ~100
2. Merge 5 zero-conflict test-only PRs (Phase 1)    → 5 merges, 0 rebases needed
3. Merge 12 low-conflict bug fixes (Phase 3)         → 12 merges, minimal rebases
4. Merge medium-conflict fixes by group (Phase 4)    → ~30 merges, group-wise rebases
5. Merge features after design review (Phase 5)      → ~10 merges
6. Merge docs (Phase 6)                              → ~5 merges
7. Evaluate community PRs (Phase 7)                  → close or rebase as needed
8. Cross-cutting changes last (Phase 7)              → #395, #338, #306

Estimated merge-to-rebase ratio: By following this order, roughly 50 PRs can merge before any significant rebase is required. The remaining PRs will each need at most 1 rebase, not cascading rebases.


🤖 Generated by Kōan from merge order analysis session

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions