Conventional commits

Conventional commits Conventional commits

Conventional commitslink image 15

Disclaimer: This post has been translated to English using a machine translation model. Please, let me know if you find any mistakes.

This post has been created from the video by Carlos Azaustre, only that since he explains how to do everything with JavaScript tools, there are many Python developers who do not have Node.js installed, so I have made a version of it but entirely with Python tools.

What are conventional commits?link image 16

integration with change and release management tools.

Commit Message Formatlink image 17

A commit message in Conventional Commits follows a specific format:

git<type>[optional
      [optional body]
      [optional footer(s)]```

Let's look at it in more detail

Type typelink image 18

The commit type indicates the nature of the change. Some common types are:

  • fix: Used for bug fixes.* feat: Used for new features. * docs: Used for documentation changes.* style: Used for changes that do not affect the meaning of the code (e.g., formatting, removing white spaces). * refactor: It is used for code changes that neither improve nor degrade functionality, such as reorganizing the code. * perf: Used for changes that improve performance.* test: Used to add or update tests. * chore: Used for changes in the process or development tools.* ci: Used for changes in continuous integration configuration files. * build: Used for changes that affect the build system or external dependencies. * revert: It is used to revert a previous commit.

Scope scopelink image 19

The scope is optional and is used to specify the part of the project that was modified. For example, if you are working on a specific component of a web application, the scope could be the name of the component. Example:

gitfix(auth):
      

Description descriptionlink image 20

The description is a brief explanation of the change. It should be concise and clear, and provide enough context to understand the purpose of the commit. Example:

git
      fix(auth): fix authentication error on login page```

Body bodylink image 21

The body is optional and is used to provide more details about the change. Here you can include motivations for the change and contrasts with the previous implementation. Example:

git
      fix(auth): fix authentication error on login page
      El token de acceso expiraba antes de lo esperado debido a un error en el cálculo de la fecha de expiración. Se ha solucionado ajustando la lógica de cálculo.

The footer is optional and is used for additional references, such as closed issue numbers or related commits. Example:

gitfix(auth):
      El token de acceso expiraba antes de lo esperado debido a un error en el cálculo de la fecha de expiración. Se ha corregido ajustando la lógica de cálculo.
      Closes #123```

Benefits of Conventional Commitslink image 23

  • Clarity and Consistency: Standardized commit messages are easier to understand and follow, which improves collaboration in development teams. * Automatic Generation of Release Notes: Tools can be used to automatically generate release notes based on commit messages.* Integration with Change Management Tools: Many development and project management tools can integrate with Conventional Commits to automate tasks such as changelog generation and release management. * Structured Change History: The change history becomes more structured and easier to navigate, making it easier to review changes and debug issues.

Practical Exampleslink image 24

Example 1: Bug Fix

gitfix(api):
      The user registration endpoint was allowing registrations with invalid email addresses. An additional validation has been added to ensure that email addresses are valid.
      Closes #456

Example 2: Adding a New Feature

gitfeat(api):
      Se implementó un nuevo endpoint que permite a los usuarios solicitar un enlace de recuperación de contraseña. El enlace se envía a su dirección de correo electrónico registrada.
      Closes #789```

Example 3: Improvement of documentation

gitdocs:
      Actualicé las instrucciones de configuración para el entorno de desarrollo y añadí una sección sobre la ejecución de pruebas.
      Closes #101

Tools to Build Messages that Comply with Conventional Commitslink image 25

Although we have seen how to create commit messages using conventional commits, it is quite possible that we might make mistakes, so we can use tools that guide us in the creation of these messages. Let's look at two: commitizen and the Conventional Commit plugin for vscode.

Commitizenlink image 26

To use it, first I will create a new folder in which I will initialize a Git repository.

	
!mkdir ~/comitizen_folder && cd ~/comitizen_folder && git init
Copy
	
hint: Using 'master' as the name for the initial branch. This default branch name
hint: is subject to change. To configure the initial branch name to use in all
hint: of your new repositories, which will suppress this warning, call:
hint:
hint: git config --global init.defaultBranch <name>
hint:
hint: Names commonly chosen instead of 'master' are 'main', 'trunk' and
hint: 'development'. The just-created branch can be renamed via this command:
hint:
hint: git branch -m <name>
Initialized empty Git repository in /home/maximofernandez/comitizen_folder/.git/

Now I install commitizen

	
%pip install --user -U commitizen
Copy
	
Collecting commitizen
Downloading commitizen-3.29.1-py3-none-any.whl.metadata (7.6 kB)
Collecting argcomplete<3.6,>=1.12.1 (from commitizen)
Downloading argcomplete-3.5.1-py3-none-any.whl.metadata (16 kB)
Requirement already satisfied: charset-normalizer<4,>=2.1.0 in /home/maximofernandez/miniforge3/lib/python3.12/site-packages (from commitizen) (3.3.2)
Requirement already satisfied: colorama<0.5.0,>=0.4.1 in /home/maximofernandez/miniforge3/lib/python3.12/site-packages (from commitizen) (0.4.6)
Collecting decli<0.7.0,>=0.6.0 (from commitizen)
Downloading decli-0.6.2-py3-none-any.whl.metadata (17 kB)
Requirement already satisfied: jinja2>=2.10.3 in /home/maximofernandez/miniforge3/lib/python3.12/site-packages (from commitizen) (3.1.4)
Requirement already satisfied: packaging>=19 in /home/maximofernandez/.local/lib/python3.12/site-packages (from commitizen) (24.1)
Requirement already satisfied: pyyaml>=3.08 in /home/maximofernandez/miniforge3/lib/python3.12/site-packages (from commitizen) (6.0.2)
Collecting questionary<3.0,>=2.0 (from commitizen)
Downloading questionary-2.0.1-py3-none-any.whl.metadata (5.4 kB)
Collecting termcolor<3,>=1.1 (from commitizen)
Downloading termcolor-2.5.0-py3-none-any.whl.metadata (6.1 kB)
Collecting tomlkit<1.0.0,>=0.5.3 (from commitizen)
Downloading tomlkit-0.13.2-py3-none-any.whl.metadata (2.7 kB)
Requirement already satisfied: MarkupSafe>=2.0 in /home/maximofernandez/miniforge3/lib/python3.12/site-packages (from jinja2>=2.10.3->commitizen) (2.1.5)
Collecting prompt_toolkit<=3.0.36,>=2.0 (from questionary<3.0,>=2.0->commitizen)
Downloading prompt_toolkit-3.0.36-py3-none-any.whl.metadata (7.0 kB)
Requirement already satisfied: wcwidth in /home/maximofernandez/miniforge3/lib/python3.12/site-packages (from prompt_toolkit<=3.0.36,>=2.0->questionary<3.0,>=2.0->commitizen) (0.2.13)
Downloading commitizen-3.29.1-py3-none-any.whl (71 kB)
Downloading argcomplete-3.5.1-py3-none-any.whl (43 kB)
Downloading decli-0.6.2-py3-none-any.whl (7.9 kB)
Downloading questionary-2.0.1-py3-none-any.whl (34 kB)
Downloading termcolor-2.5.0-py3-none-any.whl (7.8 kB)
Downloading tomlkit-0.13.2-py3-none-any.whl (37 kB)
Downloading prompt_toolkit-3.0.36-py3-none-any.whl (386 kB)
Installing collected packages: tomlkit, termcolor, prompt_toolkit, decli, argcomplete, questionary, commitizen
ERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.
ipython 8.27.0 requires prompt-toolkit<3.1.0,>=3.0.41, but you have prompt-toolkit 3.0.36 which is incompatible.
Successfully installed argcomplete-3.5.1 commitizen-3.29.1 decli-0.6.2 prompt_toolkit-3.0.36 questionary-2.0.1 termcolor-2.5.0 tomlkit-0.13.2
Note: you may need to restart the kernel to use updated packages.

We verify the installation

	
!cz version
Copy
	
3.29.1

I create a new file in the folder where I have initialized the git repository and add it to the staging area.

	
!cd ~/comitizen_folder && touch README.md && git add README.md
Copy

If I run git status I will see that the file is in the staging area and that I should now make a commit

	
!cd ~/comitizen_folder && touch README.md && git add README.md
!cd ~/comitizen_folder && git status
Copy
	
On branch master
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: README.md

It's time to create a commit with commitizen, to do this we run cz commit and a wizard will appear to help us create the commit.

	
!cd ~/comitizen_folder && cz commit
Copy
	
? Select the type of change you are committing docs: Documentation only changes
? What is the scope of this change? (class or file name): (press [enter] to skip)
readme
? Write a short and imperative summary of the code changes: (lower case and no period)
First innit, create readme
? Provide additional contextual information about the code changes: (press [enter] to skip)
This is the first commit, I create a empty readme
? Is this a BREAKING CHANGE? Correlates with MAJOR in SemVer No
? Footer. Information about Breaking Changes and reference issues that this commit closes: (press [enter] to skip)
docs(readme): First innit, create readme
This is the first commit, I create a empty readme
[master (root-commit) 4f646d4] docs(readme): First innit, create readme
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 README.md
Commit successful!

Alright, we now have our first commit created with commitizen that follows the Conventional Commits rules.

Conventional Commit Plugin for vscodelink image 27

Now we will do the same but with the vscode plugin Conventional Commit

First, you need to install the plugin, and once it's installed, press Ctrl + Shift + P and type Conventional Commit, press enter, and an assistant will appear to create the commit.

For me, using this plugin has two advantages over commitizen

  • The first is that it allows us to add emojis from gitmoji. This, provided emojis are not overused and only a few are used, makes it easier to identify the type of commit when viewing the commit history.* The second is that it saves the scopes you have used, so it prevents the creation of new scopes and instead reuses the ones you have already used.

Tools to Check Adherence to Conventional Commits Conventionlink image 28

We have seen how to create commit messages that follow the conventional commits convention, but a good practice is to create a tool to check that the commit created follows the convention, especially when working in a team. There are tools that allow us to do this, such as pre-commit, but what they do is modify the git hooks, so we are going to do it ourselves and use commitizen to help us validate the commit message.

We have already installed commitizen, so let's see how it can be used to check a commit message.

First, we create a file called commit-msg in the .git/hooks folder and give it execution permissions. Within Git hooks, there are several types of files that can be used for different tasks. In this case, we are going to use commit-msg, which runs just before the commit is created.

	
!cd ~/comitizen_folder/.git/hooks && touch commit-msg && chmod +x commit-msg
Copy

Now we add the following code to the commit-msg file

```#!/bin/sh
      This script validates the commit message using commitizen
      COMMIT_MSG_FILE=$1cz check --commit-msg-file $COMMIT_MSG_FILE```
      
	
!cd ~/comitizen_folder/.git/hooks && touch commit-msg && chmod +x commit-msg
!cd ~/comitizen_folder/.git/hooks &&
echo '#!/bin/sh' > commit-msg && \
echo '# Este script valida el mensaje del commit usando commitizen' >> commit-msg && \
echo ' ' >> commit-msg && \
echo 'COMMIT_MSG_FILE=$1' >> commit-msg && \
echo 'cz check --commit-msg-file $COMMIT_MSG_FILE' >> commit-msg
Copy

Once done, we try to make a commit with an incorrect message. First, we modify the readme and add it to the staging area.

	
!cd ~/comitizen_folder/.git/hooks && touch commit-msg && chmod +x commit-msg
!cd ~/comitizen_folder/.git/hooks &&
echo '#!/bin/sh' > commit-msg && \
echo '# Este script valida el mensaje del commit usando commitizen' >> commit-msg && \
echo ' ' >> commit-msg && \
echo 'COMMIT_MSG_FILE=$1' >> commit-msg && \
echo 'cz check --commit-msg-file $COMMIT_MSG_FILE' >> commit-msg
!cd ~/comitizen_folder && echo '.' >> README.md && git add README.md
Copy

Now we make a commit with an incorrect message

	
!cd ~/comitizen_folder/.git/hooks && touch commit-msg && chmod +x commit-msg
!cd ~/comitizen_folder/.git/hooks &&
echo '#!/bin/sh' > commit-msg && \
echo '# Este script valida el mensaje del commit usando commitizen' >> commit-msg && \
echo ' ' >> commit-msg && \
echo 'COMMIT_MSG_FILE=$1' >> commit-msg && \
echo 'cz check --commit-msg-file $COMMIT_MSG_FILE' >> commit-msg
!cd ~/comitizen_folder && echo '.' >> README.md && git add README.md
!cd ~/comitizen_folder && git commit -m "Add dot to README"
Copy
	
commit validation: failed!
please enter a commit message in the commitizen format.
commit "": "Add dot to README"
pattern: (?s)(build|ci|docs|feat|fix|perf|refactor|style|test|chore|revert|bump)((S+))?!?:( [^ ]+)(( .*)|(s*))?$

Now we make a commit with a correct message

	
!cd ~/comitizen_folder && git commit -m "docs(readme): :memo: Add dot to README"
Copy
	
Commit validation: successful!
[master d488656] docs(readme): :memo: Add dot to README
1 file changed, 1 insertion(+), 1 deletion(-)

We have successfully validated the commit, so if we look at the commit history, we will see that the commit with the incorrect message has not been created and the commit with the correct message has.

	
!cd ~/comitizen_folder && git log
Copy
	
commit d488656297c7cb448a25dd33a008cb5ce1e14e83 (HEAD -> master)
Author: MaximoFN <maximofn@gmail.com>
Date: Tue Oct 8 11:22:19 2024 +0200
docs(readme): :memo: Add dot to README
commit fb518c2b903a259b2e44972e88aabf5656f97be9
Author: MaximoFN <maximofn@gmail.com>
Date: Tue Oct 8 10:57:41 2024 +0200
docs(readme): :memo: Update readme
Update readme with text conventional commits
commit 4f646d45047a45b549243efbfde9e331d45e23f1
Author: MaximoFN <maximofn@gmail.com>
Date: Tue Oct 8 10:48:07 2024 +0200
docs(readme): First innit, create readme
This is the first commit, I create a empty readme

Tools for Creating Changelogs from Conventional Commitslink image 29

As we have the commits written following the same convention, we can automatically create a changelog with git-changelog. We install the dependencies

	
%pip install git-changelog
Copy
	
Collecting git-changelog
Downloading git_changelog-2.5.2-py3-none-any.whl.metadata (5.4 kB)
Collecting appdirs>=1.4 (from git-changelog)
Downloading appdirs-1.4.4-py2.py3-none-any.whl.metadata (9.0 kB)
Requirement already satisfied: Jinja2>=2.10 in /home/maximofernandez/miniforge3/lib/python3.12/site-packages (from git-changelog) (3.1.4)
Requirement already satisfied: packaging>=24.0 in /home/maximofernandez/.local/lib/python3.12/site-packages (from git-changelog) (24.1)
Collecting semver>=2.13 (from git-changelog)
Downloading semver-3.0.2-py3-none-any.whl.metadata (5.0 kB)
Requirement already satisfied: MarkupSafe>=2.0 in /home/maximofernandez/miniforge3/lib/python3.12/site-packages (from Jinja2>=2.10->git-changelog) (2.1.5)
Downloading git_changelog-2.5.2-py3-none-any.whl (32 kB)
Downloading appdirs-1.4.4-py2.py3-none-any.whl (9.6 kB)
Downloading semver-3.0.2-py3-none-any.whl (17 kB)
Installing collected packages: appdirs, semver, git-changelog
Successfully installed appdirs-1.4.4 git-changelog-2.5.2 semver-3.0.2
Note: you may need to restart the kernel to use updated packages.

Now we can create a changelog with git-changelog. Since we have created some very simple commits, the changelog will be very simple.

	
!cd ~/comitizen_folder && git-changelog
Copy
	
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
<!-- insertion marker -->
## Unreleased
<small>[Compare with latest]()</small>
<!-- insertion marker -->

We can also ask it to write it in a file and many more options

	
!git-changelog -h
Copy
	
usage: git-changelog [--config-file [PATH ...]] [-b] [-B VERSION] [-n SCHEME]
[-h] [-i] [-g REGEX] [-m MARKER] [-o FILE] [-p PROVIDER]
[-r] [-R] [-I FILE] [-c CONVENTION] [-s SECTIONS]
[-t TEMPLATE] [-T] [-E] [-Z] [-F RANGE] [-j KEY=VALUE]
[-V] [--debug-info]
[REPOSITORY]
Automatic Changelog generator using Jinja2 templates.
This tool parses your commit messages to extract useful data
that is then rendered using Jinja2 templates, for example to
a changelog file formatted in Markdown.
Each Git tag will be treated as a version of your project.
Each version contains a set of commits, and will be an entry
in your changelog. Commits in each version will be grouped
by sections, depending on the commit convention you follow.
### Conventions
#### Basic
*Default sections:*
- add: Added
- fix: Fixed
- change: Changed
- remove: Removed
*Additional sections:*
- merge: Merged
- doc: Documented
#### Angular
*Default sections:*
- feat: Features
- fix: Bug Fixes
- revert: Reverts
- ref, refactor: Code Refactoring
- perf: Performance Improvements
*Additional sections:*
- build: Build
- chore: Chore
- ci: Continuous Integration
- deps: Dependencies
- doc, docs: Docs
- style: Style
- test, tests: Tests
#### ConventionalCommit
*Default sections:*
- feat: Features
- fix: Bug Fixes
- revert: Reverts
- ref, refactor: Code Refactoring
- perf: Performance Improvements
*Additional sections:*
- build: Build
- chore: Chore
- ci: Continuous Integration
- deps: Dependencies
- doc, docs: Docs
- style: Style
- test, tests: Tests
positional arguments:
REPOSITORY The repository path, relative or absolute. Default:
current working directory.
options:
--config-file [PATH ...]
Configuration file(s).
-b, --bump-latest Deprecated, use --bump=auto instead. Guess the new
latest version by bumping the previous one based on
the set of unreleased commits. For example, if a
commit contains breaking changes, bump the major
number (or the minor number for 0.x versions). Else if
there are new features, bump the minor number. Else
just bump the patch number. Default: unset (false).
-B VERSION, --bump VERSION
Specify the bump from latest version for the set of
unreleased commits. Can be one of `auto`, `major`,
`minor`, `patch` or a valid SemVer version (eg.
1.2.3). For both SemVer and PEP 440 versioning schemes
(see -n), `auto` will bump the major number if a
commit contains breaking changes (or the minor number
for 0.x versions, see -Z), else the minor number if
there are new features, else the patch number.
Default: unset (false).
-n SCHEME, --versioning SCHEME
Versioning scheme to use when bumping and comparing
versions. The selected scheme will impact the values
accepted by the `--bump` option. Supported: `pep440`,
`semver`. PEP 440 provides the following bump
strategies: `auto`, `epoch`, `release`, `major`,
`minor`, `micro`, `patch`, `pre`, `alpha`, `beta`,
`candidate`, `post`, `dev`. Values `auto`, `major`,
`minor`, `micro` can be suffixed with one of `+alpha`,
`+beta`, `+candidate`, and/or `+dev`. Values `alpha`,
`beta` and `candidate` can be suffixed with `+dev`.
Examples: `auto+alpha`, `major+beta+dev`, `micro+dev`,
`candidate+dev`, etc.. SemVer provides the following
bump strategies: `auto`, `major`, `minor`, `patch`,
`release`. See the docs for more information. Default:
unset (`semver`).
-h, --help Show this help message and exit.
-i, --in-place Insert new entries (versions missing from changelog)
in-place. An output file must be specified. With
custom templates, you can pass two additional
arguments: `--version-regex` and `--marker-line`. When
writing in-place, an `in_place` variable will be
injected in the Jinja context, allowing to adapt the
generated contents (for example to skip changelog
headers or footers). Default: unset (false).
-g REGEX, --version-regex REGEX
A regular expression to match versions in the existing
changelog (used to find the latest release) when
writing in-place. The regular expression must be a
Python regex with a `version` named group. Default:
`^## [(?P<version>v?[^]]+)`.
-m MARKER, --marker-line MARKER
A marker line at which to insert new entries (versions
missing from changelog). If two marker lines are
present in the changelog, the contents between those
two lines will be overwritten (useful to update an
'Unreleased' entry for example). Default: `<!--
insertion marker -->`.
-o FILE, --output FILE
Output to given file. Default: standard output.
-p PROVIDER, --provider PROVIDER
Explicitly specify the repository provider. Default:
unset.
-r, --parse-refs Parse provider-specific references in commit messages
(GitHub/GitLab/Bitbucket issues, PRs, etc.). Default:
unset (false).
-R, --release-notes Output release notes to stdout based on the last entry
in the changelog. Default: unset (false).
-I FILE, --input FILE
Read from given file when creating release notes.
Default: `CHANGELOG.md`.
-c CONVENTION, --convention CONVENTION, --commit-style CONVENTION, --style CONVENTION
The commit convention to match against. Default:
`basic`.
-s SECTIONS, --sections SECTIONS
A comma-separated list of sections to render. See the
available sections for each supported convention in
the description. Default: unset (None).
-t TEMPLATE, --template TEMPLATE
The Jinja2 template to use. Prefix it with `path:` to
specify the path to a Jinja templated file. Default:
`keepachangelog`.
-T, --trailers, --git-trailers
Parse Git trailers in the commit message. See
https://git-scm.com/docs/git-interpret-trailers.
Default: unset (false).
-E, --omit-empty-versions
Omit empty versions from the output. Default: unset
(false).
-Z, --no-zerover By default, breaking changes on a 0.x don't bump the
major version, maintaining it at 0. With this option,
a breaking change will bump a 0.x version to 1.0.
-F RANGE, --filter-commits RANGE
The Git revision-range filter to use (e.g.
`v1.2.0..`). Default: no filter.
-j KEY=VALUE, --jinja-context KEY=VALUE
Pass additional key/value pairs to the template.
Option can be used multiple times. The key/value pairs
are accessible as 'jinja_context' in the template.
-V, --version Show the current version of the program and exit.
--debug-info Print debug information.

We could now easily generate changelogs from commits that follow the conventional commits convention. Additionally, we can add it to a CI/CD pipeline so that it is automatically generated in each release.

Continue reading

DoLa – Decoding by Contrasting Layers Improves Factuality in Large Language Models

DoLa – Decoding by Contrasting Layers Improves Factuality in Large Language Models

Have you ever talked to an LLM and they answered you something that sounds like they've been drinking machine coffee all night long 😂 That's what we call a hallucination in the LLM world! But don't worry, because it's not that your language model is crazy (although it can sometimes seem that way 🤪). The truth is that LLMs can be a bit... creative when it comes to generating text. But thanks to DoLa, a method that uses contrast layers to improve the feasibility of LLMs, we can keep our language models from turning into science fiction writers 😂. In this post, I'll explain how DoLa works and show you a code example so you can better understand how to make your LLMs more reliable and less prone to making up stories. Let's save our LLMs from insanity and make them more useful! 🚀

QLoRA: Efficient Finetuning of Quantized LLMs

QLoRA: Efficient Finetuning of Quantized LLMs

Hello everyone! 🤗 Today we are going to talk about QLoRA, the technique that will allow you to make your language models more efficient and faster ⏱️. But how does it do it? 🤔 Well, first it uses quantization to reduce the size of the model weights, which saves memory and speed 📈. Then, it applies LoRA (Low-Rank Adaptation), which is like a superpower that allows the model to adapt to new data without retraining from scratch 💪. And, for you to see how it works in practice, I leave you with a code example that will make you say 'Eureka!' 🎉 Let's dive into the world of QLoRA and discover how we can make our models smarter and more efficient! 🤓

Last posts -->

Have you seen these projects?

Subtify

Subtify Subtify

Subtitle generator for videos in the language you want. Also, it puts a different color subtitle to each person

View all projects -->

Do you want to apply AI in your project? Contact me!

Do you want to improve with these tips?

Last tips -->

Use this locally

Hugging Face spaces allow us to run models with very simple demos, but what if the demo breaks? Or if the user deletes it? That's why I've created docker containers with some interesting spaces, to be able to use them locally, whatever happens. In fact, if you click on any project view button, it may take you to a space that doesn't work.

View all containers -->

Do you want to apply AI in your project? Contact me!

Do you want to train your model with these datasets?

short-jokes-dataset

Dataset with jokes in English

opus100

Dataset with translations from English to Spanish

netflix_titles

Dataset with Netflix movies and series

View more datasets -->