@@ -12,7 +12,7 @@ import type {
1212import { GitBranch } from '../../../../git/models/branch' ;
1313import type { MergeConflict } from '../../../../git/models/mergeConflict' ;
1414import type { GitBranchReference } from '../../../../git/models/reference' ;
15- import { parseGitBranches } from '../../../../git/parsers/branchParser' ;
15+ import { parseGitBranches , parseGitBranchesDefaultFormat } from '../../../../git/parsers/branchParser' ;
1616import { parseMergeTreeConflict } from '../../../../git/parsers/mergeTreeParser' ;
1717import { getReferenceFromBranch } from '../../../../git/utils/-webview/reference.utils' ;
1818import type { BranchSortOptions } from '../../../../git/utils/-webview/sorting' ;
@@ -28,7 +28,9 @@ import { getLogScope } from '../../../../system/logger.scope';
2828import { PageableResult } from '../../../../system/paging' ;
2929import { getSettledValue } from '../../../../system/promise' ;
3030import type { Git } from '../git' ;
31+ import { GitErrors , gitLogDefaultConfigs } from '../git' ;
3132import type { LocalGitProvider } from '../localGitProvider' ;
33+ import { RunError } from '../shell' ;
3234
3335const emptyPagedResult : PagedResult < any > = Object . freeze ( { values : [ ] } ) ;
3436
@@ -76,7 +78,16 @@ export class BranchesGitSubProvider implements GitBranchesSubProvider {
7678
7779 const [ pausedOpStatusResult , committerDateResult ] = await Promise . allSettled ( [
7880 isDetachedHead ( name ) ? this . provider . status ?. getPausedOperationStatus ( repoPath ) : undefined ,
79- this . git . log__recent_committerdate ( repoPath , commitOrdering ) ,
81+ this . git
82+ . exec (
83+ { cwd : repoPath , configs : gitLogDefaultConfigs , errors : GitErrorHandling . Ignore } ,
84+ 'log' ,
85+ '-n1' ,
86+ '--format=%ct' ,
87+ commitOrdering ? `--${ commitOrdering } -order` : undefined ,
88+ '--' ,
89+ )
90+ . then ( data => ( ! data . length ? undefined : data . trim ( ) ) ) ,
8091 ] ) ;
8192
8293 const committerDate = getSettledValue ( committerDateResult ) ;
@@ -114,7 +125,13 @@ export class BranchesGitSubProvider implements GitBranchesSubProvider {
114125 if ( resultsPromise == null ) {
115126 async function load ( this : BranchesGitSubProvider ) : Promise < PagedResult < GitBranch > > {
116127 try {
117- const data = await this . git . for_each_ref__branch ( repoPath , { all : true } ) ;
128+ const data = await this . git . exec (
129+ { cwd : repoPath } ,
130+ 'for-each-ref' ,
131+ `--format=${ parseGitBranchesDefaultFormat } ` ,
132+ 'refs/heads' ,
133+ 'refs/remotes' ,
134+ ) ;
118135 // If we don't get any data, assume the repo doesn't have any commits yet so check if we have a current branch
119136 if ( ! data ?. length ) {
120137 const current = await this . getCurrentBranch ( repoPath ) ;
@@ -275,7 +292,7 @@ export class BranchesGitSubProvider implements GitBranchesSubProvider {
275292
276293 if ( remote ) {
277294 try {
278- const data = await this . git . ls_remote__HEAD ( repoPath , remote ) ;
295+ const data = await this . git . exec ( { cwd : repoPath } , 'ls- remote' , '--symref' , remote , 'HEAD' ) ;
279296 if ( data == null ) return undefined ;
280297
281298 const match = / r e f : \s ( \S + ) \s + H E A D / m. exec ( data ) ;
@@ -287,7 +304,7 @@ export class BranchesGitSubProvider implements GitBranchesSubProvider {
287304 }
288305
289306 try {
290- const data = await this . git . symbolic_ref ( repoPath , ` refs/remotes/origin/HEAD` ) ;
307+ const data = await this . git . exec ( { cwd : repoPath } , 'symbolic-ref' , '--short' , ' refs/remotes/origin/HEAD' ) ;
291308 return data ?. trim ( ) || undefined ;
292309 } catch { }
293310
@@ -304,8 +321,14 @@ export class BranchesGitSubProvider implements GitBranchesSubProvider {
304321 const scope = getLogScope ( ) ;
305322
306323 try {
307- const data = await this . git . merge_base ( repoPath , ref1 , ref2 , options ) ;
308- if ( data == null ) return undefined ;
324+ const data = await this . git . exec (
325+ { cwd : repoPath } ,
326+ 'merge-base' ,
327+ options ?. forkPoint ? '--fork-point' : undefined ,
328+ ref1 ,
329+ ref2 ,
330+ ) ;
331+ if ( ! data ) return undefined ;
309332
310333 return data . split ( '\n' ) [ 0 ] . trim ( ) || undefined ;
311334 } catch ( ex ) {
@@ -316,7 +339,7 @@ export class BranchesGitSubProvider implements GitBranchesSubProvider {
316339
317340 @log ( )
318341 async createBranch ( repoPath : string , name : string , sha : string ) : Promise < void > {
319- await this . git . branch ( repoPath , name , sha ) ;
342+ await this . git . exec ( { cwd : repoPath } , 'branch' , name , sha ) ;
320343 }
321344
322345 @log ( )
@@ -371,14 +394,7 @@ export class BranchesGitSubProvider implements GitBranchesSubProvider {
371394 } catch { }
372395
373396 // Cherry-pick detection (handles cherry-picks, rebases, etc)
374- const data = await this . git . exec < string > (
375- { cwd : repoPath } ,
376- 'cherry' ,
377- '--abbrev' ,
378- '-v' ,
379- into . name ,
380- branch . name ,
381- ) ;
397+ const data = await this . git . exec ( { cwd : repoPath } , 'cherry' , '--abbrev' , '-v' , into . name , branch . name ) ;
382398 // Check if there are no lines or all lines startwith a `-` (i.e. likely merged)
383399 if ( ! data || data . split ( '\n' ) . every ( l => l . startsWith ( '-' ) ) ) {
384400 return { merged : true , confidence : 'high' } ;
@@ -415,9 +431,37 @@ export class BranchesGitSubProvider implements GitBranchesSubProvider {
415431
416432 let data ;
417433 try {
418- data = await this . git . merge_tree ( repoPath , branch , targetBranch , '-z' , '--name-only' , '--no-messages' ) ;
434+ data = await this . git . exec (
435+ { cwd : repoPath , errors : GitErrorHandling . Throw } ,
436+ 'merge-tree' ,
437+ '-z' ,
438+ '--name-only' ,
439+ '--no-messages' ,
440+ branch ,
441+ targetBranch ,
442+ ) ;
419443 } catch ( ex ) {
420- Logger . error ( ex , scope ) ;
444+ const msg : string = ex ?. toString ( ) ?? '' ;
445+ if ( GitErrors . notAValidObjectName . test ( msg ) ) {
446+ Logger . error (
447+ ex ,
448+ scope ,
449+ `'${ targetBranch } ' or '${ branch } ' not found - ensure the branches exist and are fully qualified (e.g. 'refs/heads/main')` ,
450+ ) ;
451+ } else if ( GitErrors . badRevision . test ( msg ) ) {
452+ Logger . error ( ex , scope , `Invalid branch name: ${ msg . slice ( msg . indexOf ( "'" ) ) } ` ) ;
453+ } else if ( GitErrors . noMergeBase . test ( msg ) ) {
454+ Logger . error (
455+ ex ,
456+ scope ,
457+ `Unable to merge '${ branch } ' and '${ targetBranch } ' as they have no common ancestor` ,
458+ ) ;
459+ } else if ( ex instanceof RunError ) {
460+ data = ex . stdout ;
461+ } else {
462+ Logger . error ( ex , scope ) ;
463+ debugger ;
464+ }
421465 }
422466 if ( ! data ) return undefined ;
423467
@@ -496,7 +540,7 @@ export class BranchesGitSubProvider implements GitBranchesSubProvider {
496540 options ?: { upstream : true } ,
497541 ) : Promise < string | undefined > {
498542 try {
499- let data = await this . git . reflog ( repoPath , undefined , ref , '--grep-reflog=branch: Created from *.' ) ;
543+ let data = await this . git . exec ( { cwd : repoPath } , 'reflog' , ref , '--grep-reflog=branch: Created from *.' ) ;
500544
501545 let entries = data . split ( '\n' ) . filter ( entry => Boolean ( entry ) ) ;
502546 if ( entries . length !== 1 ) return undefined ;
@@ -517,12 +561,13 @@ export class BranchesGitSubProvider implements GitBranchesSubProvider {
517561 }
518562
519563 // Check if branch was created from HEAD
520- data = await this . git . reflog (
521- repoPath ,
522- undefined ,
564+ data = await this . git . exec (
565+ { cwd : repoPath } ,
566+ 'reflog' ,
523567 'HEAD' ,
524568 `--grep-reflog=checkout: moving from .* to ${ ref . replace ( 'refs/heads/' , '' ) } ` ,
525569 ) ;
570+
526571 entries = data . split ( '\n' ) . filter ( entry => Boolean ( entry ) ) ;
527572 if ( ! entries . length ) return undefined ;
528573
@@ -562,11 +607,11 @@ export class BranchesGitSubProvider implements GitBranchesSubProvider {
562607
563608 @log ( )
564609 async renameBranch ( repoPath : string , oldName : string , newName : string ) : Promise < void > {
565- await this . git . branch ( repoPath , '-m' , oldName , newName ) ;
610+ await this . git . exec ( { cwd : repoPath } , 'branch' , '-m' , oldName , newName ) ;
566611 }
567612
568613 private async getValidatedBranchName ( repoPath : string , name : string ) : Promise < string | undefined > {
569- const data = await this . git . exec < string > (
614+ const data = await this . git . exec (
570615 { cwd : repoPath , errors : GitErrorHandling . Ignore } ,
571616 'rev-parse' ,
572617 '--verify' ,
0 commit comments