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 |
3. **`merge`**: If you perform a merge, use this commit type. When using the |
151 |
`git merge` command, you can pass the `-m` option and a commit message as |
152 |
an argument. Sometimes git can choose to not perform a merge commit and instead |
153 |
perform a "fast-forward" merge. In that case, there will be no additional commit, |
154 |
and therefore the message will be ignored. In other cases when Git creates a new commit, |
155 |
the commit message will be used.<br /> |
156 |
Example:<br /> |
157 |
|
158 |
```bash |
159 |
git merge feature/new-permission-system -m "merge: feature/new-permission-system branch to main" |
160 |
``` |
161 |
4. **`i18n`**: This commit type is used when you add translations or make changes |
162 |
that affect the internationalization of the bot. |
163 |
|
164 |
In addition to the rules described in the original Conventional Commits |
165 |
specification, we also have the following rules: |
166 |
|
167 |
1. **Always use `BREAKING CHANGE` in the commit message if there are |
168 |
breaking changes**: If you make a change that breaks backward |
169 |
compatibility, always use the `BREAKING CHANGE` keyword in the commit |
170 |
message and then provide information about the change. |
171 |
This helps users to quickly identify the breaking changes in |
172 |
the release notes. This also helps in identifying the `MAJOR` version |
173 |
bump in the release notes, whether it is a security patch or a breaking |
174 |
change. For example: <br /> |
175 |
|
176 |
```git-commit |
177 |
feat(kernel:core)!: add new feature |
178 |
|
179 |
BREAKING CHANGE: This commit breaks backward compatibility. |
180 |
``` |
181 |
|
182 |
The `!` symbol is used to indicate that this commit is a starting point |
183 |
of a new major version, according to the Semver specification. |
184 |
|
185 |
2. **Always use `SECURITY` in the commit message for security patches**: |
186 |
If you make a security patch, always use the `SECURITY` keyword in the |
187 |
commit message and then provide information about the security issue. |
188 |
This helps users to quickly identify the security patches in the release |
189 |
notes. For example: <br /> |
190 |
|
191 |
```git-commit |
192 |
fix(kernel:core)!: fix security issue |
193 |
|
194 |
SECURITY: This commit fixes a security issue. |
195 |
``` |
196 |
|
197 |
3. **Always use `DEPRECATED` in the commit message for deprecated features**: |
198 |
If you deprecate a feature, always use the `DEPRECATED` keyword in the |
199 |
commit message and then provide information about the deprecation. |
200 |
This helps users to quickly identify the deprecated features in the |
201 |
release notes. The commit type should be `feat` in this case. |
202 |
For example: <br /> |
203 |
|
204 |
```git-commit |
205 |
feat(kernel:core)!: deprecate old feature |
206 |
|
207 |
DEPRECATED: This commit deprecates an old feature. |
208 |
``` |
209 |
|
210 |
4. **Use the `release` commit type for release commits**: If you are making |
211 |
a release commit, always use the `release` commit type, as described |
212 |
[above](#additional-commit-types). |
213 |
|
214 |
5. **Use the `deps` commit type for dependency updates**: If you are making |
215 |
a dependency update, always use the `deps` commit type, as described |
216 |
[above](#additional-commit-types). |
217 |
|
218 |
## Branching Strategy |
219 |
|
220 |
We follow the an extended version of the |
221 |
[GitHub Flow](https://guides.github.com/introduction/flow/) workflow. |
222 |
The only main branch is `main` — this is the branch that is always |
223 |
deployed to production. Notable development works are done in feature branches, |
224 |
which are then merged into the `main` branch via pull requests. |
225 |
If the feature or fix you're working on is small, you can commit directly to the |
226 |
`main` branch. |
227 |
|
228 |
We also have the following additional branches: |
229 |
|
230 |
1. **Release Branches**: We create release branches for each major version. For |
231 |
example, if the current version is `1.0.0`, the release branch will be |
232 |
`1.x`. This branch is used for bug fixes and security patches for |
233 |
that specific version without merging them into the `main` branch. Once all |
234 |
the bug fixes and security patches are done, we create a new release from |
235 |
this branch. |
236 |
|
237 |
After the release reaches its EOL (End of Life), we archive the branch and |
238 |
stop providing support for that version. |
239 |
|
240 |
2. **Bugfix Branches**: We create bugfix branches for working on a notable bug |
241 |
fix or security patch. These branches are created from the `main` branch and |
242 |
are merged back into the `main` branch via pull requests. |
243 |
These branches are prefixed by `bugfix/`. |
244 |
|
245 |
3. **Feature Branches**: We create feature branches for working on new features. |
246 |
These branches are created from the `main` branch and are merged back into |
247 |
the `main` branch via pull requests. |
248 |
These branches are prefixed by `feature/`. |
249 |
|
250 |
## Automation of Releases and Changelog Generation |
251 |
|
252 |
We use GitHub Actions for automating the release process and generating |
253 |
changelogs. We have a custom GitHub Action that automatically generates |
254 |
changelogs based on the commit messages and creates a new release on GitHub. |
255 |
The action is available on GitHub marketplace: |
256 |
[Conventional Release Action](https://github.com/marketplace/actions/conventional-release-action). |
257 |
|
258 |
The action uses the commit messages to generate the changelog and release notes, |
259 |
and then bumps the version number based on the commit messages and the rules |
260 |
of our superset of the Conventional Commits specification and Semver. |
261 |
|
262 |
#### Tips to leaverage the action |
263 |
|
264 |
1. **Forcing pre-release versions**: If you want to force a pre-release version, |
265 |
you can use a prerelease specifier in your commit message. For example: <br /> |
266 |
|
267 |
```git-commit |
268 |
feat(kernel:core): add new feature [prerelease] |
269 |
``` |
270 |
|
271 |
The identifier must be inside square brackets (`[]`) and must be one of |
272 |
`prerelease`, `alpha`, `beta`. This will force the action to bump the |
273 |
version to a pre-release version. |
274 |
|
275 |
2. **Forcing build metadata**: If you want to force build metadata, you can use |
276 |
add the `Build-metadata` footer in your commit message. For example: <br /> |
277 |
|
278 |
```git-commit |
279 |
feat(kernel:core): add new feature |
280 |
|
281 |
Build-metadata: exp.sha.5114f85.build.123 |
282 |
``` |
283 |
|
284 |
This will force the action to add the build metadata to the version. |
285 |
|
286 |
3. **Forcing a specific version suffix**: If you want to force a specific version |
287 |
suffix, you can use the `Version-suffix` footer in your commit message. For |
288 |
example: <br /> |
289 |
|
290 |
```git-commit |
291 |
feat(kernel:core): add new feature |
292 |
|
293 |
Version-suffix: -alpha.1 |
294 |
``` |
295 |
|
296 |
This will force the action to use the specified version suffix. |
297 |
|
298 |
## Signing off commits and using GPG signatures |
299 |
|
300 |
We require developers to sign off their commits and optionally use GPG |
301 |
signatures for signing commits. |
302 |
Please note that "signing off" and "GPG signing" are two different things. |
303 |
|
304 |
1. **Signing off commits**: When you make a commit, you must sign off the commit |
305 |
by adding a `Signed-off-by` line at the end of the commit message. This is |
306 |
usually done by adding `Signed-off-by: Your Name <[email protected]>`. This |
307 |
is a way to certify that you have the rights to submit the code under the |
308 |
project's license. For example: <br /> |
309 |
|
310 |
```git-commit |
311 |
feat(kernel:core): add new feature |
312 |
|
313 |
Signed-off-by: John Doe <[email protected]> |
314 |
``` |
315 |
|
316 |
If you're using the Git CLI, you can add the `-s` flag to automatically add |
317 |
the `Signed-off-by` line. For example: <br /> |
318 |
|
319 |
```bash |
320 |
git commit -sm "feat(kernel:core): add new feature" |
321 |
``` |
322 |
|
323 |
This is a good practice to follow, especially when contributing to open |
324 |
source projects. |
325 |
|
326 |
2. **Using GPG signatures**: GPG signatures are used to sign commits and tags. |
327 |
This is a way to certify that the commit or tag was made by you and not by |
328 |
someone else. This is especially useful for verifying the authenticity of |
329 |
commits and tags in open source projects. For more information on how to |
330 |
use GPG signatures with Git, see the |
331 |
[GitHub documentation](https://docs.github.com/en/github/authenticating-to-github/managing-commit-signature-verification). |
332 |
GitHub shows a "Verified" badge next to commits and tags that are signed with |
333 |
GPG signatures. |