Skip to content

Commit 1ba46f2

Browse files
committed
fix: conventional commit 'breaking change' in body instead of title
closes commitizen-tools#16
1 parent c35dbff commit 1ba46f2

9 files changed

+249
-49
lines changed

commitizen/cz/base.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ def questions(self) -> list:
1010
"""Questions regarding the commit message."""
1111

1212
@abstractmethod
13-
def message(self, answers: dict) -> dict:
13+
def message(self, answers: dict) -> str:
1414
"""Format your git message."""
1515

1616
def example(self) -> str:

commitizen/cz/conventional_commits/conventional_commits.py

+28-29
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ def parse_subject(text):
3030

3131

3232
class ConventionalCommitsCz(BaseCommitizen):
33-
def questions(self):
33+
def questions(self) -> list:
3434
questions = [
3535
{
3636
"type": "list",
@@ -45,13 +45,6 @@ def questions(self):
4545
"value": "feat",
4646
"name": "feat: A new feature. Correlates with MINOR in SemVer",
4747
},
48-
{
49-
"value": "BREAKING CHANGE",
50-
"name": (
51-
"BREAKING CHANGE: introduces a breaking API change. "
52-
"Correlates with MAJOR in SemVer"
53-
),
54-
},
5548
{"value": "docs", "name": "docs: Documentation only changes"},
5649
{
5750
"value": "style",
@@ -112,6 +105,12 @@ def questions(self):
112105
"Imperative, lower case and no final dot:\n"
113106
),
114107
},
108+
{
109+
"type": "confirm",
110+
"message": "Is this a BREAKING CHANGE? Correlates with MAJOR in SemVer",
111+
"name": "is_breaking_change",
112+
"default": False,
113+
},
115114
{
116115
"type": "input",
117116
"name": "body",
@@ -131,46 +130,46 @@ def questions(self):
131130
]
132131
return questions
133132

134-
def message(self, answers):
133+
def message(self, answers: dict) -> str:
135134
prefix = answers["prefix"]
136135
scope = answers["scope"]
137136
subject = answers["subject"]
138137
body = answers["body"]
139138
footer = answers["footer"]
140-
message = ""
141-
142-
if prefix:
143-
message += "{0}".format(prefix)
144-
if scope:
145-
message += "({0})".format(scope)
146-
message += ": "
147-
if subject:
148-
message += "{0}".format(subject)
139+
is_breaking_change = answers["is_breaking_change"]
140+
141+
if scope:
142+
scope = f"({scope})"
143+
if is_breaking_change:
144+
body = f"BREAKING CHANGE: {body}"
149145
if body:
150-
message += "\n\n{0}".format(body)
146+
body = f"\n\n{body}"
151147
if footer:
152-
message += "\n\n{0}".format(footer)
148+
footer = f"\n\n{footer}"
149+
150+
message = f"{prefix}{scope}: {subject}{body}{footer}"
151+
153152
return message
154153

155-
def example(self):
154+
def example(self) -> str:
156155
return (
157-
"feat($injector): ability to load new modules after bootstrapping\n"
158-
"\nThe new method `$injector.loadNewModules(modules)` will add "
159-
"each of the\ninjectables to the injector and execute all of the "
160-
"config and run blocks\nfor each module passed to the method.\n"
161-
"\nCloses #324"
156+
"fix: correct minor typos in code\n"
157+
"\n"
158+
"see the issue for details on the typos fixed\n"
159+
"\n"
160+
"closes issue #12"
162161
)
163162

164-
def schema(self):
163+
def schema(self) -> str:
165164
return (
166165
"<type>(<scope>): <subject>\n"
167166
"<BLANK LINE>\n"
168-
"<body>\n"
167+
"(BREAKING CHANGE: )<body>\n"
169168
"<BLANK LINE>\n"
170169
"<footer>"
171170
)
172171

173-
def info(self):
172+
def info(self) -> str:
174173
dir_path = os.path.dirname(os.path.realpath(__file__))
175174
filepath = os.path.join(dir_path, "conventional_commits_info.txt")
176175
with open(filepath, "r") as f:
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,31 @@
1-
Commit Message Format
1+
The commit contains the following structural elements, to communicate
2+
intent to the consumers of your library:
23

