Lately I've been doing a lot of thinking around versioning in repositories. For all the convenience and ubiquity of package.json
, it does sometimes misrepresent the code that is contained within a repository. For example, suppose I start out my project at v0.1.0 and that's what's in my package.json
file in my master branch. Then someone submits a pull request that I merge in - the version number hasn't changed even though the repository now no longer represents v0.1.0. The repository is actually now in an intermediate state, in between v0.1.0 and the next official release.
To deal with that, I started changing the package.json
version only long enough to push a new release, and then I would change it to a dev version representing the next scheduled release (such as v0.2.0-dev). That solved the problem of misrepresenting the version number of the repository (provided people realize "dev" means "in flux day to day"). However, it introduced a yucky workflow that I really hated. When it was time for a release, I'd have to:
- Manually change the version in
package.json
. - Tag the version in the repo.
- Publish to npm.
- Manually change the version in
package.json
to a dev version. - Push to master.
There may be some way to automate this, but I couldn't figure out a really nice way to do it.
That process works well enough when you have no unplanned releases. However, what if I'm working on v0.2.0-dev after v0.1.0 was released, and need to do a v0.1.1 release? Then I need to:
- Note the current dev version.
- Manually change the version to v0.1.1.
- Tag the version in the repo.
- Publish to npm.
- Change the version back to the same version from step 1.
- Push to master.
Add on top of this trying to create an automated changelog based on tagging, and things can get a little bit tricky.
My next thought was to have a release branch where the last published release would live. Essentially, after v0.1.0, the release branch remains at v0.1.0 while the master branch becomes v0.2.0-dev. If I need to do an intermediate release, then I merge master onto release and change versions only in the release branch. Once again, this is a bit messy because package.json
is guaranteed to have different versions on master and release, which always causes merge conflicts. This also means the changelog is updated only in the release branch. This solution turned out to be more complex than I anticipated.
I'm still not sure the right way to do this, but my high-level requirements are:
- Make sure the version in
package.json
is always accurate. - Don't require people to change the version to make a commit.
- Don't require people to use a special build command to make a commit.
- Distinguish between development (in progress) work vs. official releases.
- Be able to auto-increment the version number (via
npm version
).
How about you? How do you deal with versions in your repository?
I keep master as my stable branch; it will always have the latest proper git tag and package.json version. If I am developing features on the side, I leave them in a branch until they are ready to be released.
If people are eager to contribute to the development branch, they can use a git reference to the branch
or
git clone + npm link
.I would also add that small, frequent releases are another way around this problem; no large features build up and branches have very short life cycles.