git-commit-message 0.9.0__tar.gz → 0.9.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (21) hide show
  1. {git_commit_message-0.9.0 → git_commit_message-0.9.1}/PKG-INFO +3 -2
  2. {git_commit_message-0.9.0 → git_commit_message-0.9.1}/pyproject.toml +3 -2
  3. {git_commit_message-0.9.0 → git_commit_message-0.9.1}/src/git_commit_message/_cli.py +44 -0
  4. {git_commit_message-0.9.0 → git_commit_message-0.9.1}/src/git_commit_message/_git.py +74 -0
  5. {git_commit_message-0.9.0 → git_commit_message-0.9.1}/src/git_commit_message/_llm.py +35 -7
  6. {git_commit_message-0.9.0 → git_commit_message-0.9.1}/src/git_commit_message.egg-info/PKG-INFO +3 -2
  7. {git_commit_message-0.9.0 → git_commit_message-0.9.1}/README.md +0 -0
  8. {git_commit_message-0.9.0 → git_commit_message-0.9.1}/UNLICENSE +0 -0
  9. {git_commit_message-0.9.0 → git_commit_message-0.9.1}/setup.cfg +0 -0
  10. {git_commit_message-0.9.0 → git_commit_message-0.9.1}/src/git_commit_message/__init__.py +0 -0
  11. {git_commit_message-0.9.0 → git_commit_message-0.9.1}/src/git_commit_message/__main__.py +0 -0
  12. {git_commit_message-0.9.0 → git_commit_message-0.9.1}/src/git_commit_message/_config.py +0 -0
  13. {git_commit_message-0.9.0 → git_commit_message-0.9.1}/src/git_commit_message/_gemini.py +0 -0
  14. {git_commit_message-0.9.0 → git_commit_message-0.9.1}/src/git_commit_message/_gpt.py +0 -0
  15. {git_commit_message-0.9.0 → git_commit_message-0.9.1}/src/git_commit_message/_llamacpp.py +0 -0
  16. {git_commit_message-0.9.0 → git_commit_message-0.9.1}/src/git_commit_message/_ollama.py +0 -0
  17. {git_commit_message-0.9.0 → git_commit_message-0.9.1}/src/git_commit_message.egg-info/SOURCES.txt +0 -0
  18. {git_commit_message-0.9.0 → git_commit_message-0.9.1}/src/git_commit_message.egg-info/dependency_links.txt +0 -0
  19. {git_commit_message-0.9.0 → git_commit_message-0.9.1}/src/git_commit_message.egg-info/entry_points.txt +0 -0
  20. {git_commit_message-0.9.0 → git_commit_message-0.9.1}/src/git_commit_message.egg-info/requires.txt +0 -0
  21. {git_commit_message-0.9.0 → git_commit_message-0.9.1}/src/git_commit_message.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: git-commit-message
3
- Version: 0.9.0
3
+ Version: 0.9.1
4
4
  Summary: Generate Git commit messages from staged changes using LLM
5
5
  Maintainer-email: Mina Her <minacle@live.com>
6
6
  License: This is free and unencumbered software released into the public domain.
@@ -31,7 +31,7 @@ License: This is free and unencumbered software released into the public domain.
31
31
  Project-URL: Homepage, https://github.com/minacle/git-commit-message
32
32
  Project-URL: Repository, https://github.com/minacle/git-commit-message
33
33
  Project-URL: Issues, https://github.com/minacle/git-commit-message/issues
34
- Classifier: Development Status :: 3 - Alpha
34
+ Classifier: Development Status :: 4 - Beta
35
35
  Classifier: Environment :: Console
36
36
  Classifier: Intended Audience :: Developers
37
37
  Classifier: License :: OSI Approved :: The Unlicense (Unlicense)
@@ -40,6 +40,7 @@ Classifier: Programming Language :: Python
40
40
  Classifier: Programming Language :: Python :: 3
41
41
  Classifier: Programming Language :: Python :: 3 :: Only
42
42
  Classifier: Programming Language :: Python :: 3.13
43
+ Classifier: Programming Language :: Python :: 3.14
43
44
  Classifier: Topic :: Software Development :: Version Control :: Git
44
45
  Requires-Python: >=3.13