3-
Each commit message consists of a header, a body and a footer. The header has a special format that
4-
includes a type, a scope and a subject:
4+
fix: a commit of the type fix patches a bug in your codebase
5+
(this correlates with PATCH in semantic versioning).
56

6-
<type>(<scope>): <subject>
7-
<BLANK LINE>
8-
<body>
9-
<BLANK LINE>
10-
<footer>
7+
feat: a commit of the type feat introduces a new feature to the codebase
8+
(this correlates with MINOR in semantic versioning).
119

12-
The header is mandatory and the scope of the header is optional.
10+
BREAKING CHANGE: a commit that has the text BREAKING CHANGE: at the beginning of
11+
its optional body or footer section introduces a breaking API change
12+
(correlating with MAJOR in semantic versioning).
13+
A BREAKING CHANGE can be part of commits of any type.
1314

14-
Any line of the commit message cannot be longer 100 characters! This allows the message to be easier
15-
to read on GitHub as well as in various git tools.
15+
Others: commit types other than fix: and feat: are allowed,
16+
like chore:, docs:, style:, refactor:, perf:, test:, and others.
1617

17-
Footer should contain a closing reference to an issue if any.
18+
We also recommend improvement for commits that improve a current
19+
implementation without adding a new feature or fixing a bug.
1820

19-
This leads to more readable messages that are easy to follow when looking through the project history.
20-
But also, the git commit messages can be used to generate the changelog.
21+
Notice these types are not mandated by the conventional commits specification,
22+
and have no implicit effect in semantic versioning (unless they include a BREAKING CHANGE).
23+
24+
A scope may be provided to a commit’s type, to provide additional contextual
25+
information and is contained within parenthesis, e.g., feat(parser): add ability to parse arrays.
26+
27+
<type>[optional scope]: <description>
28+
29+
[optional body]
30+
31+
[optional footer]

commitizen/git.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,14 @@ def commit(message: str, args=""):
1919

2020
def get_commits(start: str, end: str = "HEAD", from_beginning: bool = False) -> list:
2121

22-
c = cmd.run(f"git log --pretty=format:%s {start}...{end}")
22+
c = cmd.run(f"git log --pretty=format:%s%n%b {start}...{end}")
2323

2424
if from_beginning:
25-
c = cmd.run(f"git log --pretty=format:%s {end}")
25+
c = cmd.run(f"git log --pretty=format:%s%n%b {end}")
2626

2727
if not c.out:
2828
return []
29-
29+
print(c.out)
3030
return c.out.split("\n")
3131

3232

docs/images/commit.yml

