First steps in semantic versioning
Tags: beginners, git, github
Published: 2022-03-01 16:25:49

### Relevant concepts

- **Commits:** They’re snapshots of your entire repository at specific times. You should make new commits often, based on logical units of change. Over time, commits should tell a story of the history of your repository and how it came to be the way that it currently is. The commits also includes a lot of metadata in addition to the contents and message, like the author, timestamp and more.

- **Tags:** They basically serve as a signed branch that does not permute, i.e. it always remains unchanged. It is simply an arbitrary string that points to a specific commit. A tag it’s like a name that you can use to mark a specific point in the history of a repository.

- **Releases:** They’re deployable software iterations you can package and make available for a wider audience to download and use. Releases are based on [Git tags](https://git-scm.com/book/en/Git-Basics-Tagging), which mark a specific point in your repository's history. A tag date may be different than a release date since they can be created at different times.

- **Pull Request:** They let you tell others about changes you've pushed to a branch in a repository on GitHub. Once a pull request is opened, you can discuss and review the potential changes with collaborators and add follow-up commits before your changes are merged into the base branch.


**Note:** The present article will be limited to explaining the meaning, usefulness, and functioning of semantic versioning; the concepts of tag and release will be explained lightly since they are not the current focus, they constitute the step that should be followed to apply semantic versioning.

Let's get started!

You have probably seen that in GitHub or GitLab projects there is a panel on the right side with a section called **Releases:**
![editorjs-undo-home-page](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2p0upkl970bglnoz9o1v.png)

If you click it, you’ll see the release information, something like this:
![editorjs-undo-current-release](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8f2mqjgjrqnlg5od7qw1.png)

So, do you know what v2.0.0-rc.0 means? Well, let's look at something else before proceeding, in the home page you will find the tags label:
![editorjs-undo-view-tags](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yel9j5k1sxznqaywl1x0.png)

Please click it, now you should see something like this:
![editorjs-undo-tags](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8v43bw4vu8gu8fxcdys9.png)

The first **tag** name matches the current **release** name. You’re now ready to understand its meaning. This notation is known as **semantic versioning** it refers to the version number of a project and It’s important because it says to you what changes could have been introduced in the code concerning the previous version.

As you can see, almost all tags are written in the **vX.Y.Z** format, with 3 numbers, and this is the semantic versioning core:

- X (Major): It indicates a drastic change in the code. It isn’t compatible with previous code versions.
- Y (Minor): It indicates a feature addition or feature modification, but the current code is compatible with the previous versions. Also is used when it’s necessary to mark something as deprecated.
- Z (Patch): Generally, it’s used to fix bugs, and still is compatible with the previous code versions.

Now, how can you apply this if, for example, you are starting a project? It’s pretty simple. Let’s go to do a practical example:

1. We’re going to create a repo in GitHub, you can name it whatever you want.
![create-repo-github](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yxdk4w5opo0vwsynuuvo.png)

2. The repo had been created. If you look closely, you will see that there is only one branch, the **main** branch.
![repo-github-main](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8atsbk2cevaijl2c1yo2.png)
    
3. Before beginning to create commits, we need to create another branch (remember that it isn’t a good practice to send changes directly to the main branch). Then let's create the **v0.1** branch (is actually **v0.1.0**, but when **Z** is zero, we can omit it from the branch name).
![repo-github-branches](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7jzqejusxma12e4irkvn.png)
    
    Well, this is a good point to explain additional adjusts:
    
    a. All branches must be created from the main branch.
    b. The **v0.1** branch is used because will be the first release, and probably not a stable version, it will need more adjusts.
    c. All tags between **1.0.0** and **1.9.9** should be contained in the **v1.0.0** (or **v1.0**) branch, all tags between **2.0.0** and **2.9.9** should be contained in the **v2.0.0** (or **v2.0**) branch, and so on.
    d. Probably the **v0.1** branch will have only one tag, the **v0.1**, and this is right because is our first version, so we’re implementing the initial functionality of the project.
    e. When the changes introduced in the current branch are ready, you must create a **PR** to merge with the **main** branch.

4. Now, we’re going to [create **commits**](https://github.com/git-guides/git-commit) implementing the transactional system features:

    a. Install the initial project configuration and its dependencies.
    b. Add the login/signup component.
    c. Implement the allowed transactions.
    d. Add the user roles.
    e. Limit the user permissions.
    f. Implement a public dashboard to display transactions in real-time.
    g. Implement methods to ensure transaction integrity.
    
    Now, in the v0.1 branch we have the previous commits:
    ![repo-github-with-new-commits](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zt1abi8xhrislrji5qlp.png)
    ![repo-github-commits](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o6a6x9puhulb95qacp73.png)

5. As these features will be our first project version, let’s [create the tag](https://git-scm.com/book/en/v2/Git-Basics-Tagging) with its version number, in this case, we’ll create the v0.1 tag to establish the project version.
    ```bash
    git tag -a v0.1 -m "Initial release"

    git push origin --tags
    ```


    If you see the GitHub repo, now there’s a tag, the one we just created.
    ![repo-github-view-tags](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/in5xaki66zqyq825tdan.png)
    ![repo-github-tags](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7ndykgova96s3whvkyk9.png)

6. With this first version, we can [create the **PR**](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request) to merge the **v0.1** branch with the **main** branch:
    ![repo-github-create-pr](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ir7yhrkhvpi9s2jck09f.png)

7. Now, if you return to the **main** branch, you’ll see something like the following, so let’s create our first release.
    ![repo-github-releases](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/spuhyr03ooeyzztxvdyj.png)
    ![repo-github-create-releases](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1qht4ufjt0v67mj6ut2b.png)

The process to create new tags and publish releases is very similar to the one seen above, e.g., if we wanted to solve a security problem in version **0.1**, we would create commits to solve it on the **v0.1** branch, then we could create the **v0.1.1** tag, create again a PR to merge with the main branch and finally create the release with this version more stable than the previous one.

In some projects, you can see releases like **v1.0.3-alpha**, **v1.0.3-beta.** Do you know what is this? These additional words are stability indicators, and they use greek letters, so alpha < beta, i.e., beta is more stable than alpha.

In some projects, release candidates are also used, which are branches that are sufficiently solid, or that want to establish enough solidity when the release is created (which will probably be used by end-users), it will have as few errors as possible.

Surely this is not the only way to use semantic versioning in projects, so far I think it is a good way to do it and it’s easy to understand and share, there may be better ways to do it so, why don't you tell me how you do it or what you would improve to the current one?

📔 This information may be of interest to you:

- [Continuous Deployment with Semantic Release and GitHub Actions](https://www.wizeline.com/blog-continuous-deployment-with-semantic-release-and-github-actions/)
- [semantic-release](https://github.com/semantic-release/semantic-release)
- [Semantic versioning](https://semver.org/)
- [About releases](https://docs.github.com/en/repositories/releasing-projects-on-github/about-releases)