1 |
rakinar2 |
627 |
--- |
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 <[email protected]>`. 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 <[email protected]> |
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. |