@@ -504,74 +504,94 @@ export class ComposerWebviewProvider implements WebviewProvider<State, State, Co
504504 } ;
505505 }
506506
507- // Get the merge target for the branch
508- const baseBranchNameResult = await getBranchMergeTargetName ( this . container , branch ) ;
507+ // Get the merge target for the branch with recursive resolution
509508 let mergeTargetName : string | undefined ;
510- if ( ! baseBranchNameResult . paused ) {
511- mergeTargetName = baseBranchNameResult . value ;
512- }
509+ let currentMergeTargetBranchName = branchName ;
510+ let currentMergeTargetBranch = branch ;
511+ const visitedBranches = new Set < string > ( ) ;
512+ let attempts = 0 ;
513+ const maxAttempts = 10 ;
513514
514- if ( ! mergeTargetName ) {
515- return {
516- ...this . initialState ,
517- loadingError : `Unable to determine merge target for branch '${ branchName } '.` ,
518- } ;
519- }
515+ while ( attempts < maxAttempts ) {
516+ attempts ++ ;
520517
521- // Get branch commits
522- const branchData = await getBranchCommits ( this . container , repo , branchName , mergeTargetName ) ;
523- if ( ! branchData ) {
524- return {
525- ...this . initialState ,
526- loadingError : `No commits found for branch '${ branchName } ' or unable to determine branch base.` ,
527- } ;
528- }
518+ // Prevent infinite loops by tracking visited branches
519+ if ( visitedBranches . has ( currentMergeTargetBranchName ) ) {
520+ break ;
521+ }
522+ visitedBranches . add ( currentMergeTargetBranchName ) ;
523+
524+ const mergeTargetNameResult = await getBranchMergeTargetName ( this . container , currentMergeTargetBranch ) ;
525+ if ( ! mergeTargetNameResult . paused && mergeTargetNameResult . value ) {
526+ mergeTargetName = mergeTargetNameResult . value ;
527+
528+ // Get branch commits to check if we have unique commits
529+ const branchData = await getBranchCommits ( this . container , repo , branchName , mergeTargetName ) ;
530+ if ( branchData && branchData . commits . length > 0 ) {
531+ // Found unique commits, use this merge target
532+ const { commits : branchCommits , baseCommit, headCommitSha } = branchData ;
533+
534+ // Create composer commits and hunks from branch commits
535+ const composerData = await createComposerCommitsFromGitCommits ( repo , branchCommits ) ;
536+ if ( ! composerData ) {
537+ return {
538+ ...this . initialState ,
539+ loadingError : `Failed to process commits for branch '${ branchName } '.` ,
540+ } ;
541+ }
529542
530- const { commits : branchCommits , baseCommit, headCommitSha } = branchData ;
543+ const { commits, hunks } = composerData ;
544+ const diffs = ( await getComposerDiffs ( repo , { baseSha : baseCommit . sha , headSha : headCommitSha } ) ) ! ;
531545
532- // Check if branch has no commits
533- if ( branchCommits . length === 0 ) {
534- return {
535- ...this . initialState ,
536- loadingError : `Branch '${ branchName } ' has no unique commits.` ,
537- } ;
538- }
546+ // Return successful state with found commits
547+ return this . initializeStateAndContext (
548+ repo ,
549+ hunks ,
550+ commits ,
551+ diffs ,
552+ {
553+ sha : baseCommit . sha ,
554+ message : baseCommit . message ,
555+ repoName : repo . name ,
556+ branchName : branchName ,
557+ } ,
558+ headCommitSha ,
559+ currentMergeTargetBranchName ,
560+ mode ,
561+ source ,
562+ isReload ,
563+ ) ;
564+ }
539565
540- // Create composer commits and hunks from branch commits
541- const composerData = await createComposerCommitsFromGitCommits ( repo , branchCommits ) ;
542- if ( ! composerData ) {
543- return {
544- ...this . initialState ,
545- loadingError : `Failed to process commits for branch '${ branchName } '.` ,
546- } ;
547- }
566+ // No unique commits found, try to resolve the merge target recursively
567+ // Get the branch that the current merge target points to
568+ const targetBranch = await repo . git . branches . getBranch ( mergeTargetName ) ;
569+ if ( ! targetBranch ) {
570+ // Can't find the target branch, stop here
571+ break ;
572+ }
548573
549- const { commits, hunks } = composerData ;
550- const diffs = ( await getComposerDiffs ( repo , { baseSha : baseCommit . sha , headSha : headCommitSha } ) ) ! ;
574+ // Check if the target branch name is the same as current branch (circular reference)
575+ if ( targetBranch . name === currentMergeTargetBranchName ) {
576+ break ;
577+ }
551578
552- // Set up telemetry context
553- this . _context . diff . staged = false ;
554- this . _context . diff . unstaged = false ;
555- this . _context . diff . unstagedIncluded = false ;
556- this . _context . diff . commits = true ;
579+ // Move to the target branch and try again
580+ currentMergeTargetBranchName = targetBranch . name ;
581+ currentMergeTargetBranch = targetBranch ;
582+ } else {
583+ // No merge target found or paused, stop here
584+ break ;
585+ }
586+ }
557587
558- return this . initializeStateAndContext (
559- repo ,
560- hunks ,
561- commits ,
562- diffs ,
563- {
564- sha : baseCommit . sha ,
565- message : baseCommit . message ,
566- repoName : repo . name ,
567- branchName : branchName ,
568- } ,
569- headCommitSha ,
570- branchName ,
571- mode ,
572- source ,
573- isReload ,
574- ) ;
588+ // If we get here, we couldn't find unique commits after trying all merge targets or reaching max attempts
589+ return {
590+ ...this . initialState ,
591+ loadingError : mergeTargetName
592+ ? `Branch '${ branchName } ' has no unique commits against any resolved merge target.`
593+ : `Unable to determine merge target for branch '${ branchName } '.` ,
594+ } ;
575595 }
576596
577597 private getRepositoryState ( ) {
0 commit comments