From 4941c314fc8c38ed6df037c29d4809f7a7fd9af9 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Wed, 6 May 2026 14:52:31 +0800 Subject: [PATCH 1/7] Add AI-disclusure and quality requirements to the contribution guidelines. Co-authored-by: GPT 5.5 --- CONTRIBUTING.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8536d7f73..d8a29f55d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -9,6 +9,35 @@ The following is a short step-by-step rundown of what one typically would do to - Feel free to add yourself to AUTHORS file. - Create a pull request. +## Quality expectations + +Contributions must be made with care and meet the quality bar of the surrounding code. +That means a change should not leave GitPython worse than it was before: it should be +readable, maintainable, tested where practical, documented and consistent with the +existing style and behavior. +A contribution that works only narrowly but lowers the quality of the +codebase may be declined, and the pull request closed without warning. + +## AI-assisted contributions + +If AI edits files for you, disclose it in the pull request description and commit +metadata. Prefer making the agent identity part of the commit, for example by using +an AI author such as `$agent $version ` or a co-author via +a `Co-authored-by: ` trailer. + +Agents operating through a person's GitHub account must identify themselves. For +example, comments posted by an agent should say so directly with phrases like +`AI agent on behalf of : ...`. + +Fully AI-generated comments on pull requests or issues must also be disclosed. +Undisclosed AI-generated comments may lead to the pull request or issue being closed. + +AI-assisted proofreading or wording polish does not need disclosure, but it is still +courteous to mention it when the AI materially influenced the final text. + +Automated or "full-auto" AI contributions without a human responsible for reviewing +and standing behind the work may be closed. + ## Fuzzing Test Specific Documentation For details related to contributing to the fuzzing test suite and OSS-Fuzz integration, please From 92ff6df86b82e94254874b52b05dee9ffe38716b Mon Sep 17 00:00:00 2001 From: Eliah Kagan Date: Wed, 6 May 2026 09:58:33 -0400 Subject: [PATCH 2/7] Separate quality paragraphs and adjust decline wording Split the quality-expectations section into two paragraphs (the warning about low-quality contributions being declined was visually merged with the preceding paragraph). Replace "and the pull request closed without warning" with a note that maintainers may not always be able to provide detailed feedback, which conveys the same practical reality. Co-authored-by: Claude Opus 4.6 --- CONTRIBUTING.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d8a29f55d..60e34a651 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -15,8 +15,10 @@ Contributions must be made with care and meet the quality bar of the surrounding That means a change should not leave GitPython worse than it was before: it should be readable, maintainable, tested where practical, documented and consistent with the existing style and behavior. + A contribution that works only narrowly but lowers the quality of the -codebase may be declined, and the pull request closed without warning. +codebase may be declined. The maintainers may not always be able to provide +detailed feedback. ## AI-assisted contributions From d172e541455679ebdfb55df1411836298cb47b8d Mon Sep 17 00:00:00 2001 From: Matt Van Horn <455140+mvanhorn@users.noreply.github.com> Date: Thu, 7 May 2026 03:20:20 -0700 Subject: [PATCH 3/7] docs(cmd): clarify Git.execute() string vs list command argument Closes #2016 Users routinely hit GitCommandNotFound by passing a single string with spaces to repo.git.execute(...). With shell=False (default) subprocess treats the entire string as the executable name and fails. Document the recommended list form, the string-as-single-executable behavior, and the two ways to coerce a string into argv tokens (shlex.split or shell=True). --- git/cmd.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/git/cmd.py b/git/cmd.py index 78a9f4c78..1ecff9318 100644 --- a/git/cmd.py +++ b/git/cmd.py @@ -1119,9 +1119,16 @@ def execute( information (stdout). :param command: - The command argument list to execute. - It should be a sequence of program arguments, or a string. The - program to execute is the first item in the args sequence or string. + The command to execute. A sequence of program arguments is the + recommended form when `shell` is ``False`` (the default), e.g. + ``["git", "log", "-n", "1"]``. + + A string is accepted, but with `shell` set to ``False`` it is passed + as a single executable name to :class:`subprocess.Popen`. For example, + ``"git log -n 1"`` looks for an executable literally named + ``git log -n 1`` and will fail with :class:`GitCommandNotFound`. To + split a command string into argv tokens, pass ``shlex.split(...)`` as + a sequence or set `shell` to ``True`` (see the warning below). :param istream: Standard input filehandle passed to :class:`subprocess.Popen`. From 010a7bbfd237d2ab0627c20a542933abf978b690 Mon Sep 17 00:00:00 2001 From: Eliah Kagan Date: Fri, 8 May 2026 16:34:31 -0400 Subject: [PATCH 4/7] Rewrite Git.execute() command parameter docstring per #2146 #2146 identifies two factual problems in #2144's `:param command:` rewrite, both of which this fixes: 1. The claim that with `shell=False` a string "is passed as a single executable name to `subprocess.Popen`" is accurate on Unix-like systems, but on Windows `subprocess.Popen` forwards the string to `CreateProcessW` and Windows command-line parsing produces argv. So multi-word strings happen to work on Windows -- which makes the docstring misleading for Windows readers and unhelpful for anyone whose actual problem is portability. 2. The blanket recommendation to use `shlex.split` read as a general string-to-argv splitter. `shlex.split` parses POSIX shell syntax on all systems, and the resulting tokens are still unsafe for anything but fixed, fully trusted strings -- in particular, strings built by interpolating values can still inject extra arguments via embedded whitespace or quoting. Restructure `:param command:` into four paragraphs (description, platform-specific string handling, `shell=True` / `Git.USE_SHELL` warning, qualified `shlex.split` note) and cross-reference `USE_SHELL` for the long-form security discussion rather than reproducing it. Add a related paragraph to `:param shell:` noting `shlex.split`'s narrow value as a transitional tool when migrating existing string-command `shell=True` calls on Unix-like systems, with extreme care, and cross-referencing `:param command:` for the risks. This fixes #2146. Only documentation is changed. Co-authored-by: Claude Opus 4.7 (1M context) --- git/cmd.py | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/git/cmd.py b/git/cmd.py index 7f2564d45..861009099 100644 --- a/git/cmd.py +++ b/git/cmd.py @@ -1131,16 +1131,28 @@ def execute( information (stdout). :param command: - The command to execute. A sequence of program arguments is the - recommended form when `shell` is ``False`` (the default), e.g. - ``["git", "log", "-n", "1"]``. - - A string is accepted, but with `shell` set to ``False`` it is passed - as a single executable name to :class:`subprocess.Popen`. For example, - ``"git log -n 1"`` looks for an executable literally named - ``git log -n 1`` and will fail with :class:`GitCommandNotFound`. To - split a command string into argv tokens, pass ``shlex.split(...)`` as - a sequence or set `shell` to ``True`` (see the warning below). + The command to execute. A sequence of program arguments is recommended. + A string is also accepted, but its meaning is strongly platform-dependent. + + By default, a shell is not used. On Unix-like systems, a string is the whole + program name (so ``"git log -n 1"`` raises :class:`GitCommandNotFound`). On + Windows, the program parses the arguments itself, so multi-word strings can + work but are not portable. + + Avoid ``shell=True`` (and :attr:`Git.USE_SHELL`): this runs the command in + a shell, which is generally unsafe. The shell interprets metacharacters + such as ``;``, ``|``, ``&``, ``$(...)``, ``$VAR``, ``%VAR%``, and ``^`` + (depending on the platform) as syntax. Any untrusted text in the command + can then execute arbitrary OS commands. See :attr:`Git.USE_SHELL`. + + Producing a sequence automatically by :func:`shlex.split` and passing it + as the command is far safer than ``shell=True``. But :func:`shlex.split` + parses POSIX shell syntax on all systems, and the result is still unsafe + for anything but *fixed, fully trusted* strings. Do not use it on strings + built by interpolating values: whitespace or quoting in an untrusted value + can still inject arguments. For input derived in any way from untrusted + data, build the argument sequence yourself, while ensuring each argument + is fully sanitized. :param istream: Standard input filehandle passed to :class:`subprocess.Popen`. @@ -1208,6 +1220,11 @@ def execute( needed (nor useful) to work around any known operating system specific issues. + On Unix-like systems, when migrating away from passing string commands with + ``shell=True``, :func:`shlex.split` may serve as a transitional step in rare + cases, but this should be undertaken with extreme care. See the `command` + parameter above on the risks. + :param env: A dictionary of environment variables to be passed to :class:`subprocess.Popen`. From 38d62c4b60b5cd2ed743c00f2cac1875c76449e0 Mon Sep 17 00:00:00 2001 From: Eliah Kagan Date: Sat, 9 May 2026 21:19:10 -0400 Subject: [PATCH 5/7] Word `shell` mention of `shlex.split` more carefully To avert the mistake of not removing `shell=True` when using it. Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Co-authored-by: Claude Opus 4.7 (1M context) --- git/cmd.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/git/cmd.py b/git/cmd.py index 861009099..98bb62775 100644 --- a/git/cmd.py +++ b/git/cmd.py @@ -1222,8 +1222,8 @@ def execute( On Unix-like systems, when migrating away from passing string commands with ``shell=True``, :func:`shlex.split` may serve as a transitional step in rare - cases, but this should be undertaken with extreme care. See the `command` - parameter above on the risks. + cases, with extreme care. (Drop ``shell=True`` and pass the resulting + sequence as the command.) See the `command` parameter above on the risks. :param env: A dictionary of environment variables to be passed to From 0c1e40982438b46e2e47dc833bccdced779a47db Mon Sep 17 00:00:00 2001 From: Eliah Kagan Date: Sat, 9 May 2026 21:49:47 -0400 Subject: [PATCH 6/7] Document init script behavior when multiple remotes have master When `master` is locally absent and more than one remote has it, `git checkout master --` fails by default even if all remotes agree, and the script falls back to creating `master` at `HEAD`. The reflog populated by the subsequent resets then traces `HEAD`'s history rather than a remote `master`'s. This is harmless, because `master` is reset to `__testing_point__` either way, but unintuitive. Add a comment so a reader of the script does not have to discover this from a confusing run. This fixes #2145. Co-Authored-By: Claude Opus 4.7 (1M context) --- init-tests-after-clone.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/init-tests-after-clone.sh b/init-tests-after-clone.sh index bfada01b0..a88f983fc 100755 --- a/init-tests-after-clone.sh +++ b/init-tests-after-clone.sh @@ -40,6 +40,11 @@ fi git tag __testing_point__ # The tests need a branch called master. +# +# If master is locally absent but more than one remote has it, checkout fails +# by default even if all remotes agree, and we fall back to creating it at +# HEAD. The reflog we populate below then traces HEAD's history rather than +# a remote master's, but master is reset to __testing_point__ either way. git checkout master -- || git checkout -b master # The tests need a reflog history on the master branch. From 465f1d587a13795b35a4b72ad7fafbbe9c7731ac Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 10 May 2026 13:32:12 +0000 Subject: [PATCH 7/7] Bump git/ext/gitdb from `335c0f6` to `0a019a2` Bumps [git/ext/gitdb](https://github.com/gitpython-developers/gitdb) from `335c0f6` to `0a019a2`. - [Release notes](https://github.com/gitpython-developers/gitdb/releases) - [Commits](https://github.com/gitpython-developers/gitdb/compare/335c0f66173eecdc7b2597c2b6c3d1fde795df30...0a019a2e2bd73158cf8b637ad78b5d4b8f15e42e) --- updated-dependencies: - dependency-name: git/ext/gitdb dependency-version: 0a019a2e2bd73158cf8b637ad78b5d4b8f15e42e dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- git/ext/gitdb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git/ext/gitdb b/git/ext/gitdb index 335c0f661..0a019a2e2 160000 --- a/git/ext/gitdb +++ b/git/ext/gitdb @@ -1 +1 @@ -Subproject commit 335c0f66173eecdc7b2597c2b6c3d1fde795df30 +Subproject commit 0a019a2e2bd73158cf8b637ad78b5d4b8f15e42e