-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Post: My branching/tagging strategy for packages (#34)
- Loading branch information
1 parent
7e46ad8
commit 4941ed3
Showing
1 changed file
with
110 additions
and
0 deletions.
There are no files selected for viewing
110 changes: 110 additions & 0 deletions
110
source/_posts/tagging-and-branching-strategy-for-libraries-and-packages.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
--- | ||
title: My branching/tagging strategy for packages | ||
date: 2023-08-11 | ||
excerpt: How I manage branches and tags for the PHP packages I've published | ||
extends: _layouts.post | ||
section: body | ||
--- | ||
|
||
I've never had a very good grasp on how I should branch my open source libraries. There are a lot of resources out there | ||
detailing how to branch and tag _projects_ ([git-flow](https://nvie.com/posts/a-successful-git-branching-model/), | ||
[GitHub flow](https://docs.github.com/en/get-started/quickstart/github-flow), | ||
[Trunk based development](https://trunkbaseddevelopment.com), ...), but these don't map very well to distributed | ||
libraries. | ||
|
||
This is the blog post I wish I had when I was searching for a good workflow for branching and tagging open source | ||
packages/libraries. | ||
|
||
## My strategy | ||
This workflow is similar to what I've observed other packages/libraries/frameworks follow. It is not meant to be a | ||
definitive guide to how _you_ should do it, but serves mainly as a reminder and guide for _myself_. Ok, let's dive in. | ||
|
||
### Initial development | ||
First off, every repository has a `main` branch. This is always the _next_ major version of the library, and therefore | ||
also where all the development happens _before_ a version is tagged. | ||
|
||
### Tagging the first version | ||
When you're ready to tag your first major version (`v1.0.0`), first create a branch called `1.x`. This is where you'll | ||
then tag your first version from. | ||
|
||
```sh | ||
$ git switch main | ||
$ git pull origin main | ||
$ git switch -c 1.x | ||
$ git push origin 1.x | ||
$ git tag -s v1.0.0 -m 'Version 1.0.0' | ||
$ git push origin v1.0.0 | ||
``` | ||
|
||
Be sure to also [make `1.x` the default branch on GitHub](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-branches-in-your-repository/changing-the-default-branch). | ||
From this point on, `main` is for `v2.0.0` development. I would now also _stop_ directly committing to any of these | ||
branches and work via pull requests instead. These pull requests most often target `1.x`, and are ported over to `main`. | ||
|
||
For instance, say you have a new feature _without breaking changes_ in the works. The pull request for this feature will | ||
target `1.x` so it lands in `v1.1.0`. Once approved and merged into `1.x`, you'd merge that change into `main`: | ||
|
||
```sh | ||
$ git switch 1.x | ||
$ git pull origin 1.x | ||
$ git switch main | ||
$ git pull origin main | ||
$ git merge 1.x --ff-only | ||
$ git push origin main | ||
``` | ||
|
||
> You could also facilitate this merge from the GitHub UI by using the "compare" page. Append `/compare/main...1.x` to | ||
> your repository's URL, and you'll see a button to create a pull request to merge the changes from `1.x` into `main`. | ||
### Tagging new minor and patch versions | ||
Once `v1.1.0` is ready to be released, tag it from the `1.x` branch: | ||
|
||
```sh | ||
$ git switch 1.x | ||
$ git pull origin 1.x | ||
$ git tag -s v1.1.0 -m 'Version 1.1.0' | ||
$ git push origin v1.1.0 | ||
``` | ||
|
||
### Two point oh and beyond | ||
When you introduce a breaking change in one of your pull requests, you should target it to the `main` branch. The moment | ||
you're ready to tag `v2.0.0`, you create a new `2.x` branch and tag the next major version from there. This is pretty | ||
much the same as [tagging the first version](#tagging-the-first-version). | ||
|
||
```sh | ||
$ git switch main | ||
$ git pull origin main | ||
$ git switch -c 2.x | ||
$ git tag -s v2.0.0 -m 'Version 2.0.0' | ||
$ git push origin v2.0.0 | ||
``` | ||
|
||
> **Remember to also [update the default branch](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-branches-in-your-repository/changing-the-default-branch) | ||
> to `2.x` at this point.** | ||
### Bug fixes for previous versions | ||
If a bug fix comes in that should be applied to `2.x` _and_ `1.x` (or other previous versions), it should be targeted to | ||
the latest branch where the bug is present. I will assume `2.x` in this case. Once the bug fix is merged into `2.x`, you | ||
can _cherry-pick_ the commit(s) into the other affected version(s): | ||
|
||
```sh | ||
$ git switch 2.x | ||
$ git pull origin 2.x | ||
$ git switch 1.x | ||
$ git cherry-pick <commit sha> | ||
# Or, if you want to cherry-pick multiple commits: | ||
# git cherry-pick <first commit>^..<last commit> | ||
$ git push origin 1.x | ||
$ git tag -s v1.x.y -m 'Version 1.x.y' # Where 'y' is incremented | ||
$ git push origin v1.x.y | ||
$ git switch main | ||
``` | ||
|
||
## The alternative | ||
I considered a strategy where the `main` branch is always the _current_ latest version, but that resulted in more | ||
forgettable administrative work. Besides, what I outlined above is actually what Laravel does (as far as I could infer), | ||
and it's similar to [what Symfony follows](https://symfony.com/doc/current/contributing/code/pull_requests.html#choose-the-right-branch). | ||
So we're in good company. | ||
|
||
## Conclusion | ||
I hope now that I've written this down, I can actually follow this in my own projects. This should ease the process of | ||
contributing to my packages, and help me in being less confused when I need to tag a new release. |