@@ -30,7 +30,7 @@ import {
3030} from '../../../../git/parsers/logParser' ;
3131import type { GitGraphSearch , GitGraphSearchResultData , GitGraphSearchResults } from '../../../../git/search' ;
3232import { getSearchQueryComparisonKey , parseSearchQueryCommand } from '../../../../git/search' ;
33- import { getDefaultBranchName , isBranchStarred } from '../../../../git/utils/-webview/branch.utils' ;
33+ import { getBranchMergeBaseAndCommonCommit , isBranchStarred } from '../../../../git/utils/-webview/branch.utils' ;
3434import { getRemoteIconUri } from '../../../../git/utils/-webview/icons' ;
3535import { groupWorktreesByBranch } from '../../../../git/utils/-webview/worktree.utils' ;
3636import {
@@ -349,7 +349,10 @@ export class GraphGitSubProvider implements GitGraphSubProvider {
349349 branchId = branch ?. id ?? getBranchId ( repoPath , false , tip ) ;
350350
351351 // Check if branch has commits that can be recomposed and get merge base
352- const mergeBase = await this . getMergeBase ( branch , repoPath ) ;
352+ const mergeBaseResult =
353+ branch && ( await getBranchMergeBaseAndCommonCommit ( this . container , branch ) ) ;
354+ const isRecomposable = Boolean ( mergeBaseResult && mergeBaseResult . commit !== branch ?. sha ) ;
355+ const mergeBase = isRecomposable ? mergeBaseResult : undefined ;
353356
354357 context = {
355358 webviewItem : `gitlens:branch${ head ? '+current' : '' } ${
@@ -625,74 +628,6 @@ export class GraphGitSubProvider implements GitGraphSubProvider {
625628 return getCommitsForGraphCore . call ( this , defaultLimit , selectSha , undefined , cancellation ) ;
626629 }
627630
628- private async getMergeBase (
629- branch : GitBranch | undefined ,
630- repoPath : string ,
631- ) : Promise < { commit : string ; branch : string ; remote : boolean } | undefined > {
632- if ( ! branch || branch . remote ) return undefined ;
633-
634- try {
635- const upstreamName = branch . upstream ?. name ;
636- const svc = this . container . git . getRepositoryService ( repoPath ) ;
637-
638- // Get stored merge target configurations
639- const [ targetBranchResult , mergeBaseResult , defaultBranchResult ] = await Promise . allSettled ( [
640- svc . branches . getStoredMergeTargetBranchName ?.( branch . name ) ,
641- svc . branches . getBaseBranchName ?.( branch . name ) ,
642- getDefaultBranchName ( this . container , branch . repoPath , branch . name ) ,
643- ] ) ;
644- const targetBranch = getSettledValue ( targetBranchResult ) ;
645- const validTargetBranch = targetBranch && targetBranch !== upstreamName ? targetBranch : undefined ;
646- const mergeBase = getSettledValue ( mergeBaseResult ) || getSettledValue ( defaultBranchResult ) ;
647- const validMergeBase = mergeBase && mergeBase !== upstreamName ? mergeBase : undefined ;
648-
649- // Select target with most recent common commit (closest to branch tip)
650- const validTargets = [ validTargetBranch , validMergeBase ] ;
651- const recentMergeBase = await this . selectMostRecentMergeBase ( branch . name , validTargets , svc ) ;
652-
653- const isRecomposable = Boolean ( recentMergeBase && recentMergeBase . commit !== branch . sha ) ;
654- return isRecomposable ? recentMergeBase : undefined ;
655- } catch {
656- // If we can't determine, assume not recomposable
657- return undefined ;
658- }
659- }
660-
661- private async selectMostRecentMergeBase (
662- branchName : string ,
663- targets : ( string | undefined ) [ ] ,
664- svc : ReturnType < typeof this . container . git . getRepositoryService > ,
665- ) : Promise < { commit : string ; branch : string ; remote : boolean } | undefined > {
666- const isString = ( t : string | undefined ) : t is string => Boolean ( t ) ;
667- const mergeBaseResults = await Promise . allSettled (
668- targets . filter ( isString ) . map ( async target => {
669- const commit = await svc . refs . getMergeBase ( branchName , target ) ;
670- return {
671- commit : commit ,
672- branch : target ,
673- } ;
674- } ) ,
675- ) ;
676- const mergeBases = mergeBaseResults
677- . map ( result => getSettledValue ( result ) )
678- . filter ( ( r ) : r is { commit : string ; branch : string ; remote : boolean } => isString ( r ?. commit ) ) ;
679-
680- if ( mergeBases . length === 0 ) return undefined ;
681-
682- let mostRecentMergeBase = mergeBases [ 0 ] ;
683- for ( let i = 1 ; i < mergeBases . length ; i ++ ) {
684- const isCurrentMoreRecent = await svc . commits . isAncestorOf (
685- mostRecentMergeBase ?. commit ,
686- mergeBases [ i ] . commit ,
687- ) ;
688- if ( isCurrentMoreRecent ) {
689- mostRecentMergeBase = mergeBases [ i ] ;
690- }
691- }
692-
693- return mostRecentMergeBase ;
694- }
695-
696631 @log < GraphGitSubProvider [ 'searchGraph' ] > ( {
697632 args : {
698633 1 : s =>
0 commit comments