1 |
--- |
2 |
title: Version Control System (VCS) Guide |
3 |
short_name: VCS Guide |
4 |
--- |
5 |
|
6 |
# Version Control System (VCS) Guide |
7 |
|
8 |
Version Control Systems (VCS) are extremely important tools for managing |
9 |
codebases, tracking changes, and collaborating with other developers. This guide |
10 |
provides an overview of VCS concepts, common workflows, and best practices that |
11 |
we follow at OSN. |
12 |
**This is not a tutorial on how to use Git or SVN, but rather a |
13 |
guide on what standards we follow at OSN.** |
14 |
|
15 |
## What VCS do we use? |
16 |
|
17 |
At OSN, we prefer using Git as our primary VCS. Git is a modern, distributed VCS |
18 |
that is widely used in the industry. For more information, |
19 |
[refer here](https://git-scm.com/). |
20 |
|
21 |
We also use Subversion (SVN) for some of our projects. SVN is a centralized VCS |
22 |
that used to be popular before Git. It usually does not have as many features as |
23 |
Git, but it is still widely used in some organizations. For more information, |
24 |
[refer here](https://subversion.apache.org/). |
25 |
|
26 |
We use [GitHub](https://github.com) as our Git hosting platform. |
27 |
As for SVN, we have our own SVN server: |
28 |
[svn.onesoftnet.eu.org](https://svn.onesoftnet.eu.org). |
29 |
|
30 |
## Introduction to Semantic Versioning |
31 |
|
32 |
Semantic Versioning (Semver) is a versioning scheme that is widely used in the |
33 |
software industry. It is a simple set of rules and requirements that dictate how |
34 |
version numbers are assigned and incremented. The format is as follows: |
35 |
|
36 |
``` |
37 |
MAJOR.MINOR.PATCH |
38 |
``` |
39 |
|
40 |
1. **MAJOR**: Incremented when you make incompatible API changes. |
41 |
2. **MINOR**: Incremented when you add functionality in a backwards-compatible |
42 |
manner. |
43 |
3. **PATCH**: Incremented when you make backwards-compatible bug fixes. |
44 |
|
45 |
For more information, [refer here](https://semver.org/). |
46 |
|
47 |
**OSN Projects follow a superset of Semver**. |
48 |
In addition to the rules described |
49 |
in [Semver](https://semver.org/), we also have the following rules: |
50 |
|
51 |
1. **Pre-release versions**: We use the `-alpha`, `-beta`, and `-rc` suffixes |
52 |
for pre-release versions. For example, `1.0.0-alpha.1`, `1.0.0-beta.1`, |
53 |
`1.0.0-rc.1`. Each of these suffixes have specific meanings: |
54 |
|
55 |
- `-alpha`: This is the first stage of the release cycle. It is used for |
56 |
initial testing and feedback, when features are still being added. |
57 |
|
58 |
- `-beta`: This is the second stage of the release cycle. It is used for |
59 |
feature complete testing and feedback. |
60 |
|
61 |
- `-rc`: This is the third stage of the release cycle. It is used for |
62 |
final testing and feedback before the final release. |
63 |
|
64 |
2. **Build metadata**: We use the `+` suffix for build metadata. For example, |
65 |
`1.0.0+exp.sha.5114f85`. This can be used to identify the build number, commit |
66 |
hash, or any other build-related information. |
67 |
We usually only use this for internal builds, however it can be used for |
68 |
public releases as well, if needed.<br /> |
69 |
We use the following formats for build metadata: |
70 |
|
71 |
- `exp`: Experimental build: This is usually used for internal builds |
72 |
that are not meant for public release. |
73 |
- `sha`: Commit hash: This is used to identify the commit hash of the |
74 |
build. |
75 |
- `build`: Build number: This is used to identify the build number of |
76 |
the build. |
77 |
|
78 |
You can either use all of these formats or only some of them, depending on |
79 |
your requirements. When combining multiple formats, separate them with a |
80 |
dot (`.`). For example, `1.0.0+exp.sha.5114f85.build.123`. |
81 |
|
82 |
3. **Exceptions for security patches**: We use the `PATCH` version for |
83 |
security patches. However, if the security issue is severe (>= 8.0 in |
84 |
[CVSS](https://www.first.org/cvss/calculator/3.1)), we increment the |
85 |
`MAJOR` version. For example, if the current version is `1.0.0`, and |
86 |
a security patch is released, the new version will be `1.0.1`. If the |
87 |
security issue is severe, the new version will be `2.0.0`. |
88 |
This helps users to quickly identify the severely affeted version and |
89 |
the version with the security patch. |
90 |
|
91 |
## Conventional Commits |
92 |
|
93 |
Conventional Commits is a specification for adding human and machine readable |
94 |
meaning to commit messages. It is a simple set of rules for creating an explicit |
95 |
commit history. For information, see the |
96 |
[Conventional Commits specification](https://www.conventionalcommits.org/). |
97 |
|
98 |
We follow a superset of the Conventional Commits specification. The advantage of |
99 |
this is that it helps in generating release notes, changelogs, and automating |
100 |
the creation of new releases. |
101 |
|
102 |
#### Commit Scope Format |
103 |
|
104 |
When making commits, please specify a scope for the commit. The scope should be |
105 |
the name of the module or component that you are working on. For example: |
106 |
|
107 |
```git-commit |
108 |
feat(kernel): add new feature |
109 |
``` |
110 |
|
111 |
In this example, `kernel` is the module or component that the commit is related |
112 |
to. You might also divide the scope into multiple parts, separated by a colon |
113 |
(`:`) to indicate submodules or subcomponents. For example: |
114 |
|
115 |
```git-commit |
116 |
feat(kernel:core): add new feature |
117 |
``` |
118 |
|
119 |
In this example, `kernel` is the main module and `core` is a submodule of the |
120 |
`kernel` module. |
121 |
|
122 |
#### Additional commit types |
123 |
|
124 |
Our superset defines the following additional commit types: |
125 |
|
126 |
1. **`release`**: This commit type is used for release commits. It is used to |
127 |
indicate that a new version has been released. For example: <br /> |
128 |
|
129 |
```git-commit |
130 |
release: v1.0.0 [skip ci] |
131 |
``` |
132 |
|
133 |
The `[skip ci]` tag is used to indicate that this commit should not trigger |
134 |
a CI build. |
135 |
|
136 |
2. **`deps`**: This commit type is used for dependency updates. It is used to |
137 |
indicate that a dependency has been updated. For example: <br /> |
138 |
|
139 |
```git-commit |
140 |
deps: update dependencies |
141 |
``` |
142 |
|
143 |
This commit type may have a subject. The subject is usually `dev` to indicate |
144 |
a development dependency update, or maybe a specific package name to indicate |
145 |
a specific dependency update. For example: <br /> |
146 |
|
147 |
```git-commit |
148 |
deps(dev): update dev dependencies |
149 |
``` |
150 |
|
151 |
In addition to the rules described in the original Conventional Commits |
152 |
specification, we also have the following rules: |
153 |
|
154 |
1. **Always use `BREAKING CHANGE` in the commit message if there are |
155 |
breaking changes**: If you make a change that breaks backward |
156 |
compatibility, always use the `BREAKING CHANGE` keyword in the commit |
157 |
message and then provide information about the change. |
158 |
This helps users to quickly identify the breaking changes in |
159 |
the release notes. This also helps in identifying the `MAJOR` version |
160 |
bump in the release notes, whether it is a security patch or a breaking |
161 |
change. For example: <br /> |
162 |
|
163 |
```git-commit |
164 |
feat(kernel:core)!: add new feature |
165 |
|
166 |
BREAKING CHANGE: This commit breaks backward compatibility. |
167 |
``` |
168 |
|
169 |
The `!` symbol is used to indicate that this commit is a starting point |
170 |
of a new major version, according to the Semver specification. |
171 |
|
172 |
2. **Always use `SECURITY` in the commit message for security patches**: |
173 |
If you make a security patch, always use the `SECURITY` keyword in the |
174 |
commit message and then provide information about the security issue. |
175 |
This helps users to quickly identify the security patches in the release |
176 |
notes. For example: <br /> |
177 |
|
178 |
```git-commit |
179 |
fix(kernel:core)!: fix security issue |
180 |
|
181 |
SECURITY: This commit fixes a security issue. |
182 |
``` |
183 |
|
184 |
3. **Always use `DEPRECATED` in the commit message for deprecated features**: |
185 |
If you deprecate a feature, always use the `DEPRECATED` keyword in the |
186 |
commit message and then provide information about the deprecation. |
187 |
This helps users to quickly identify the deprecated features in the |
188 |
release notes. The commit type should be `feat` in this case. |
189 |
For example: <br /> |
190 |
|
191 |
```git-commit |
192 |
feat(kernel:core)!: deprecate old feature |
193 |
|
194 |
DEPRECATED: This commit deprecates an old feature. |
195 |
``` |
196 |
|
197 |
4. **Use the `release` commit type for release commits**: If you are making |
198 |
a release commit, always use the `release` commit type, as described |
199 |
[above](#additional-commit-types). |
200 |
|
201 |
5. **Use the `deps` commit type for dependency updates**: If you are making |
202 |
a dependency update, always use the `deps` commit type, as described |
203 |
[above](#additional-commit-types). |
204 |
|
205 |
## Branching Strategy |
206 |
|
207 |
We follow the an extended version of the |
208 |
[GitHub Flow](https://guides.github.com/introduction/flow/) workflow. |
209 |
Thee only main branch is `main` — this is the branch that is always |
210 |
deployed to production. Notable development works are done in feature branches, |
211 |
which are then merged into the `main` branch via pull requests. |
212 |
If the feature or fix you're working on is small, you can commit directly to the |
213 |
`main` branch. |
214 |
|
215 |
We also have the following additional branches: |
216 |
|
217 |
1. **Release Branches**: We create release branches for each major version. For |
218 |
example, if the current version is `1.0.0`, the release branch will be |
219 |
`1.x`. This branch is used for bug fixes and security patches for |
220 |
that specific version without merging them into the `main` branch. Once all |
221 |
the bug fixes and security patches are done, we create a new release from |
222 |
this branch. |
223 |
|
224 |
After the release reaches its EOL (End of Life), we archive the branch and |
225 |
stop providing support for that version. |
226 |
|
227 |
2. **Bugfix Branches**: We create bugfix branches for working on a notable bug |
228 |
fix or security patch. These branches are created from the `main` branch and |
229 |
are merged back into the `main` branch via pull requests. |
230 |
These branches are prefixed by `fix/`. |
231 |
|
232 |
3. **Feature Branches**: We create feature branches for working on new features. |
233 |
These branches are created from the `main` branch and are merged back into |
234 |
the `main` branch via pull requests. |
235 |
These branches are prefixed by `feat/`. |
236 |
|
237 |
## Automation of Releases and Changelog Generation |
238 |
|
239 |
We use GitHub Actions for automating the release process and generating |
240 |
changelogs. We have a custom GitHub Action that automatically generates |
241 |
changelogs based on the commit messages and creates a new release on GitHub. |
242 |
The action is available on GitHub marketplace: |
243 |
[Conventional Release Action](https://github.com/marketplace/actions/conventional-release-action). |
244 |
|
245 |
The action uses the commit messages to generate the changelog and release notes, |
246 |
and then bumps the version number based on the commit messages and the rules |
247 |
of our superset of the Conventional Commits specification and Semver. |
248 |
|
249 |
#### Tips to leaverage the action |
250 |
|
251 |
1. **Forcing pre-release versions**: If you want to force a pre-release version, |
252 |
you can use a prerelease specifier in your commit message. For example: <br /> |
253 |
|
254 |
```git-commit |
255 |
feat(kernel:core): add new feature [prerelease] |
256 |
``` |
257 |
|
258 |
The identifier must be inside square brackets (`[]`) and must be one of |
259 |
`prerelease`, `alpha`, `beta`. This will force the action to bump the |
260 |
version to a pre-release version. |
261 |
|
262 |
2. **Forcing build metadata**: If you want to force build metadata, you can use |
263 |
add the `Build-metadata` footer in your commit message. For example: <br /> |
264 |
|
265 |
```git-commit |
266 |
feat(kernel:core): add new feature |
267 |
|
268 |
Build-metadata: exp.sha.5114f85.build.123 |
269 |
``` |
270 |
|
271 |
This will force the action to add the build metadata to the version. |
272 |
|
273 |
3. **Forcing a specific version suffix**: If you want to force a specific version |
274 |
suffix, you can use the `Version-suffix` footer in your commit message. For |
275 |
example: <br /> |
276 |
|
277 |
```git-commit |
278 |
feat(kernel:core): add new feature |
279 |
|
280 |
Version-suffix: -alpha.1 |
281 |
``` |
282 |
|
283 |
This will force the action to use the specified version suffix. |
284 |
|
285 |
## Signing off commits and using GPG signatures |
286 |
|
287 |
We require developers to sign off their commits and optionally use GPG |
288 |
signatures for signing commits. |
289 |
Please note that "signing off" and "GPG signing" are two different things. |
290 |
|
291 |
1. **Signing off commits**: When you make a commit, you must sign off the commit |
292 |
by adding a `Signed-off-by` line at the end of the commit message. This is |
293 |
usually done by adding `Signed-off-by: Your Name <youremail@addr.com>`. This |
294 |
is a way to certify that you have the rights to submit the code under the |
295 |
project's license. For example: <br /> |
296 |
|
297 |
```git-commit |
298 |
feat(kernel:core): add new feature |
299 |
|
300 |
Signed-off-by: John Doe <johndoe@acme.com> |
301 |
``` |
302 |
|
303 |
If you're using the Git CLI, you can add the `-s` flag to automatically add |
304 |
the `Signed-off-by` line. For example: <br /> |
305 |
|
306 |
```bash |
307 |
git commit -sm "feat(kernel:core): add new feature" |
308 |
``` |
309 |
|
310 |
This is a good practice to follow, especially when contributing to open |
311 |
source projects. |
312 |
|
313 |
2. **Using GPG signatures**: GPG signatures are used to sign commits and tags. |
314 |
This is a way to certify that the commit or tag was made by you and not by |
315 |
someone else. This is especially useful for verifying the authenticity of |
316 |
commits and tags in open source projects. For more information on how to |
317 |
use GPG signatures with Git, see the |
318 |
[GitHub documentation](https://docs.github.com/en/github/authenticating-to-github/managing-commit-signature-verification). |
319 |
GitHub shows a "Verified" badge next to commits and tags that are signed with |
320 |
GPG signatures. |