feat: add attribute-co-authored-by option for commit attribution

This commit is contained in:
Andrew Grigorev (aider) 2025-04-12 17:39:49 +03:00
parent 482e0c2d0b
commit 4783ad3a73
2 changed files with 38 additions and 47 deletions

View file

@ -428,7 +428,7 @@ def get_parser(default_config_files, git_root):
"--attribute-author", "--attribute-author",
action=argparse.BooleanOptionalAction, action=argparse.BooleanOptionalAction,
default=True, default=True,
help="Attribute aider code changes in the git author name (default: True)", help="Attribute aider code changes in the git author name (default: True, ignored if attribute-co-authored-by is True unless explicitly set)",
) )
group.add_argument( group.add_argument(
"--attribute-committer", "--attribute-committer",

View file

@ -69,6 +69,8 @@ class GitRepo:
self.attribute_committer = attribute_committer self.attribute_committer = attribute_committer
self.attribute_commit_message_author = attribute_commit_message_author self.attribute_commit_message_author = attribute_commit_message_author
self.attribute_commit_message_committer = attribute_commit_message_committer self.attribute_commit_message_committer = attribute_commit_message_committer
# Ensure attribute_co_authored_by is initialized, default to False if not provided
self.attribute_co_authored_by = getattr(self, 'attribute_co_authored_by', False)
self.commit_prompt = commit_prompt self.commit_prompt = commit_prompt
self.subtree_only = subtree_only self.subtree_only = subtree_only
self.git_commit_verify = git_commit_verify self.git_commit_verify = git_commit_verify
@ -124,66 +126,56 @@ class GitRepo:
else: else:
commit_message = self.get_commit_message(diffs, context) commit_message = self.get_commit_message(diffs, context)
commit_message_trailer = "" # Retrieve attribute settings, prioritizing coder.args if available
attribute_author = self.attribute_author
attribute_committer = self.attribute_committer
attribute_commit_message_author = self.attribute_commit_message_author
attribute_commit_message_committer = self.attribute_commit_message_committer
attribute_co_authored_by = False # Default if coder or args not available
if coder and hasattr(coder, "args"): if coder and hasattr(coder, "args"):
attribute_author = coder.args.attribute_author attribute_author = coder.args.attribute_author
attribute_committer = coder.args.attribute_committer attribute_committer = coder.args.attribute_committer
attribute_commit_message_author = coder.args.attribute_commit_message_author attribute_commit_message_author = coder.args.attribute_commit_message_author
attribute_commit_message_committer = coder.args.attribute_commit_message_committer attribute_commit_message_committer = coder.args.attribute_commit_message_committer
attribute_co_authored_by = coder.args.attribute_co_authored_by attribute_co_authored_by = coder.args.attribute_co_authored_by
else:
# Fallback to self attributes (initialized from config/defaults)
attribute_author = self.attribute_author
attribute_committer = self.attribute_committer
attribute_commit_message_author = self.attribute_commit_message_author
attribute_commit_message_committer = self.attribute_commit_message_committer
attribute_co_authored_by = getattr(self, 'attribute_co_authored_by', False)
commit_message_trailer = ""
prefix_commit_message = False
use_attribute_author = False
use_attribute_committer = False
if aider_edits: if aider_edits:
# Add Co-authored-by trailer if configured # Determine commit message prefixing
if attribute_commit_message_author or attribute_commit_message_committer:
prefix_commit_message = True
# Determine author/committer modification and trailer
if attribute_co_authored_by: if attribute_co_authored_by:
model_name = "unknown-model" model_name = "unknown-model"
if coder and hasattr(coder, "main_model") and coder.main_model.name: if coder and hasattr(coder, "main_model") and coder.main_model.name:
model_name = coder.main_model.name model_name = coder.main_model.name
commit_message_trailer = ( commit_message_trailer = f"\n\nCo-authored-by: aider ({model_name}) <noreply@aider.dev>"
f"\n\nCo-authored-by: aider ({model_name}) <noreply@aider.dev>" # Only modify author/committer if explicitly requested alongside co-authored-by
) use_attribute_author = attribute_author
use_attribute_committer = attribute_committer
# Prefix commit message if configured else:
if attribute_commit_message_author or attribute_commit_message_committer: # Original behavior when co-authored-by is false
commit_message = "aider: " + commit_message use_attribute_author = attribute_author
use_attribute_committer = attribute_committer
# Prepare author/committer modification flags (used later) else: # not aider_edits
use_attribute_author = attribute_author # Keep original behavior for non-aider edits
use_attribute_committer = attribute_committer
else:
# Don't modify author/committer/message for non-aider edits
use_attribute_author = False use_attribute_author = False
use_attribute_committer = self.attribute_committer # Keep committer modification for non-aider edits if configured use_attribute_committer = attribute_committer # Respect config for committer
prefix_commit_message = False # Don't prefix non-aider commits
# Use coder.args if available, otherwise default to config/defaults
attribute_author = (
coder.args.attribute_author
if coder and hasattr(coder, "args")
else self.attribute_author
)
attribute_committer = (
coder.args.attribute_committer
if coder and hasattr(coder, "args")
else self.attribute_committer
)
attribute_commit_message_author = (
coder.args.attribute_commit_message_author
if coder and hasattr(coder, "args")
else self.attribute_commit_message_author
)
attribute_commit_message_committer = (
coder.args.attribute_commit_message_committer
if coder and hasattr(coder, "args")
else self.attribute_commit_message_committer
)
if not commit_message: if not commit_message:
commit_message = "(no commit message provided)" commit_message = "(no commit message provided)"
if prefix_commit_message:
commit_message = "aider: " + commit_message
full_commit_message = commit_message + commit_message_trailer full_commit_message = commit_message + commit_message_trailer
# if context: # if context:
# full_commit_message += "\n\n# Aider chat conversation:\n\n" + context # full_commit_message += "\n\n# Aider chat conversation:\n\n" + context
@ -210,8 +202,7 @@ class GitRepo:
# Apply author/committer modifications based on flags determined earlier # Apply author/committer modifications based on flags determined earlier
if use_attribute_committer: if use_attribute_committer:
os.environ["GIT_COMMITTER_NAME"] = committer_name os.environ["GIT_COMMITTER_NAME"] = committer_name
if use_attribute_author:
if use_attribute_author: # Already checks for aider_edits implicitly
os.environ["GIT_AUTHOR_NAME"] = committer_name os.environ["GIT_AUTHOR_NAME"] = committer_name
try: try:
@ -229,7 +220,7 @@ class GitRepo:
elif "GIT_COMMITTER_NAME" in os.environ: elif "GIT_COMMITTER_NAME" in os.environ:
del os.environ["GIT_COMMITTER_NAME"] del os.environ["GIT_COMMITTER_NAME"]
if use_attribute_author: # Already checks for aider_edits implicitly if use_attribute_author:
if original_author_name_env is not None: if original_author_name_env is not None:
os.environ["GIT_AUTHOR_NAME"] = original_author_name_env os.environ["GIT_AUTHOR_NAME"] = original_author_name_env
elif "GIT_AUTHOR_NAME" in os.environ: elif "GIT_AUTHOR_NAME" in os.environ: