🔗Git for Windows’ release process

The release process of Git for Windows is ever-evolving. For now, it consists of these steps:

Note: the hardest part is traditonally preparing -rc0 of every major release.

🔗Making sure that there are no unaddressed issues

There are essentially three-and-a-half venues where Git for Windows bugs are reported:

🔗In case last-minute component updates are needed

What if, say, a new Git Credential Manager Core version needs to be snuck in at the last minute (where “last minute” is anything within the past 24h)?

To integrate such an updated component, depending on the component type (MINGW or MSYS?) either the Build and publish MINGW Pacman package or the Build and publish MSYS Pacman package Pipeline need to be triggered (specifying the component name via the package.to.build variable at queue time).

Once the component has been built and uploaded to Git for Windows’ Pacman repositories (i.e. once that triggered Pipeline finished), the sync workflows (32-bit and 64-bit) must be triggered, manually. These workflows are responsible for installing the updated Pacman packages into the git-sdk-64 and git-sdk-32 repositories.

Note: Historically, we used the artifacts of the git-sdk-64-extra-artifacts and the git-sdk-32-extra-artifacts Pipeline Pipelines that were triggered automatically by pushes to git-sdk-64 and git-sdk-32, respectively, and we had to wait for them to complete before proceeding. As of June 17th, 2022, this is no longer necessary.

🔗Rebasing Git for Windows’ patches

Note: this section assumes that the reader is very familiar with interactive rebases, in particular with the --rebase-merges variant thereof. Readers without much experience in this are highly advised to read up on https://git-scm.com/docs/git-rebase#_rebasing_merges before going any further.

The trick is not just to run /usr/src/build-extra/shears.sh --merging --onto <version> merging-rebase, it is even more important to verify that the result makes sense. To make sense, the result:

Note: internally, the shears.sh script runs git rebase --rebase-merges --interactive with one quirk: a first line is injected into the todo list that creates a “dummy” merge commit: it is a merge that pulls in the pre-rebase commits, but it uses -s ours so that the tree remains unchanged relative to the onto commit. The effect is that the patches got rebased, and the end result still fast-forwards from the previous tip of the main branch.

🔗Opening a PR to kick off a PR build

This is easy: just push a branch to your fork and then go to https://github.com/git-for-windows/git/pull/new/main and select that branch from your fork.

The harder part is to include the range-diff (with --creation-factor=95; see the gfw-range-diff alias in the previous section) and discuss it.

To make it easier to see what happened to patches that are no longer part of Git for Windows’ branch thicket, it is highly advised to use a variant of the shell script used in https://github.com/git-for-windows/git/pull/2626, and to perform a similarly thorough analysis, especially for any -rc0 version:

$ x="$(git range-diff -s origin/main^{/^Start.the}..origin/main v2.27.0..v2.28.0-rc0 |
    sed -n 's/^[ 0-9]*:  \([0-9a-f][0-9a-f]*\) [=!] [ 0-9]*:  \([0-9a-f][0-9a-f]*\).*/-e "s\/\1\/\1 (upstream: \2)\/"/p')"

$ git gfw-range-diff origin/main HEAD |
  sed -e 's/^[ 0-9]*:  [0-9a-f]* [=!]/ &/' \
      -e 's/^[ 0-9]*:  [0-9a-f]* </-&/' \
      -e 's/^[ 0-9]*:  [0-9a-f]* >/+&/' |
  eval sed ${x:-\'\'} |
  clip.exe

For convenience, this can be automated via this alias:

[alias]
	pre-release-pr-range-diff = "!set -x && x=\"$(git range-diff -s origin/main^{/^Start.the}..origin/main origin/main^{/^Start.the}^..HEAD^{/^Start.the}^ | sed -n 's/^[ 0-9]*:  \\([0-9a-f][0-9a-f]*\\) [=!] [ 0-9]*:  \\([0-9a-f][0-9a-f]*\\).*/-e \"s\\/\\1\\/\\1 (upstream: \\2)\\/\"/p')\" && git gfw-range-diff origin/main HEAD | sed -e 's/^[ 0-9]*:  [0-9a-f]* [=!]/ &/' -e 's/^[ 0-9]*:  [0-9a-f]* </-&/' -e 's/^[ 0-9]*:  [0-9a-f]* >/+&/' | eval sed ${x:-\\'\\'} | clip.exe"

🔗Linking the “New git version” issue

When a new version is tagged in upstream git, the “Monitor Component Updates” pipeline in Git for Windows creates an issue for the version (example). For tracking & automation purposes, you should:

🔗Kicking off the “Git Artifacts” automation

Add a PR comment with the slash command /git-artifacts. This will kick off several GitHub workflow runs in https://github.com/git-for-windows/git-for-windows-automation: one to create the tag and adjust the release notes, and then one each for every CPU architecture supported by Git for Windows generating:

🔗Verifying that the resulting installer works

The idea here is to download the Git-<version>-64-bit.exe artifact from the workflow run, install it, and run through the “pre-flight check list” at https://github.com/git-for-windows/build-extra/blob/HEAD/installer/checklist.txt.

🔗Kicking off the /release slash command that publishes the release

This one is really easy (as long as nothing is broken…): add a PR comment with the /release slash command.

Note: The pacman upload always takes this long.

Sadly, things are broken a lot. In those cases, the logs have to be analyzed, and the GitHub workflow definition needs to be edited (on the release branch of git-for-windows/git-for-windows-automation), and the failing jobs of the workflow run have to be rerunExamples for failures that happened in the past:

🔗Pushing directly to main to close the PR and set the stage for uploading the release as a new snapshot

This step is trivial: git push origin <branch>:main where <branch> is something like rebase-to-v2.37.0.

This will trigger another “Git artifacts” run, which will figure out that there is a GitHub Release for that commit, download those artifacts, then trigger a run of the Snapshots Release Pipeline, which will then upload the snapshot.

It is important to wait with pushing to main until there is a GitHub Release, otherwise the “Git artifacts” Pipeline would build another set of artifacts and upload those, but we do want to use the same artifacts as were uploaded to GitHub Releases.

Note: The idea is to push to main relatively soon after the Release Pipeline finished, to keep the Pacman repository, the snapshots and the main branches as aligned as possible.

🔗How to release a quick-fix release

Outside of the -rc<N> phase, just follow the process as described above. This will publish one of those (2) versions, e.g. v2.24.1(2). Typically this happens very close after an official release e.g. when really serious bugs crept into Git for Windows unnoticed, such as Git GUI crashing before even showing the window.

In the hypothetical case that a quick-fix release is necessary during the -rc<N> phase, after main was pushed, i.e. needing to branch off of an earlier revision of main, all the above steps can be performed with ease (as the Pipelines do not run directly on main, but instead require use.branch to be set). The only tricky part is pushing the result to main. The recommended way is to use the next merging rebase to pull in the changes by inserting another fake merge before the one inserted by shears.sh.