45
46
  Description-Content-Type: text/markdown
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "git-commit-message"
3
- version = "0.9.0"
3
+ version = "0.9.1"
4
4
  description = "Generate Git commit messages from staged changes using LLM"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.13"
@@ -13,7 +13,7 @@ dependencies = [
13
13
  maintainers = [{ name = "Mina Her", email = "minacle@live.com" }]
14
14
  license = { file = "UNLICENSE" }
15
15
  classifiers = [
16
- "Development Status :: 3 - Alpha",
16
+ "Development Status :: 4 - Beta",
17
17
  "Environment :: Console",
18
18
  "Intended Audience :: Developers",
19
19
  "License :: OSI Approved :: The Unlicense (Unlicense)",
@@ -22,6 +22,7 @@ classifiers = [
22
22
  "Programming Language :: Python :: 3",
23
23
  "Programming Language :: Python :: 3 :: Only",
24
24
  "Programming Language :: Python :: 3.13",
25
+ "Programming Language :: Python :: 3.14",
25
26
  "Topic :: Software Development :: Version Control :: Git",
26
27
  ]
27
28
 
@@ -17,6 +17,8 @@ from typing import Final
17
17
 
18
18
  from ._git import (
19
19
  commit_with_message,
20
+ get_current_branch,
21
+ get_git_log,
20
22
  get_repo_root,
21
23
  get_staged_diff,
22
24
  has_head_commit,
@@ -47,6 +49,9 @@ class CliArgs(Namespace):
47
49
  "max_length",
48
50
  "chunk_tokens",
49
51
  "diff_context",
52
+ "no_branch",
53
+ "no_log",
54
+ "log_count",
50
55
  "host",
51
56
  "co_authors",
52
57
  )
@@ -68,6 +73,9 @@ class CliArgs(Namespace):
68
73
  self.max_length: int | None = None
69
74
  self.chunk_tokens: int | None = None
70
75
  self.diff_context: int | None = None
76
+ self.no_branch: bool = False
77
+ self.no_log: bool = False
78
+ self.log_count: int = 10
71
79
  self.host: str | None = None
72
80
  self.co_authors: list[str] | None = None
73
81
 
@@ -304,6 +312,31 @@ def _build_parser() -> ArgumentParser:
304
312
  ),
305
313
  )
306
314
 
