The core team of Git LFS maintainers publishes releases on a cadence of their determining.
We follow Semantic Versioning standards as follows:
-
MAJOR
releases are done on a scale of 2-4 years. These encompass breaking, incompatible API changes, or command-line interface changes that would cause existing programs or use-cases scripted against Git LFS to break. -
MINOR
releases are done on a scale of 2-6 months. These encompass new features, bug fixes, and other "medium"-sized changes into a semi-regular release schedule. -
PATCH
releases are done on the scale of weeks to months. These encompass critical bug fixes, but lack new features. They are amended to aMINOR
release "series", or, if serious enough (e.g., security vulnerabilities, etc.) are backported to previous versions.
We package several artifacts for each tagged release. They are:
-
git-lfs-@{os}-v@{release}-@{arch}.tar.gz
for the following values:operating system architecture git-lfs-darwin-amd64-v@{version}.tar.gz darwin amd64 git-lfs-darwin-arm64-v@{version}.tar.gz darwin arm64 git-lfs-freebsd-386-v@{version}.tar.gz freebsd 386 git-lfs-freebsd-amd64-v@{version}.tar.gz freebsd amd64 git-lfs-linux-386-v@{version}.tar.gz linux (generic) 386 git-lfs-linux-amd64-v@{version}.tar.gz linux (generic) amd64 git-lfs-linux-arm-v@{version}.tar.gz linux (generic) arm git-lfs-linux-arm64-v@{version}.tar.gz linux (generic) arm64 git-lfs-linux-ppc64le-v@{version}.tar.gz linux (generic) ppc64le git-lfs-linux-s390x-v@{version}.tar.gz linux (generic) s390x git-lfs-linux-loong64-v@{version}.tar.gz linux (generic) loong64 -
git-lfs-windows-v@{release}-@{arch}.zip
for the following values:operating system architecture git-lfs-windows-386-v@{version}.zip windows 386 git-lfs-windows-amd64-v@{version}.zip windows amd64 git-lfs-windows-arm64-v@{version}.zip windows arm64 -
git-lfs-windows-v@{release}.exe
, a signed Windows installer that contains copies of both-x86
and-x64
copies of Git LFS. -
*.deb
, and*.rpm
packages for all of the distributions named inscript/packagegcloud.rb
.
We do all major development on the main
branch, and assume it to be passing
tests at all times. New features are added via the feature-branch workflow, or
(optionally) from a contributor's fork.
This is done so that main
can progress and grow new features, while
historical releases such as vM.N.0
can receive bug fixes as they are applied
to main
, eventually culminating in a vM.N.1
(and so on) release.
Let release vM.N.P
denote the version that we are releasing.
When P
is equal to zero, we say that we are releasing a MINOR version of
Git LFS in the vM.N
-series, unless N
is also equal to zero, in which
case we are releasing a MAJOR version. Conversely, if P
is not equal
to zero, we are releasing a PATCH version.
-
First, we write the release notes and do the housekeeping required to indicate a new version. For a MAJOR or MINOR version, we start with a
main
branch which is up to date with the latest changes from the remote and then checkout a newrelease-next
branch from that base.If we are releasing a PATCH version, we create a
release-M.N
branch with cherry-picked merges from themain
branch, as described in the instructions below, and then checkout therelease-next
branch from that base.We next perform the following steps to prepare the
release-next
branch:-
Run
script/changelog
and categorize each merge commit as a feature, bug fix, miscellaneous change, or a change to be skipped and ignored. Ensure that your~/.netrc
credentials are up-to-date in order to make requests to the GitHub API, or use aGITHUB_TOKEN
environment variable.The
changelog
script will write a portion of the new CHANGELOG to stdout, which you should copy and paste intoCHANGELOG.md
, along with an H2-level heading containing the new version and the expected release date. This heading should be consistent with the exising style in the document.For a MAJOR release, use
script/changelog v(M-1).L.0...HEAD
, where(M-1)
is the previous MAJOR release number andL
is the final MINOR release number in that series. For a MINOR release, usescript/changelog vM.(N-1).0...HEAD
, where(N-1)
is the previous MINOR release number, and for a PATCH release, usescript/changelog --patch vM.N.(P-1)...HEAD
, where(P-1)
is the previous PATCH release number.-
Optionally write 1-2 paragraphs summarizing the release and calling out community contributions.
-
If we are releasing a MAJOR or MINOR version and not a PATCH, and if the most recent non-PATCH release was followed by a series of one or more PATCH releases, include any changes listed in the CHANGELOG of that series' release branch in the new release's CHANGELOG. (For a new MAJOR version, the prior release branch would be named
release-(M-1).L
, following the terminology defined above, while for a new MINOR version the prior release branch would be namedrelease-M.(N-1)
.)
-
-
Run
script/update-version vM.N.P
to update the version number in all of the relevant files. Note that this script requires a version ofsed(1)
compatible with the GNU implementation. -
Adjust the date in the
debian/changelog
entry to reflect the expected release date rather than the current date. -
Commit all the files changed in the steps above in a single new commit:
$ git commit -m 'release: vM.N.P'
-
-
Then, push the
release-next
branch and create a pull request with your changes from the branch. If you're building a MAJOR or MINOR release, set the base to themain
branch. Otherwise, set the base to therelease-M.N
branch.-
Add the
release
label to the PR. -
In the PR description, consider uploading builds for implementers to use in testing. These can be generated from a local tag, which does not need to be signed (but must be annotated). Check that the local version of Go is equivalent to the most recent one used by the GitHub Actions workflows for the release branch, which may be different from that used on the
main
branch. For a patch release in particular you may need to downgrade your local Go version. The build artifacts will be placed in thebin/releases
directory and may be uploaded into the PR from there:$ git tag -m vM.N.P-pre vM.N.P-pre $ make release $ ls bin/releases
-
Notify the
@git-lfs/releases
and@git-lfs/implementers
teams, collections of humans who are interested in Git LFS releases. -
Ensure that the normal Continuous Integration workflow for PRs that runs automatically in GitHub Actions succeeds fully.
-
As the GitHub Actions release workflow will not run for PRs, consider creating an annotated tag with the
-pre
suffix and pushing the tag, which will trigger a run of the release workflow that does not upload artifacts to Packagecloud. Alternatively, in a private clone of the repository, create such a tag from therelease-next
branch plus one commit to change the repository name inscript/upload
, and push the tag so Actions will run the release workflow. Ensure that the workflow succeeds (excepting the Packagecloud upload step, which will be skipped).
-
-
Once approved and verified, merge the pull request you created in the previous step. Locally, create a GPG-signed tag on the merge commit called
vM.N.P
:$ git show -q --pretty=%s%n%b HEAD Merge pull request #xxxx from git-lfs/release-next release: vM.N.P $ git tag -s vM.N.P -m vM.N.P $ git describe HEAD vM.N.P $ git show -q --pretty=%s%d%n%b vM.N.P tag vM.N.P Tagger: ... vM.N.P -----BEGIN PGP SIGNATURE----- ... -----END PGP SIGNATURE----- Merge pull request #xxxx from git-lfs/release-next (tag: vM.N.P) release: vM.N.P
-
Push the tag, via:
$ git push origin vM.N.P
This will kick off the process of building the release artifacts. This process will take somewhere between 45 minutes and an hour. When it's done, you'll end up with a draft release in the repository for the version in question.
-
From the command line, finalize the release process by signing the release:
$ script/upload --finalize vM.N.P
Note that this script requires GnuPG as well as Ruby (with the OpenSSL gem) and several other tools. You will need to provide your GitHub credentials in your
~/.netrc
file or via aGITHUB_TOKEN
environment variable.If you want to inspect the data before approving it, pass the
--inspect
option, which will drop you to a shell and let you look at things. If the shell exits successfully, the build will be signed; otherwise, the process will be aborted. -
Publish the release on GitHub, assuming it looks correct.
-
Move any remaining items out of the milestone for the current release to a future release and close the milestone.
-
Update the
_config.yml
file ingit-lfs/git-lfs.github.com
, similar to the following:--- _config.yml +++ _config.yml @@ -1,7 +1,7 @@ # Site settings title: "Git Large File Storage" description: "Git Large File Storage (LFS) replaces large files such as audio samples, videos, datasets, and graphics with text pointers inside Git, while storing the file contents on a remote server like GitHub.com or GitHub Enterprise." -git-lfs-release: M.(N-1).0 +git-lfs-release: M.N.0 url: "https://git-lfs.com"
-
Create a GitHub PR to update the Homebrew formula for Git LFS with the
brew bump-formula-pr
command on a macOS system. The SHA-256 value should correspond with the packaged artifact containing the new release's source files which is available at the given URL:$ brew tap homebrew/core $ brew bump-formula-pr \ --url https://github.com/git-lfs/git-lfs/releases/download/vM.N.P/git-lfs-vM.N.P.tar.gz \ --sha256 <SHA-256> \ git-lfs
When building a PATCH release, we cherry-pick merges from main
to the
vM.N
release branch, creating the branch first if it does not exist,
and then use that branch as the base for the PATCH release.
-
If the
release-M.N
branch does not already exist, create it from the corresponding MINOR release tag (or MAJOR release tag, if no MINOR releases have been made since the last MAJOR release):$ git checkout -b release-M.N vM.N.0
If the release branch already exists because this is not the first patch release for the given MINOR (or MAJOR) release, simply checkout the
release-M.N
branch, and ensure that you have the latest changes from the remote. -
Gather a set of potential candidates to backport to the
release-M.N
branch with:$ git log --merges --first-parent vM.N.(P-1)...main
-
For each merge that you want to backport, run:
$ git cherry-pick -m1 <SHA-1>
This will cherry-pick the merge onto your release branch, using the
-m1
option to specify that the first parent of the merge corresponds to the mainline. -
Then follow the guidelines above, using the
release-M.N
branch as the base for the new PATCH release.