+187
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
# The configurations that used for the recording, feel free to edit them
2+
config:
3+
4+
# Specify a command to be executed
5+
# like `/bin/bash -l`, `ls`, or any other commands
6+
# the default is bash for Linux
7+
# or powershell.exe for Windows
8+
command: bash -l
9+
10+
# Specify the current working directory path
11+
# the default is the current working directory path
12+
cwd: ~/my-project
13+
14+
# Export additional ENV variables
15+
env:
16+
recording: true
17+
18+
# Explicitly set the number of columns
19+
# or use `auto` to take the current
20+
# number of columns of your shell
21+
cols: 101
22+
23+
# Explicitly set the number of rows
24+
# or use `auto` to take the current
25+
# number of rows of your shell
26+
rows: 22
27+
28+
# Amount of times to repeat GIF
29+
# If value is -1, play once
30+
# If value is 0, loop indefinitely
31+
# If value is a positive number, loop n times
32+
repeat: 0
33+
34+
# Quality
35+
# 1 - 100
36+
quality: 85
37+
38+
# Delay between frames in ms
39+
# If the value is `auto` use the actual recording delays
40+
frameDelay: auto
41+
42+
# Maximum delay between frames in ms
43+
# Ignored if the `frameDelay` isn't set to `auto`
44+
# Set to `auto` to prevent limiting the max idle time
45+
maxIdleTime: 2000
46+
47+
# The surrounding frame box
48+
# The `type` can be null, window, floating, or solid`
49+
# To hide the title use the value null
50+
# Don't forget to add a backgroundColor style with a null as type
51+
frameBox:
52+
type: floating
53+
title: Commitizen
54+
style:
55+
border: 0px black solid
56+
# boxShadow: none
57+
# margin: 0px
58+
59+
# Add a watermark image to the rendered gif
60+
# You need to specify an absolute path for
61+
# the image on your machine or a URL, and you can also
62+
# add your own CSS styles
63+
watermark:
64+
imagePath: null
65+
style:
66+
position: absolute
67+
right: 15px
68+
bottom: 15px
69+
width: 100px
70+
opacity: 0.9
71+
72+
# Cursor style can be one of
73+
# `block`, `underline`, or `bar`
74+
cursorStyle: block
75+
76+
# Font family
77+
# You can use any font that is installed on your machine
78+
# in CSS-like syntax
79+
fontFamily: "Monaco, Lucida Console, Ubuntu Mono, Monospace"
80+
81+
# The size of the font
82+
fontSize: 12
83+
84+
# The height of lines
85+
lineHeight: 1
86+
87+
# The spacing between letters
88+
letterSpacing: 0
89+
90+
# Theme
91+
theme:
92+
background: "transparent"
93+
foreground: "#afafaf"
94+
cursor: "#c7c7c7"
95+
black: "#232628"
96+
red: "#fc4384"
97+
green: "#b3e33b"
98+
yellow: "#ffa727"
99+
blue: "#75dff2"
100+
magenta: "#ae89fe"
101+
cyan: "#708387"
102+
white: "#d5d5d0"
103+
brightBlack: "#626566"
104+
brightRed: "#ff7fac"
105+
brightGreen: "#c8ed71"
106+
brightYellow: "#ebdf86"
107+
brightBlue: "#75dff2"
108+
brightMagenta: "#ae89fe"
109+
brightCyan: "#b1c6ca"
110+
brightWhite: "#f9f9f4"
111+
112+
# Records, feel free to edit them
113+
records:
114+
- delay: 987
115+
content: "\e[1;33m\e[0;32m\e[1;34m\e[1;32msantiago\e[1;34m@\e[1;31mhome\e[1;37m in \e[1;34m~/my-project\e[0;36m |master #|\e[1;32m\r\r\n\e[1;32m$\e[00m "
116+
- delay: 731
117+
content: c
118+
- delay: 345
119+
content: z
120+
- delay: 135
121+
content: ' '
122+
- delay: 118
123+
content: c
124+
- delay: 116
125+
content: o
126+
- delay: 200
127+
content: m
128+
- delay: 135
129+
content: m
130+
- delay: 199
131+
content: i
132+
- delay: 406
133+
content: t
134+
- delay: 144
135+
content: "\r\n"
136+
- delay: 209
137+
content: "\e[?1l\e[6n"
138+
- delay: 7
139+
content: "\e[?2004h\e[?25l\e[0m\e[?7l\e[0m\e[J\e[0;38;5;67m?\e[0;1m Select the type of change you are committing \e[0m (Use arrow keys) \r\e[100C \e[0m\r\r\n\e[0m » fix: A bug fix. Correlates with PATCH in SemVer\e[0m\r\r\n\e[0m feat: A new feature. Correlates with MINOR in SemVer\e[0m\r\r\n\e[0m docs: Documentation only changes\e[0m\r\r\n\e[0m style: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-\r\e[100Cc\e[0m\r\r\n\e[0m refactor: A code change that neither fixes a bug nor adds a feature\e[0m\r\r\n\e[0m perf: A code change that improves performance\e[0m\r\r\n\e[0m test: Adding missing or correcting existing tests\e[0m\r\r\n\e[0m build: Changes that affect the build system or external dependencies (example scopes: pip, docker\r\e[100C,\e[0m\r\r\n\e[0m ci: Changes to our CI configuration files and scripts (example scopes: GitLabCI) \r\e[100C \r\e[9A\e[64C\e[?7h\e[0m\e[?12l\e[?25h"
140+
- delay: 17
141+
content: "\e[?25l\e[?7l\e[0m\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\e[0m ci: Changes to our CI configuration files and scripts (example scopes: GitLabCI)\e[0m\e[K\e[0m\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\e[0m \r\e[100C \r\e[19A\e[64C\e[?7h\e[0m\e[?12l\e[?25h"
142+
- delay: 647
143+
content: "\e[?25l\e[?7l\e[0m\r\r\n\e[0m \e[0m\r\r\n\e[0m » \e[2A\e[61C\e[?7h\e[0m\e[?12l\e[?25h"
144+
- delay: 574
145+
content: "\e[?25l\e[?7l\e[64D\e[0m\e[J\e[0;38;5;67m?\e[0;1m Select the type of change you are committing \e[0;38;5;214;1m feat: A new feature. Correlates with MINOR in SemVer\r\e[100C\e[0m \r\e[0m\r\r\n\e[J\e[?7h\e[0m\e[?12l\e[?25h\e[?2004l"
146+
- delay: 20
147+
content: "\e[?1l\e[6n\e[?2004h\e[?25l\e[0m\e[?7l\e[0m\e[J\e[0;38;5;67m?\e[0;1m Scope. Could be anything specifying place of the commit change (users, db, poll):\e[0m \r\e[100C \e[0m\r\r\n\e[0;1m \e[0m \r\e[100C \r\e[C\e[?7h\e[0m\e[?12l\e[?25h"
148+
- delay: 11
149+
content: "\e[?25l\e[?7l\b\e[0;1m \e[0m \e[0m\e[K\e[0m\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\e[0m \r\e[100C \r\e[17A\e[C\e[?7h\e[0m\e[?12l\e[?25h"
150+
- delay: 1388
151+
content: "\e[?25l\e[?7l\e[A\b\e[0m\e[J\e[0;38;5;67m?\e[0;1m Scope. Could be anything specifying place of the commit change (users, db, poll):\e[0m \r\e[100C \e[0m\r\r\n\e[0;1m \e[0m \r\e[100C \r\e[0m\r\r\n\e[J\e[?7h\e[0m\e[?12l\e[?25h\e[?2004l"
152+
- delay: 12
153+
content: "\e[?1l\e[6n"
154+
- delay: 5
155+
content: "\e[?2004h\e[?25l\e[0m\e[?7l\e[0m\e[J\e[0;38;5;67m?\e[0;1m Subject. Concise description of the changes. Imperative, lower case and no final dot:\e[0m \r\e[100C \e[0m\r\r\n\e[0;1m \e[0m \r\e[100C \r\e[C\e[?7h\e[0m\e[?12l\e[?25h"
156+
- delay: 24
157+
content: "\e[?25l\e[?7l\b\e[0;1m \e[0m \e[0m\e[K\e[0m\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\e[0m \r\e[100C \r\e[15A\e[C\e[?7h\e[0m\e[?12l\e[?25h"
158+
- delay: 925
159+
content: "\e[?25l\e[?7l\e[0mallow provided config object to extend other configs \b\e[?7h\e[0m\e[?12l\e[?25h\e[?25l\e[?7l\e[?7h\e[0m\e[?12l\e[?25h"
160+
- delay: 2880
161+
content: "\e[?25l\e[?7l\e[A\e[53D\e[0m\e[J\e[0;38;5;67m?\e[0;1m Subject. Concise description of the changes. Imperative, lower case and no final dot:\e[0m \r\e[100C \e[0m\r\r\n\e[0;1m \e[0mallow provided config object to extend other configs \r\e[100C \r\e[0m\r\r\n\e[J\e[?7h\e[0m\e[?12l\e[?25h\e[?2004l"
162+
- delay: 13
163+
content: "\e[?1l\e[6n\e[?2004h\e[?25l\e[0m\e[?7l\e[0m\e[J\e[0;38;5;67m?\e[0;1m Is this a BREAKING CHANGE? Correlates with MAJOR in SemVer \e[0m (y/N) \r\e[100C \r\e[67C\e[?7h\e[0m\e[?12l\e[?25h"
164+
- delay: 19
165+
content: "\e[?25l\e[?7l\e[67D\e[0;38;5;67m?\e[0;1m Is this a BREAKING CHANGE? Correlates with MAJOR in SemVer \e[0m (y/N) \e[0m\e[K\e[0m\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\e[0m \r\e[100C \r\e[14A\e[67C\e[?7h\e[0m\e[?12l\e[?25h"
166+
- delay: 1521
167+
content: "\e[?25l\e[?7l\e[67D\e[0m\e[J\e[0;38;5;67m?\e[0;1m Is this a BREAKING CHANGE? Correlates with MAJOR in SemVer \e[0;38;5;214;1m Yes\e[0m \r\e[100C \r\e[0m\r\r\n\e[J\e[?7h\e[0m\e[?12l\e[?25h\e[?2004l"
168+
- delay: 15
169+
content: "\e[?1l\e[6n\e[?2004h\e[?25l\e[0m\e[?7l\e[0m\e[J\e[0;38;5;67m?\e[0;1m Body. Motivation for the change and contrast this with previous behavior:\e[0m \r\e[100C \e[0m\r\r\n\e[0;1m \e[0m \r\e[100C \r\e[C\e[?7h\e[0m\e[?12l\e[?25h"
170+
- delay: 16
171+
content: "\e[?25l\e[?7l\b\e[0;1m \e[0m \e[0m\e[K\e[0m\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\e[0m \r\e[100C \r\e[12A\e[C\e[?7h\e[0m\e[?12l\e[?25h"
172+
- delay: 5659
173+
content: "\e[?25l\e[?7l\e[0mextends key in config file is now used for extending other config files \b\e[?7h\e[0m\e[?12l\e[?25h\e[?25l\e[?7l\e[?7h\e[0m\e[?12l\e[?25h"
174+
- delay: 647
175+
content: "\e[?25l\e[?7l\e[A\e[72D\e[0m\e[J\e[0;38;5;67m?\e[0;1m Body. Motivation for the change and contrast this with previous behavior:\e[0m \r\e[100C \e[0m\r\r\n\e[0;1m \e[0mextends key in config file is now used for extending other config files \r\e[100C \r\e[0m\r\r\n\e[J\e[?7h\e[0m\e[?12l\e[?25h\e[?2004l"
176+
- delay: 10
177+
content: "\e[?1l\e[6n"
178+
- delay: 5
179+
content: "\e[?2004h\e[?25l\e[0m\e[?7l\e[0m\e[J\e[0;38;5;67m?\e[0;1m Footer. Information about Breaking Changes and reference issues that this commit closes:\e[0m \r\e[100C \e[0m\r\r\n\e[0;1m \e[0m \r\e[100C \r\e[C\e[?7h\e[0m\e[?12l\e[?25h"
180+
- delay: 22
181+
content: "\e[?25l\e[?7l\b\e[0;1m \e[0m \e[0m\e[K\e[0m\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\e[0m \r\e[100C \r\e[10A\e[C\e[?7h\e[0m\e[?12l\e[?25h"
182+
- delay: 1583
183+
content: "\e[?25l\e[?7l\e[A\b\e[0m\e[J\e[0;38;5;67m?\e[0;1m Footer. Information about Breaking Changes and reference issues that this commit closes:\e[0m \r\e[100C \e[0m\r\r\n\e[0;1m \e[0m \r\e[100C \r\e[0m\r\r\n\e[J\e[?7h\e[0m\e[?12l\e[?25h\e[?2004l"
184+
- delay: 6
185+
content: "[master (root-commit) 76d9660] feat: allow provided config object to extend other configs\r\n 1 file changed, 0 insertions(+), 0 deletions(-)\r\n create mode 100644 fil.py\r\n\r\n\e[32mCommit successful!\e[0m\r\n\e[0m"
186+
- delay: 102
187+
content: "\e[1;33m\e[0;32m\e[1;34m\e[1;32msantiago\e[1;34m@\e[1;31mhome\e[1;37m in \e[1;34m~/my-project\e[0;36m |master|\e[1;32m\r\r\n\e[1;32m$\e[00m "

docs/images/demo.gif

390 KB
Loading

docs/index.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ the version or a changelog.
3636

3737
Python 3.6+
3838

39-
[Git][gitscm]
39+
[Git][gitscm] `1.8.5.2`+
4040

4141
## Installation
4242

tests/test_commands.py

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ def test_commit(mocker):
1111
"prefix": "feat",
1212
"subject": "user created",
1313
"scope": "",
14+
"is_breaking_change": False,
1415
"body": "",
1516
"footer": "",
1617
}

0 commit comments

Comments
 (0)