From 0b45d122c68cd7de9e0fbcd9f6cc336bee9371fc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Jan 2026 13:05:40 +0000 Subject: [PATCH 1/3] Bump git/ext/gitdb from `335c0f6` to `4c63ee6` Bumps [git/ext/gitdb](https://github.com/gitpython-developers/gitdb) from `335c0f6` to `4c63ee6`. - [Release notes](https://github.com/gitpython-developers/gitdb/releases) - [Commits](https://github.com/gitpython-developers/gitdb/compare/335c0f66173eecdc7b2597c2b6c3d1fde795df30...4c63ee6636a6a3370f58b05d0bd19fec2f16dd5a) --- updated-dependencies: - dependency-name: git/ext/gitdb dependency-version: 4c63ee6636a6a3370f58b05d0bd19fec2f16dd5a 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..4c63ee663 160000 --- a/git/ext/gitdb +++ b/git/ext/gitdb @@ -1 +1 @@ -Subproject commit 335c0f66173eecdc7b2597c2b6c3d1fde795df30 +Subproject commit 4c63ee6636a6a3370f58b05d0bd19fec2f16dd5a From acc6a8cc83188b107344797cdf6b88398fef0676 Mon Sep 17 00:00:00 2001 From: Ilyas Timour Date: Sat, 10 Jan 2026 11:07:29 +0100 Subject: [PATCH 2/3] DOC: README Add urls and updated a relative url --- README.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 59c6f995b..412d38205 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ by setting the `GIT_PYTHON_GIT_EXECUTABLE=` environment variable. - Git (1.7.x or newer) - Python >= 3.7 -The list of dependencies are listed in `./requirements.txt` and `./test-requirements.txt`. +The list of dependencies are listed in [`./requirements.txt`](https://github.com/gitpython-developers/GitPython/blob/main/requirements.txt) and [`./test-requirements.txt`](https://github.com/gitpython-developers/GitPython/blob/main/test-requirements.txt). The installer takes care of installing them for you. ### INSTALL @@ -180,7 +180,7 @@ Style and formatting checks, and running tests on all the different supported Py #### Configuration files -Specific tools are all configured in the `./pyproject.toml` file: +Specific tools are all configured in the [`./pyproject.toml`](https://github.com/gitpython-developers/GitPython/blob/main/pyproject.toml) file: - `pytest` (test runner) - `coverage.py` (code coverage) @@ -189,9 +189,9 @@ Specific tools are all configured in the `./pyproject.toml` file: Orchestration tools: -- Configuration for `pre-commit` is in the `./.pre-commit-config.yaml` file. -- Configuration for `tox` is in `./tox.ini`. -- Configuration for GitHub Actions (CI) is in files inside `./.github/workflows/`. +- Configuration for `pre-commit` is in the [`./.pre-commit-config.yaml`](https://github.com/gitpython-developers/GitPython/blob/main/.pre-commit-config.yaml) file. +- Configuration for `tox` is in [`./tox.ini`](https://github.com/gitpython-developers/GitPython/blob/main/tox.ini). +- Configuration for GitHub Actions (CI) is in files inside [`./.github/workflows/`](https://github.com/gitpython-developers/GitPython/tree/main/.github/workflows). ### Contributions @@ -212,8 +212,8 @@ Please have a look at the [contributions file][contributing]. ### How to make a new release -1. Update/verify the **version** in the `VERSION` file. -2. Update/verify that the `doc/source/changes.rst` changelog file was updated. It should include a link to the forthcoming release page: `https://github.com/gitpython-developers/GitPython/releases/tag/` +1. Update/verify the **version** in the [`VERSION`](https://github.com/gitpython-developers/GitPython/blob/main/VERSION) file. +2. Update/verify that the [`doc/source/changes.rst`](https://github.com/gitpython-developers/GitPython/blob/main/doc/source/changes.rst) changelog file was updated. It should include a link to the forthcoming release page: `https://github.com/gitpython-developers/GitPython/releases/tag/` 3. Commit everything. 4. Run `git tag -s ` to tag the version in Git. 5. _Optionally_ create and activate a [virtual environment](https://packaging.python.org/en/latest/guides/installing-using-pip-and-virtual-environments/#creating-a-virtual-environment). (Then the next step can install `build` and `twine`.) @@ -240,7 +240,7 @@ Please have a look at the [contributions file][contributing]. [3-Clause BSD License](https://opensource.org/license/bsd-3-clause/), also known as the New BSD License. See the [LICENSE file][license]. -One file exclusively used for fuzz testing is subject to [a separate license, detailed here](./fuzzing/README.md#license). +One file exclusively used for fuzz testing is subject to [a separate license, detailed here](https://github.com/gitpython-developers/GitPython/blob/main/fuzzing/README.md#license). This file is not included in the wheel or sdist packages published by the maintainers of GitPython. [contributing]: https://github.com/gitpython-developers/GitPython/blob/main/CONTRIBUTING.md From 1a74bce18b5492a3cec9b839a4cb706d78eca466 Mon Sep 17 00:00:00 2001 From: danielyan Date: Mon, 9 Feb 2026 20:03:39 +0000 Subject: [PATCH 3/3] Fix GitConfigParser ignoring multiple [include] path entries When an [include] section has multiple entries with the same key (e.g. multiple 'path' values), only the last one was respected. This is because _included_paths() used self.items(section) which delegates to _OMD.items(), and _OMD.__getitem__ returns only the last value for a given key. Fix by using _OMD.items_all() to retrieve all values for each key in the include/includeIf sections, ensuring all paths are processed. Fixes gitpython-developers#2099 --- git/config.py | 18 ++++++++++++++---- test/test_config.py | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 4 deletions(-) diff --git a/git/config.py b/git/config.py index 769929441..c6eaf8f7b 100644 --- a/git/config.py +++ b/git/config.py @@ -549,11 +549,21 @@ def _included_paths(self) -> List[Tuple[str, str]]: :return: The list of paths, where each path is a tuple of (option, value). """ + + def _all_items(section: str) -> List[Tuple[str, str]]: + """Return all (key, value) pairs for a section, including duplicate keys.""" + return [ + (key, value) + for key, values in self._sections[section].items_all() + if key != "__name__" + for value in values + ] + paths = [] for section in self.sections(): if section == "include": - paths += self.items(section) + paths += _all_items(section) match = CONDITIONAL_INCLUDE_REGEXP.search(section) if match is None or self._repo is None: @@ -579,7 +589,7 @@ def _included_paths(self) -> List[Tuple[str, str]]: ) if self._repo.git_dir: if fnmatch.fnmatchcase(os.fspath(self._repo.git_dir), value): - paths += self.items(section) + paths += _all_items(section) elif keyword == "onbranch": try: @@ -589,11 +599,11 @@ def _included_paths(self) -> List[Tuple[str, str]]: continue if fnmatch.fnmatchcase(branch_name, value): - paths += self.items(section) + paths += _all_items(section) elif keyword == "hasconfig:remote.*.url": for remote in self._repo.remotes: if fnmatch.fnmatchcase(remote.url, value): - paths += self.items(section) + paths += _all_items(section) break return paths diff --git a/test/test_config.py b/test/test_config.py index 56ac0f304..11ea52d16 100644 --- a/test/test_config.py +++ b/test/test_config.py @@ -246,6 +246,43 @@ def check_test_value(cr, value): with GitConfigParser(fpa, read_only=True) as cr: check_test_value(cr, tv) + @with_rw_directory + def test_multiple_include_paths_with_same_key(self, rw_dir): + """Test that multiple 'path' entries under [include] are all respected. + + Regression test for https://github.com/gitpython-developers/GitPython/issues/2099. + Git config allows multiple ``path`` values under ``[include]``, e.g.:: + + [include] + path = file1 + path = file2 + + Previously only one of these was included because _OMD.items() returns + only the last value for each key. + """ + # Create two config files to be included. + fp_inc1 = osp.join(rw_dir, "inc1.cfg") + fp_inc2 = osp.join(rw_dir, "inc2.cfg") + fp_main = osp.join(rw_dir, "main.cfg") + + with GitConfigParser(fp_inc1, read_only=False) as cw: + cw.set_value("user", "name", "from-inc1") + + with GitConfigParser(fp_inc2, read_only=False) as cw: + cw.set_value("core", "bar", "from-inc2") + + # Write a config with two path entries under a single [include] section. + # We write it manually because set_value would overwrite the key. + with open(fp_main, "w") as f: + f.write("[include]\n") + f.write(f"\tpath = {fp_inc1}\n") + f.write(f"\tpath = {fp_inc2}\n") + + with GitConfigParser(fp_main, read_only=True) as cr: + # Both included files should be loaded. + assert cr.get_value("user", "name") == "from-inc1" + assert cr.get_value("core", "bar") == "from-inc2" + @pytest.mark.xfail( sys.platform == "win32", reason='Second config._has_includes() assertion fails (for "config is included if path is matching git_dir")',