From 8eb845981e077274d2746a753a5f91ba35a243d8 Mon Sep 17 00:00:00 2001 From: Matthew John Cheetham Date: Mon, 12 Oct 2026 13:53:04 +0100 Subject: [PATCH 1/5] fixup! release: use correct ESRP param name in tasks Signed-off-by: Matthew John Cheetham --- .azure-pipelines/release.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.azure-pipelines/release.yml b/.azure-pipelines/release.yml index 1940056e2b3b21..2d2a7f31857122 100644 --- a/.azure-pipelines/release.yml +++ b/.azure-pipelines/release.yml @@ -160,12 +160,12 @@ extends: inputs: azureSubscription: $(esrpAppConnectionName) addSpnToEnvironment: true - scriptType: ps + scriptType: bash scriptLocation: inlineScript inlineScript: | - Write-Host "ESRP connection details:" - Write-Host "ClientId: $env:servicePrincipalId" - Write-Host "TenantId: $env:tenantId" + echo "ESRP connection details:" + echo "ClientId: $servicePrincipalId" + echo "TenantId: $tenantId" - stage: build displayName: 'Build' From 7df1c81bd36dbcef5e689785c2b06b8c1c495e05 Mon Sep 17 00:00:00 2001 From: Matthew John Cheetham Date: Mon, 12 Oct 2026 11:18:03 +0100 Subject: [PATCH 2/5] release: add Linux and macOS binary tarballs Official Linux and macOS releases currently offer only installers. Provide binary tarballs alongside them so consumers can extract the release payload without running a platform-specific installer. Reuse the staged installation trees to keep the archives aligned with the installers, including signed macOS binaries when ESRP is enabled. Preserve the usr/local layout and support files expected by the existing builds rather than creating a separate relocatable distribution. Linux archives retain the Debian package's runtime dependencies. Assisted-by: GPT-6.1 Sol Signed-off-by: Matthew John Cheetham --- .azure-pipelines/release.yml | 25 +++++++++++++++++-------- README.md | 8 +++++++- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/.azure-pipelines/release.yml b/.azure-pipelines/release.yml index 2d2a7f31857122..4975d17722cda7 100644 --- a/.azure-pipelines/release.yml +++ b/.azure-pipelines/release.yml @@ -719,7 +719,8 @@ extends: # 5. `make pkg` -> unsigned .pkg in disk-image/. # 6. ESRP-sign and ESRP-notarize the .pkg in place. # 7. `make image` wraps disk-image/ contents in a DMG. - # 8. Stage the .pkg and .dmg under _final/ for upload. + # 8. Archive build-artifacts/ as a binary .tar.gz and + # stage it with the .pkg and .dmg under _final/ for upload. steps: - checkout: self - task: Bash@3 @@ -1032,13 +1033,14 @@ extends: # which contains the signed and notarized .pkg. make -C .github/macos-installer V=1 ARCH_UNIV=$(cc_arch) image - task: Bash@3 - displayName: 'Stage installer artifacts for upload' + displayName: 'Stage release artifacts for upload' inputs: targetType: inline script: | set -euo pipefail - mkdir -p "$(Build.ArtifactStagingDirectory)/_final" + final_dir="$(Build.ArtifactStagingDirectory)/_final" + mkdir -p "$final_dir" ls -la .github/macos-installer/ \ .github/macos-installer/disk-image/ || true # The .pkg lands either directly under disk-image/ @@ -1049,7 +1051,10 @@ extends: | head -1) mv .github/macos-installer/git-*-$(cc_arch).dmg \ "$pkg" \ - "$(Build.ArtifactStagingDirectory)/_final/" + "$final_dir/" + tar -czf \ + "$final_dir/git-$(git_version)-$(cc_arch).tar.gz" \ + -C .github/macos-installer/build-artifacts usr # Validate the freshly built pkg in-place: install it, # assert `git --version`, and confirm the binary contains # only the specific architecture. Folded into the build job @@ -1208,14 +1213,18 @@ extends: } ] - task: Bash@3 - displayName: 'Stage Debian package for upload' + displayName: 'Stage release artifacts for upload' inputs: targetType: inline script: | set -euo pipefail - mkdir -p "$(Build.ArtifactStagingDirectory)/_final" - mv "$(Build.ArtifactStagingDirectory)/app/microsoft-git_$(git_version)_$(deb_arch).deb" \ - "$(Build.ArtifactStagingDirectory)/_final/" + + staging_dir="$(Build.ArtifactStagingDirectory)" + pkg_name="microsoft-git_$(git_version)_$(deb_arch)" + mkdir -p "$staging_dir/_final" + mv "$staging_dir/app/$pkg_name.deb" "$staging_dir/_final/" + tar -czf "$staging_dir/_final/$pkg_name.tar.gz" \ + -C "$staging_dir/pkgroot" usr # Validate the freshly built .deb in-place: install it # and assert `git --version`. Folded into the build job # so it runs on the same agent without the 1ES job- diff --git a/README.md b/README.md index 3e0fa1516b879c..c2176ef96f0a4e 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,13 @@ Downloading and Installing If you're working in a monorepo and want to take advantage of the performance boosts in `microsoft/git`, then you can download the latest version installer for your OS from the [Releases page](https://github.com/microsoft/git/releases). Alternatively, you can opt to install -via the command line, using the below instructions for supported OSes: +via the command line, using the below instructions for supported OSes. + +Binary `.tar.gz` archives are also available for Linux (x64 and ARM64) and +macOS (ARM64). They contain the installers' `usr/local` tree and can be +extracted at the filesystem root. Linux archives require the same runtime +dependencies as the Debian package; they do not make older distributions +compatible. ## Windows From dd57ca4b12eb1cc56c1d5b13628f11356a38dbaf Mon Sep 17 00:00:00 2001 From: Matthew John Cheetham Date: Mon, 12 Oct 2026 11:56:34 +0100 Subject: [PATCH 3/5] release: use macos- and linux- tar.gz names Today there is no clear differentiation between the Linux and Mac release artifacts other than their file extensions (.deb for Linux Debian package, and .pkg for macOS Installer package). Since the tarballs use the same extension on both platforms (.tar.gz) we need a more clear way to tell them apart. Add a macos- and linux- prefix to the architecture part of the artifact file names for the tarballs. Note: it technically is possible to tell the difference because the Linux artifact is "microsoft-git-*" and the Mac artifact is "git-*" but this is very subtle. Signed-off-by: Matthew John Cheetham --- .azure-pipelines/release.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.azure-pipelines/release.yml b/.azure-pipelines/release.yml index 4975d17722cda7..5028defe459315 100644 --- a/.azure-pipelines/release.yml +++ b/.azure-pipelines/release.yml @@ -1053,7 +1053,7 @@ extends: "$pkg" \ "$final_dir/" tar -czf \ - "$final_dir/git-$(git_version)-$(cc_arch).tar.gz" \ + "$final_dir/git-$(git_version)-macos-$(cc_arch).tar.gz" \ -C .github/macos-installer/build-artifacts usr # Validate the freshly built pkg in-place: install it, # assert `git --version`, and confirm the binary contains @@ -1220,10 +1220,9 @@ extends: set -euo pipefail staging_dir="$(Build.ArtifactStagingDirectory)" - pkg_name="microsoft-git_$(git_version)_$(deb_arch)" mkdir -p "$staging_dir/_final" - mv "$staging_dir/app/$pkg_name.deb" "$staging_dir/_final/" - tar -czf "$staging_dir/_final/$pkg_name.tar.gz" \ + mv "$staging_dir/app/microsoft-git_$(git_version)_$(deb_arch).deb" "$staging_dir/_final/" + tar -czf "$staging_dir/_final/microsoft-git_$(git_version)_linux_$(deb_arch).tar.gz" \ -C "$staging_dir/pkgroot" usr # Validate the freshly built .deb in-place: install it # and assert `git --version`. Folded into the build job From 81a1edff6b66af1eac3a921b04cd61f8338c7ade Mon Sep 17 00:00:00 2001 From: Matthew John Cheetham Date: Mon, 12 Oct 2026 12:13:13 +0100 Subject: [PATCH 4/5] release: add macos to package filenames Binary tarballs now include the platform before the CPU architecture, but macOS installer packages still omit it. Give packages the same macos- suffix so installers and archives follow a consistent naming convention. Rename the package at build time rather than only when staging release assets so the DMG contains the same filename as the standalone package. Keep packaging, notarization and the Azure installer lookups aligned. Assisted-by: GPT-6.1 Sol Signed-off-by: Matthew John Cheetham --- .azure-pipelines/release.yml | 12 ++++++------ .github/macos-installer/Makefile | 14 ++++++++------ 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/.azure-pipelines/release.yml b/.azure-pipelines/release.yml index 5028defe459315..6671167e164582 100644 --- a/.azure-pipelines/release.yml +++ b/.azure-pipelines/release.yml @@ -1029,8 +1029,8 @@ extends: VERSION="$(git_version)" export VERSION - # Builds git--$(cc_arch).dmg from disk-image/, - # which contains the signed and notarized .pkg. + # Wrap the signed and notarized .pkg from disk-image/ + # in git--macos-$(cc_arch).dmg. make -C .github/macos-installer V=1 ARCH_UNIV=$(cc_arch) image - task: Bash@3 displayName: 'Stage release artifacts for upload' @@ -1047,9 +1047,9 @@ extends: # or, after ESRP MacAppNotarize re-packs it, inside # disk-image/.zip.unzipped/. Find it. pkg=$(find .github/macos-installer/disk-image \ - -name "git-*-$(cc_arch).pkg" -type f \ + -name "git-*-macos-$(cc_arch).pkg" -type f \ | head -1) - mv .github/macos-installer/git-*-$(cc_arch).dmg \ + mv .github/macos-installer/git-*-macos-$(cc_arch).dmg \ "$pkg" \ "$final_dir/" tar -czf \ @@ -1066,9 +1066,9 @@ extends: brew uninstall git || true fi pkg=$(find "$(Build.ArtifactStagingDirectory)/_final" \ - -name "git-*-$(cc_arch).pkg" -type f | head -1) + -name "git-*-macos-$(cc_arch).pkg" -type f | head -1) if [ -z "$pkg" ]; then - echo "No git-*-$(cc_arch).pkg found in _final" >&2 + echo "No git-*-macos-$(cc_arch).pkg found in _final" >&2 exit 1 fi echo "Installing $pkg" diff --git a/.github/macos-installer/Makefile b/.github/macos-installer/Makefile index 949995b08e6291..9b390ddbb668fe 100644 --- a/.github/macos-installer/Makefile +++ b/.github/macos-installer/Makefile @@ -121,6 +121,8 @@ disk-image/VERSION-$(VERSION)-$(ARCH_UNIV): mkdir disk-image touch "$@" +pkg_file := disk-image/git-$(ORIGINAL_VERSION)-macos-$(ARCH_UNIV).pkg + pkg_cmd := pkgbuild --identifier com.git.pkg --version $(VERSION) \ --root $(ARTIFACTDIR)$(PREFIX) --scripts assets/scripts \ --install-location $(PREFIX) @@ -129,12 +131,12 @@ ifdef APPLE_INSTALLER_IDENTITY pkg_cmd += --sign "$(APPLE_INSTALLER_IDENTITY)" endif -pkg_cmd += disk-image/git-$(ORIGINAL_VERSION)-$(ARCH_UNIV).pkg +pkg_cmd += $(pkg_file) -disk-image/git-$(ORIGINAL_VERSION)-$(ARCH_UNIV).pkg: disk-image/VERSION-$(VERSION)-$(ARCH_UNIV) symlinks +$(pkg_file): disk-image/VERSION-$(VERSION)-$(ARCH_UNIV) symlinks $(pkg_cmd) -git-%-$(ARCH_UNIV).dmg: +git-%-macos-$(ARCH_UNIV).dmg: hdiutil create git-$(ORIGINAL_VERSION)-$(ARCH_UNIV).uncompressed.dmg -fs HFS+ -srcfolder disk-image -volname "Git $(ORIGINAL_VERSION) $(ARCH_UNIV)" -ov 2>&1 | tee err || { \ grep "Resource busy" err && \ sleep 5 && \ @@ -144,9 +146,9 @@ git-%-$(ARCH_UNIV).dmg: payload: $(BUILD_DIR)/git-$(VERSION)/osx-installed $(BUILD_DIR)/git-$(VERSION)/osx-built-assert-$(ARCH_UNIV) -pkg: disk-image/git-$(ORIGINAL_VERSION)-$(ARCH_UNIV).pkg +pkg: $(pkg_file) -image: git-$(ORIGINAL_VERSION)-$(ARCH_UNIV).dmg +image: git-$(ORIGINAL_VERSION)-macos-$(ARCH_UNIV).dmg ifdef APPLE_APP_IDENTITY codesign: @@ -159,6 +161,6 @@ endif ifdef APPLE_KEYCHAIN_PROFILE notarize: @$(CURDIR)/../scripts/notarize.sh \ - --package="disk-image/git-$(ORIGINAL_VERSION)-$(ARCH_UNIV).pkg" \ + --package="$(pkg_file)" \ --keychain-profile="$(APPLE_KEYCHAIN_PROFILE)" endif From d6d9570a06edb2c080e6bf388eddcc5cbd418bed Mon Sep 17 00:00:00 2001 From: Matthew John Cheetham Date: Mon, 12 Oct 2026 12:25:41 +0100 Subject: [PATCH 5/5] release: add linux to Debian package filenames Linux tarballs already identify their platform in the filename, while Debian packages do not. Give both artifacts the same microsoft-git__linux_ basename so release assets follow a consistent naming convention. The build and staging steps must agree on this basename; otherwise staging tries to move a file that dpkg-deb never created. Keep the Debian package metadata unchanged: the qualifier identifies the release asset, not the installed package. Assisted-by: GPT-6.1 Sol Signed-off-by: Matthew John Cheetham --- .azure-pipelines/release.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.azure-pipelines/release.yml b/.azure-pipelines/release.yml index 6671167e164582..c26344031531a1 100644 --- a/.azure-pipelines/release.yml +++ b/.azure-pipelines/release.yml @@ -1156,7 +1156,7 @@ extends: echo "$BUILD_VERSION" >version make GIT-VERSION-FILE - PKGNAME="microsoft-git_${VERSION}_$(deb_arch)" + PKGNAME="microsoft-git_${VERSION}_linux_$(deb_arch)" PKGDIR="$(Build.ArtifactStagingDirectory)/pkgroot" rm -rf "$PKGDIR" mkdir -p "$PKGDIR/DEBIAN" @@ -1221,9 +1221,10 @@ extends: staging_dir="$(Build.ArtifactStagingDirectory)" mkdir -p "$staging_dir/_final" - mv "$staging_dir/app/microsoft-git_$(git_version)_$(deb_arch).deb" "$staging_dir/_final/" - tar -czf "$staging_dir/_final/microsoft-git_$(git_version)_linux_$(deb_arch).tar.gz" \ - -C "$staging_dir/pkgroot" usr + pkg_name="microsoft-git_$(git_version)_linux_$(deb_arch)" + mv "$staging_dir/app/$pkg_name.deb" "$staging_dir/_final/" + tar -czf "$staging_dir/_final/$pkg_name.tar.gz" \ + -C "$staging_dir/pkgroot" usr # Validate the freshly built .deb in-place: install it # and assert `git --version`. Folded into the build job # so it runs on the same agent without the 1ES job-