Skip to content

Commit b5d86a1

Browse files
EliahKaganclaude
andcommitted
Clarify Git.execute() string semantics on Windows and shlex caveat
gitpython-developers#2144 stated that with shell=False, a string command is passed as a single executable name. That is correct on POSIX, but on Windows subprocess.Popen forwards the string to CreateProcessW and Windows command-line parsing rules produce the program's argv. So a multi-word command string like "git version" actually runs on Windows. It also recommended shlex.split() for tokenizing a string into argv. The shlex module is intended only for Unix shells; its tokenization can diverge from Windows command-line conventions, with possible security implications when the input is not fully trusted. Rewrite the :param command: block to keep gitpython-developers#2144's recommendation to use the sequence form and its helpful POSIX failure-mode example, add an explicit Windows bullet describing the OS-side parsing, and note shlex.split's POSIX-only nature. This is documentation only; behavior is unchanged. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 7b83f7a commit b5d86a1

1 file changed

Lines changed: 26 additions & 10 deletions

File tree

git/cmd.py

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1131,16 +1131,32 @@ def execute(
11311131
information (stdout).
11321132
11331133
:param command:
1134-
The command to execute. A sequence of program arguments is the
1135-
recommended form when `shell` is ``False`` (the default), e.g.
1136-
``["git", "log", "-n", "1"]``.
1137-
1138-
A string is accepted, but with `shell` set to ``False`` it is passed
1139-
as a single executable name to :class:`subprocess.Popen`. For example,
1140-
``"git log -n 1"`` looks for an executable literally named
1141-
``git log -n 1`` and will fail with :class:`GitCommandNotFound`. To
1142-
split a command string into argv tokens, pass ``shlex.split(...)`` as
1143-
a sequence or set `shell` to ``True`` (see the warning below).
1134+
The command to execute. A sequence of program arguments, e.g.
1135+
``["git", "log", "-n", "1"]``, is the recommended form: the tokens
1136+
are passed to the program unchanged on every platform.
1137+
1138+
A string is also accepted, but how it is interpreted depends on
1139+
the platform when `shell` is ``False`` (the default), because
1140+
:meth:`Git.execute` delegates to :class:`subprocess.Popen`:
1141+
1142+
* On POSIX, the entire string is taken as the executable name; no
1143+
tokenization is performed. ``"git log -n 1"`` therefore looks
1144+
for an executable literally named ``git log -n 1`` and fails
1145+
with :class:`GitCommandNotFound`.
1146+
* On Windows, the string is passed unchanged to the underlying
1147+
``CreateProcessW`` API, and Windows command-line parsing rules
1148+
determine the tokens the called program receives in its argv.
1149+
``"git log -n 1"`` therefore runs ``git`` with arguments
1150+
``log``, ``-n``, and ``1``.
1151+
1152+
To split a command string into argv tokens portably, construct
1153+
the sequence form yourself. :func:`shlex.split` is a tempting
1154+
shortcut, but :mod:`shlex` is intended only for Unix-style
1155+
shells; its tokenization can diverge from Windows command-line
1156+
conventions, with possible security implications when the input
1157+
is not fully trusted. Setting `shell` to ``True`` instead causes
1158+
the platform's shell to tokenize the string, but see the warning
1159+
on the `shell` parameter below before relying on that.
11441160
11451161
:param istream:
11461162
Standard input filehandle passed to :class:`subprocess.Popen`.

0 commit comments

Comments
 (0)