From df9ce672278a097c435006d29bb1c2a057e4e94e Mon Sep 17 00:00:00 2001
From: Steven Van Ingelgem <steven@vaningelgem.be>
Date: Tue, 10 Jun 2025 08:37:42 +0200
Subject: [PATCH 1/5] Allow to fetch tags.

---
 src/git-command-manager.ts | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/git-command-manager.ts b/src/git-command-manager.ts
index 8e42a38..261aedc 100644
--- a/src/git-command-manager.ts
+++ b/src/git-command-manager.ts
@@ -261,8 +261,8 @@ class GitCommandManager {
     }
   ): Promise<void> {
     const args = ['-c', 'protocol.version=2', 'fetch']
-    if (!refSpec.some(x => x === refHelper.tagsRefSpec) && !options.fetchTags) {
-      args.push('--no-tags')
+    if (!refSpec.some(x => x === refHelper.tagsRefSpec)) {
+      args.push(options.fetchTags ? '--tags' : '--no-tags')
     }
 
     args.push('--prune', '--no-recurse-submodules')

From 6b47c9436e478eec2220e61972b035623a83c11e Mon Sep 17 00:00:00 2001
From: Steven Van Ingelgem <steven@vaningelgem.be>
Date: Tue, 10 Jun 2025 08:45:30 +0200
Subject: [PATCH 2/5] Allow to fetch tags.

---
 __test__/git-command-manager.test.ts | 3 +++
 dist/index.js                        | 4 ++--
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/__test__/git-command-manager.test.ts b/__test__/git-command-manager.test.ts
index cea73d4..9b12027 100644
--- a/__test__/git-command-manager.test.ts
+++ b/__test__/git-command-manager.test.ts
@@ -134,6 +134,7 @@ describe('Test fetchDepth and fetchTags options', () => {
         '-c',
         'protocol.version=2',
         'fetch',
+        '--tags',
         '--prune',
         '--no-recurse-submodules',
         '--filter=filterValue',
@@ -248,6 +249,7 @@ describe('Test fetchDepth and fetchTags options', () => {
         '-c',
         'protocol.version=2',
         'fetch',
+        '--tags',
         '--prune',
         '--no-recurse-submodules',
         '--filter=filterValue',
@@ -364,6 +366,7 @@ describe('Test fetchDepth and fetchTags options', () => {
         '-c',
         'protocol.version=2',
         'fetch',
+        '--tags',
         '--prune',
         '--no-recurse-submodules',
         '--progress',
diff --git a/dist/index.js b/dist/index.js
index b0db713..009a26b 100644
--- a/dist/index.js
+++ b/dist/index.js
@@ -653,8 +653,8 @@ class GitCommandManager {
     fetch(refSpec, options) {
         return __awaiter(this, void 0, void 0, function* () {
             const args = ['-c', 'protocol.version=2', 'fetch'];
-            if (!refSpec.some(x => x === refHelper.tagsRefSpec) && !options.fetchTags) {
-                args.push('--no-tags');
+            if (!refSpec.some(x => x === refHelper.tagsRefSpec)) {
+                args.push(options.fetchTags ? '--tags' : '--no-tags');
             }
             args.push('--prune', '--no-recurse-submodules');
             if (options.showProgress) {

From f3e6cc288df3938c4af7657194799ee8a7a4aff3 Mon Sep 17 00:00:00 2001
From: Steven Van Ingelgem <steven@vaningelgem.be>
Date: Tue, 10 Jun 2025 09:24:38 +0200
Subject: [PATCH 3/5] Ignore intellij

---
 .gitignore | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/.gitignore b/.gitignore
index cd1f03c..5f16633 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,4 +2,5 @@ __test__/_temp
 _temp/
 lib/
 node_modules/
-.vscode/
\ No newline at end of file
+.vscode/
+.idea/

From 49528c1b57f74392481cee840cc1374349293aff Mon Sep 17 00:00:00 2001
From: Steven Van Ingelgem <steven@vaningelgem.be>
Date: Tue, 10 Jun 2025 09:24:51 +0200
Subject: [PATCH 4/5] Proper 2.48 tags handling

---
 src/git-command-manager.ts | 21 +++++++++++++++++++--
 1 file changed, 19 insertions(+), 2 deletions(-)

diff --git a/src/git-command-manager.ts b/src/git-command-manager.ts
index 261aedc..2d1303b 100644
--- a/src/git-command-manager.ts
+++ b/src/git-command-manager.ts
@@ -261,8 +261,12 @@ class GitCommandManager {
     }
   ): Promise<void> {
     const args = ['-c', 'protocol.version=2', 'fetch']
-    if (!refSpec.some(x => x === refHelper.tagsRefSpec)) {
-      args.push(options.fetchTags ? '--tags' : '--no-tags')
+    const hasTagsRefSpec = refSpec.some(x => x === refHelper.tagsRefSpec)
+    const needsSeparateTagFetch = this.gitVersion.toString().startsWith('2.48') && options.fetchTags && !hasTagsRefSpec
+
+    if (!hasTagsRefSpec) {
+      // For git 2.48, skip --tags here if we need separate fetch
+      args.push(needsSeparateTagFetch || !options.fetchTags ? '--no-tags' : '--tags')
     }
 
     args.push('--prune', '--no-recurse-submodules')
@@ -293,6 +297,19 @@ class GitCommandManager {
     await retryHelper.execute(async () => {
       await that.execGit(args)
     })
+
+    // Separate tag fetch for git 2.48
+    if (needsSeparateTagFetch) {
+      const tagArgs = ['-c', 'protocol.version=2', 'fetch', '--tags', '--prune']
+      if (options.showProgress) {
+        tagArgs.push('--progress')
+      }
+      tagArgs.push('origin')
+
+      await retryHelper.execute(async () => {
+        await that.execGit(tagArgs)
+      })
+    }
   }
 
   async getDefaultBranch(repositoryUrl: string): Promise<string> {

From 0548471950d86b19eae6c063105707c831fb5c03 Mon Sep 17 00:00:00 2001
From: Steven Van Ingelgem <steven@vaningelgem.be>
Date: Tue, 10 Jun 2025 09:26:54 +0200
Subject: [PATCH 5/5] Updated tests for the differences in 2.48 behaviour

---
 __test__/git-command-manager.test.ts | 222 +++++++++++++++++++++++++++
 1 file changed, 222 insertions(+)

diff --git a/__test__/git-command-manager.test.ts b/__test__/git-command-manager.test.ts
index 9b12027..dbe0c4e 100644
--- a/__test__/git-command-manager.test.ts
+++ b/__test__/git-command-manager.test.ts
@@ -379,3 +379,225 @@ describe('Test fetchDepth and fetchTags options', () => {
     )
   })
 })
+
+describe('Test git 2.48 tag fetching behavior', () => {
+  beforeEach(async () => {
+    jest.spyOn(fshelper, 'fileExistsSync').mockImplementation(jest.fn())
+    jest.spyOn(fshelper, 'directoryExistsSync').mockImplementation(jest.fn())
+  })
+
+  afterEach(() => {
+    jest.restoreAllMocks()
+  })
+
+  it('should perform separate tag fetch for git 2.48 when fetchTags is true', async () => {
+    mockExec.mockImplementation((path, args, options) => {
+      if (args.includes('version')) {
+        options.listeners.stdout(Buffer.from('2.48.1'))
+      }
+      return 0
+    })
+    jest.spyOn(exec, 'exec').mockImplementation(mockExec)
+
+    const workingDirectory = 'test'
+    const lfs = false
+    const doSparseCheckout = false
+    git = await commandManager.createCommandManager(
+      workingDirectory,
+      lfs,
+      doSparseCheckout
+    )
+
+    const refSpec = ['refspec1']
+    const options = {
+      fetchTags: true
+    }
+
+    await git.fetch(refSpec, options)
+
+    // First call: main fetch with --no-tags
+    expect(mockExec).toHaveBeenNthCalledWith(
+      2, // First call is version check
+      expect.any(String),
+      [
+        '-c',
+        'protocol.version=2',
+        'fetch',
+        '--no-tags',
+        '--prune',
+        '--no-recurse-submodules',
+        'origin',
+        'refspec1'
+      ],
+      expect.any(Object)
+    )
+
+    // Second call: separate tag fetch
+    expect(mockExec).toHaveBeenNthCalledWith(
+      3,
+      expect.any(String),
+      [
+        '-c',
+        'protocol.version=2',
+        'fetch',
+        '--tags',
+        '--prune',
+        'origin'
+      ],
+      expect.any(Object)
+    )
+
+    expect(mockExec).toHaveBeenCalledTimes(3) // version + main fetch + tag fetch
+  })
+
+  it('should perform separate tag fetch with progress for git 2.48', async () => {
+    mockExec.mockImplementation((path, args, options) => {
+      if (args.includes('version')) {
+        options.listeners.stdout(Buffer.from('2.48.0'))
+      }
+      return 0
+    })
+    jest.spyOn(exec, 'exec').mockImplementation(mockExec)
+
+    const workingDirectory = 'test'
+    const lfs = false
+    const doSparseCheckout = false
+    git = await commandManager.createCommandManager(
+      workingDirectory,
+      lfs,
+      doSparseCheckout
+    )
+
+    const refSpec = ['refspec1']
+    const options = {
+      fetchTags: true,
+      showProgress: true
+    }
+
+    await git.fetch(refSpec, options)
+
+    // Main fetch with --no-tags and --progress
+    expect(mockExec).toHaveBeenNthCalledWith(
+      2,
+      expect.any(String),
+      [
+        '-c',
+        'protocol.version=2',
+        'fetch',
+        '--no-tags',
+        '--prune',
+        '--no-recurse-submodules',
+        '--progress',
+        'origin',
+        'refspec1'
+      ],
+      expect.any(Object)
+    )
+
+    // Separate tag fetch with --progress
+    expect(mockExec).toHaveBeenNthCalledWith(
+      3,
+      expect.any(String),
+      [
+        '-c',
+        'protocol.version=2',
+        'fetch',
+        '--tags',
+        '--prune',
+        '--progress',
+        'origin'
+      ],
+      expect.any(Object)
+    )
+  })
+
+  it('should NOT perform separate tag fetch for git 2.48 when fetchTags is false', async () => {
+    mockExec.mockImplementation((path, args, options) => {
+      if (args.includes('version')) {
+        options.listeners.stdout(Buffer.from('2.48.1'))
+      }
+      return 0
+    })
+    jest.spyOn(exec, 'exec').mockImplementation(mockExec)
+
+    const workingDirectory = 'test'
+    const lfs = false
+    const doSparseCheckout = false
+    git = await commandManager.createCommandManager(
+      workingDirectory,
+      lfs,
+      doSparseCheckout
+    )
+
+    const refSpec = ['refspec1']
+    const options = {
+      fetchTags: false
+    }
+
+    await git.fetch(refSpec, options)
+
+    // Only one fetch call with --no-tags
+    expect(mockExec).toHaveBeenNthCalledWith(
+      2,
+      expect.any(String),
+      [
+        '-c',
+        'protocol.version=2',
+        'fetch',
+        '--no-tags',
+        '--prune',
+        '--no-recurse-submodules',
+        'origin',
+        'refspec1'
+      ],
+      expect.any(Object)
+    )
+
+    expect(mockExec).toHaveBeenCalledTimes(2) // version + single fetch only
+  })
+
+  it('should use normal behavior for non-2.48 git versions', async () => {
+    mockExec.mockImplementation((path, args, options) => {
+      if (args.includes('version')) {
+        options.listeners.stdout(Buffer.from('2.47.0'))
+      }
+      return 0
+    })
+    jest.spyOn(exec, 'exec').mockImplementation(mockExec)
+
+    const workingDirectory = 'test'
+    const lfs = false
+    const doSparseCheckout = false
+    git = await commandManager.createCommandManager(
+      workingDirectory,
+      lfs,
+      doSparseCheckout
+    )
+
+    const refSpec = ['refspec1']
+    const options = {
+      fetchTags: true
+    }
+
+    await git.fetch(refSpec, options)
+
+    // Single fetch with --tags
+    expect(mockExec).toHaveBeenNthCalledWith(
+      2,
+      expect.any(String),
+      [
+        '-c',
+        'protocol.version=2',
+        'fetch',
+        '--tags',
+        '--prune',
+        '--no-recurse-submodules',
+        'origin',
+        'refspec1'
+      ],
+      expect.any(Object)
+    )
+
+    expect(mockExec).toHaveBeenCalledTimes(2) // version + single fetch only
+  })
+})