How do you know if a git commit message is good?
How do you know if a git commit message is good?
If you can browse your git history and understand why those changes were made and why/how that technical decision happened without needing to refer to tickets, issues, or requirements, then you likely have an excellent git history.
If your git history looks like:
commit 04796b39d364b6c580bbe17ecf3f0160b5c8877d
Author: John Snow
Date: Sun Jul 7 12:03:51 2024 +0300
Fix PRJ-5623
commit 828394c2864ea98003491e17b2562ad24bada653
Author: John Snow
Date: Sun Jul 7 12:03:51 2024 +0300
Implement PRJ-6523
commit f64299c822a7cd38557eb935f074f18eed5719a2
Author: Jane Dane
Date: Mon Aug 15 17:41:23 2022 +0300
Refactor User authentication
commit abbd91854acce973ec662b0f2b75e89a4ceb3261
Author: Jane Dane
Date: Mon Aug 15 15:30:08 2022 +0300
Move parse_with_options to Team
Then, you might want to reconsider how you write your commits.
An example of a goodish git commit message
Here is an example of a git commit message that is good enough:
Commit 234a85f59da9c81edfa981dd56a1d97795a7d1c9
Author: Lucian Ghinda
Date: Sun Aug 25 07:56:07 2024 +0300
Add new tag formats to improve the speed of tagging
This commit introduces new tag formats in the TagTypeMap and updates
ContentTypeIdentifier tests for compatibility.
These changes ensure that the ContentTypeIdentifier can correctly
identify content types using the new tag formats, maintaining
the system's flexibility and reliability.
Why these changes?
(1) We want to allow users to tag content using shorter tags
eg: `stype` instead of `section:type`
(2) Automatically fix typos in tag formats:
eg: typing `a` instead of `s` in `s:type` => `a:type`
(3) Duplicate tag letter replaces `:`
eg: `aatype` is the same as ```ruby
require 'bundler/inline'
gemfile do
source 'https://rubygems.org'
gem 'benchmark-ips', require: false
end
HASH = {
first_name: nil,
last_name: nil,
country: nil,
profession: nil,
language: nil,
hobby: nil,
pet: nil,
longer_name: nil,
occupation: nil,
mailing_address: nil,
}.freeze
require 'benchmark/ips'
Benchmark.ips do |x|
x.report("to_s") { HASH.transform_keys(&:to_s) }
x.report("cond") { HASH.transform_keys { |k| Symbol === k ? k.name : k.to_s } }
x.compare!(order: :baseline)
end
```0
```ruby
require 'bundler/inline'
gemfile do
source 'https://rubygems.org'
gem 'benchmark-ips', require: false
end
HASH = {
first_name: nil,
last_name: nil,
country: nil,
profession: nil,
language: nil,
hobby: nil,
pet: nil,
longer_name: nil,
occupation: nil,
mailing_address: nil,
}.freeze
require 'benchmark/ips'
Benchmark.ips do |x|
x.report("to_s") { HASH.transform_keys(&:to_s) }
x.report("cond") { HASH.transform_keys { |k| Symbol === k ? k.name : k.to_s } }
x.compare!(order: :baseline)
end
```1 is the same as ```ruby
require 'bundler/inline'
gemfile do
source 'https://rubygems.org'
gem 'benchmark-ips', require: false
end
HASH = {
first_name: nil,
last_name: nil,
country: nil,
profession: nil,
language: nil,
hobby: nil,
pet: nil,
longer_name: nil,
occupation: nil,
mailing_address: nil,
}.freeze
require 'benchmark/ips'
Benchmark.ips do |x|
x.report("to_s") { HASH.transform_keys(&:to_s) }
x.report("cond") { HASH.transform_keys { |k| Symbol === k ? k.name : k.to_s } }
x.compare!(order: :baseline)
end
```2
Changes:
1. Updated TagTypeMap to include new formats:
- 's:type' (e.g., 'a:code', 'a:article')
- 'stype' (e.g., 'scode', 'sarticle')
- 'sstype' (e.g., 'sscode', 'sstarticle')
- 'a:type' (e.g., 'a:code', 'a:article')
- 'aatype' (e.g., 'aacode', 'aaarticle')
- 'Aatype' (e.g., 'Aacode', 'Aaarticle')
2. Updated ContentTypeIdentifier tests to cover new tag formats
for all existing content types:
- Code, Articles, Videos, Library, Newsletter, Podcasts
- Related, Community, Events, Books, Launch, Slides
A better example
Here is an example of a git commit message shared by Zlatko Alomerovic via Linkedin. The message is written by Jean Boussier (@byroot) in a commit for Rails and it looks like this (here is just the first part of it)
The full message looks like this:
commit 8c7e69b79b63a88a170a9b9004a906db00161a3b
Author: Jean Boussier
Date: Mon Jan 8 18:43:37 2024 +0100
Optimize Hash\#stringify_keys
Using Symbol\#name allows to hit two birds with one stone.
First it will return a pre-existing string, so will save
one allocation per key.
Second, that string will be already interned, so it will
save the internal ```ruby
require 'bundler/inline'
gemfile do
source 'https://rubygems.org'
gem 'benchmark-ips', require: false
end
HASH = {
first_name: nil,
last_name: nil,
country: nil,
profession: nil,
language: nil,
hobby: nil,
pet: nil,
longer_name: nil,
occupation: nil,
mailing_address: nil,
}.freeze
require 'benchmark/ips'
Benchmark.ips do |x|
x.report("to_s") { HASH.transform_keys(&:to_s) }
x.report("cond") { HASH.transform_keys { |k| Symbol === k ? k.name : k.to_s } }
x.compare!(order: :baseline)
end
```3 implementation the work of looking
up the interned strings table to deduplicate the key.
```
ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x86_64-darwin21]
Warming up --------------------------------------
to_s 17.768k i/100ms
cond 23.703k i/100ms
Calculating -------------------------------------
to_s 169.830k (±10.4%) i/s - 852.864k in 5.088377s
cond 236.803k (± 7.9%) i/s - 1.185M in 5.040945s
cond 236.803k (± 7.9%) i/s - 1.185M in 5.040945s
Comparison:
to_s: 169830.3 i/s
cond: 236803.4 i/s - 1.39x faster
```
```ruby
require 'bundler/inline'
gemfile do
source 'https://rubygems.org'
gem 'benchmark-ips', require: false
end
HASH = {
first_name: nil,
last_name: nil,
country: nil,
profession: nil,
language: nil,
hobby: nil,
pet: nil,
longer_name: nil,
occupation: nil,
mailing_address: nil,
}.freeze
require 'benchmark/ips'
Benchmark.ips do |x|
x.report("to_s") { HASH.transform_keys(&:to_s) }
x.report("cond") { HASH.transform_keys { |k| Symbol === k ? k.name : k.to_s } }
x.compare!(order: :baseline)
end
```