315
+ parser.add_argument(
316
+ "--no-branch",
317
+ dest="no_branch",
318
+ action="store_true",
319
+ help="Do not include the current branch name in the LLM context.",
320
+ )
321
+
322
+ parser.add_argument(
323
+ "--no-log",
324
+ dest="no_log",
325
+ action="store_true",
326
+ help="Do not include recent Git log entries in the LLM context.",
327
+ )
328
+
329
+ parser.add_argument(
330
+ "--log-count",
331
+ dest="log_count",
332
+ type=int,
333
+ default=10,
334
+ help=(
335
+ "Number of recent Git log entries to include in the LLM context "
336
+ "(default: 10). Ignored when --no-log is set."
337
+ ),
338
+ )
339
+
307
340
  parser.add_argument(
308
341
  "--host",
309
342
  dest="host",
@@ -370,6 +403,10 @@ def _run(
370
403
  print("--diff-context must be greater than or equal to 0.", file=stderr)
371
404
  return 2
372
405
 
406
+ if not args.no_log and args.log_count < 1:
407
+ print("--log-count must be greater than or equal to 1.", file=stderr)
408
+ return 2
409
+
373
410
  provider_name: str = resolve_provider_name(args.provider)
374
411
  provider_arg_error = validate_provider_chunk_tokens(provider_name, chunk_tokens)
375
412
  if provider_arg_error is not None:
@@ -396,6 +433,9 @@ def _run(
396
433
 
397
434
  diff_text = get_staged_diff(repo_root, context_lines=diff_context)
398
435
 
436
+ branch: str | None = None if args.no_branch else get_current_branch(repo_root)
437
+ log: str | None = None if args.no_log else get_git_log(repo_root, count=args.log_count)
438
+
399
439
  hint: str | None = args.description if isinstance(args.description, str) else None
400
440
 
401
441
  normalized_co_authors: list[str] | None = None
@@ -420,6 +460,8 @@ def _run(
420
460
  args.provider,
421
461
  args.host,
422
462
  args.conventional,
463
+ branch=branch,
464
+ log=log,
423
465
  )
424
466
  message = result.message
425
467
  else:
@@ -434,6 +476,8 @@ def _run(
434
476
  args.provider,
435
477
  args.host,
436
478
  args.conventional,
479
+ branch=branch,
480
+ log=log,
437
481
  )
438
482
  except UnsupportedProviderError as exc:
439
483
  print(str(exc), file=stderr)
@@ -232,6 +232,80 @@ def get_staged_diff(
232
232
  return out.decode()
233
233
 
234
234
 
235
+ def get_current_branch(
236
+ cwd: Path,
237
+ /,
238
+ ) -> str | None:
239
+ """Return the current branch name, or ``None`` if HEAD is detached.
240
+
241
+ Parameters
242
+ ----------
243
+ cwd
244
+ Repository directory in which to run Git.
245
+
246
+ Returns
247
+ -------
248
+ str | None
249
+ Branch name, or ``None`` when HEAD is detached or the command fails.
250
+ """
251
+
252
+ completed = run(
253
+ ["git", "branch", "--show-current"],
254
+ cwd=str(cwd),
255
+ check=False,
256
+ capture_output=True,
257
+ )
258
+ if completed.returncode != 0:
259
+ return None
260
+ name = completed.stdout.decode().strip()
261
+ return name or None
262
+
263
+
264
+ def get_git_log(
265
+ cwd: Path,
266
+ /,
267
+ *,
268
+ count: int = 10,
269
+ ) -> str | None:
270
+ """Return recent Git log entries as formatted text.
271
+
272
+ Parameters
273
+ ----------
274
+ cwd
275
+ Repository directory in which to run Git.
276
+ count
277
+ Maximum number of commits to include.
278
+
279
+ Returns
280
+ -------
281
+ str | None
282
+ Formatted log text, or ``None`` if the repository has no commits
283
+ or if ``git log`` fails.
284
+ """
285
+
286
+ if count < 1:
287
+ raise ValueError(f"count must be >= 1, got {count}")
288
+
289
+ if not has_head_commit(cwd):
290
+ return None
291
+
292
+ try:
293
+ out: bytes = check_output(
294
+ [
295
+ "git",
296
+ "log",
297
+ f"-{count}",
298
+ "--format=%h %s%n%n%b%n---%n",
299
+ ],
300
+ cwd=str(cwd),
301
+ )
302
+ except CalledProcessError:
303
+ return None
304
+
305
+ text = out.decode().strip()
306
+ return text or None
307
+
308
+
235
309
  def commit_with_message(
236
310
  message: str,
237
311
  edit: bool,
@@ -298,12 +298,19 @@ def _build_combined_prompt(
298
298
  hint: str | None,
299
299
  content_label: str = "Changes (diff)",
300
300
  /,
301
+ *,
302
+ branch: str | None = None,
303
+ log: str | None = None,
301
304
  ) -> str:
302
- hint_content: str | None = (
303
- f"# Auxiliary context (user-provided)\n{hint}" if hint else None
304
- )
305
- content: str = f"# {content_label}\n{diff}"
306
- return "\n\n".join([part for part in (hint_content, content) if part is not None])
305
+ parts: list[str] = []
306
+ if hint:
307
+ parts.append(f"# Auxiliary context (user-provided)\n{hint}")
308
+ if branch:
309
+ parts.append(f"# Current branch\n{branch}")
310
+ if log:
311
+ parts.append(f"# Recent commits\n{log}")
312
+ parts.append(f"# {content_label}\n{diff}")
313
+ return "\n\n".join(parts)
307
314
 
308
315
 
309
316
  def _split_diff_into_hunks(
@@ -423,6 +430,9 @@ def _generate_commit_from_summaries(
423
430
  language: str,
424
431
  conventional: bool = False,
425
432
  /,
433
+ *,
434
+ branch: str | None = None,
435
+ log: str | None = None,
426
436
  ) -> LLMTextResult:
427
437
  instructions = _build_system_prompt(single_line, subject_max, language, conventional)
428
438
  sections: list[str] = []
@@ -430,6 +440,12 @@ def _generate_commit_from_summaries(
430
440
  if hint:
431
441
  sections.append(f"# Auxiliary context (user-provided)\n{hint}")
432
442
 
443
+ if branch:
444
+ sections.append(f"# Current branch\n{branch}")
445
+
446
+ if log:
447
+ sections.append(f"# Recent commits\n{log}")
448
+
433
449
  if summaries:
434
450
  numbered = [
435
451
  f"Summary {idx + 1}:\n{summary}" for idx, summary in enumerate(summaries)
@@ -490,6 +506,9 @@ def generate_commit_message(
490
506
  host: str | None = None,
491
507
  conventional: bool = False,
492
508
  /,
509
+ *,
510
+ branch: str | None = None,
511
+ log: str | None = None,
493
512
  ) -> str:
494
513
  chosen_provider = resolve_provider_name(provider)
495
514
  chosen_model = resolve_model_name(model, chosen_provider)
@@ -523,11 +542,13 @@ def generate_commit_message(
523
542
  subject_max,
524
543
  chosen_language,
525
544
  conventional,
545
+ branch=branch,
546
+ log=log,
526
547
  )
527
548
  text = (final.text or "").strip()
528
549
  else:
529
550
  instructions = _build_system_prompt(single_line, subject_max, chosen_language, conventional)
530
- user_text = _build_combined_prompt(diff, hint)
551
+ user_text = _build_combined_prompt(diff, hint, branch=branch, log=log)
531
552
  final = llm.generate_text(
532
553
  model=chosen_model,
533
554
  instructions=instructions,
@@ -553,6 +574,9 @@ def generate_commit_message_with_info(
553
574
  host: str | None = None,
554
575
  conventional: bool = False,
555
576
  /,
577
+ *,
578
+ branch: str | None = None,
579
+ log: str | None = None,
556
580
  ) -> CommitMessageResult:
557
581
  chosen_provider = resolve_provider_name(provider)
558
582
  chosen_model = resolve_model_name(model, chosen_provider)
@@ -588,12 +612,16 @@ def generate_commit_message_with_info(
588
612
  subject_max,
589
613
  chosen_language,
590
614
  conventional,
615
+ branch=branch,
616
+ log=log,
591
617
  )
592
618
 
593
619
  combined_prompt = _build_combined_prompt(
594
620
  "\n".join(summary_texts),
595
621
  hint,
596
622
  "Combined summaries (English)",
623
+ branch=branch,
624
+ log=log,
597
625
  )
598
626
 
599
627
  prompt_tokens, completion_tokens, total_tokens = _sum_usage(
@@ -605,7 +633,7 @@ def generate_commit_message_with_info(
605
633
 
606
634
  else:
607
635
  instructions = _build_system_prompt(single_line, subject_max, chosen_language, conventional)
608
- combined_prompt = _build_combined_prompt(diff, hint)
636
+ combined_prompt = _build_combined_prompt(diff, hint, branch=branch, log=log)
609
637
 
610
638
  final_result = llm.generate_text(
611
639
  model=chosen_model,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: git-commit-message
3
- Version: 0.9.0
3
+ Version: 0.9.1
4
4
  Summary: Generate Git commit messages from staged changes using LLM
5
5
  Maintainer-email: Mina Her <minacle@live.com>
6
6
  License: This is free and unencumbered software released into the public domain.
@@ -31,7 +31,7 @@ License: This is free and unencumbered software released into the public domain.
31
31
  Project-URL: Homepage, https://github.com/minacle/git-commit-message
32
32
  Project-URL: Repository, https://github.com/minacle/git-commit-message
33
33
  Project-URL: Issues, https://github.com/minacle/git-commit-message/issues
34
- Classifier: Development Status :: 3 - Alpha
34
+ Classifier: Development Status :: 4 - Beta
35
35
  Classifier: Environment :: Console
36
36
  Classifier: Intended Audience :: Developers
37
37
  Classifier: License :: OSI Approved :: The Unlicense (Unlicense)
@@ -40,6 +40,7 @@ Classifier: Programming Language :: Python
40
40
  Classifier: Programming Language :: Python :: 3
41
41
  Classifier: Programming Language :: Python :: 3 :: Only
42
42
  Classifier: Programming Language :: Python :: 3.13
43
+ Classifier: Programming Language :: Python :: 3.14
43
44
  Classifier: Topic :: Software Development :: Version Control :: Git
44
45
  Requires-Python: >=3.13
45
46
  Description-Content-Type: text/markdown