Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: gitpython-developers/GitPython
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 3.2.0
Choose a base ref
...
head repository: gitpython-developers/GitPython
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: main
Choose a head ref
  • 20 commits
  • 11 files changed
  • 8 contributors

Commits on Sep 30, 2026

  1. Merge pull request #2260 from gitpython-developers/new-release

    prepare for next release, v3.2
    Byron authored Sep 30, 2026
    Configuration menu
    Copy the full SHA
    2d7f566 View commit details
    Browse the repository at this point in the history

Commits on Oct 1, 2026

  1. objects: decode a byte mode before reading its digits

    mode_str_to_int(b"100644") returned 1830740. A byte is an int, so the
    digit 4 was read as 52. A text mode was already 0o100644.
    SashaMIT committed Oct 1, 2026
    Configuration menu
    Copy the full SHA
    62266da View commit details
    Browse the repository at this point in the history
  2. Merge pull request #2261 from SashaMIT/decode-byte-mode

    objects: decode a byte mode before reading its digits
    Byron authored Oct 1, 2026
    Configuration menu
    Copy the full SHA
    bda18e0 View commit details
    Browse the repository at this point in the history
  3. build(deps): bump https://github.com/astral-sh/ruff-pre-commit

    Bumps the pre-commit group with 1 update: [https://github.com/astral-sh/ruff-pre-commit](https://github.com/astral-sh/ruff-pre-commit).
    
    
    Updates `https://github.com/astral-sh/ruff-pre-commit` from v0.16.5 to 0.16.9
    - [Release notes](https://github.com/astral-sh/ruff-pre-commit/releases)
    - [Commits](astral-sh/ruff-pre-commit@v0.16.5...v0.16.9)
    
    ---
    updated-dependencies:
    - dependency-name: https://github.com/astral-sh/ruff-pre-commit
      dependency-version: 0.16.9
      dependency-type: direct:production
      dependency-group: pre-commit
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    dependabot[bot] authored Oct 1, 2026
    Configuration menu
    Copy the full SHA
    f24ed41 View commit details
    Browse the repository at this point in the history
  4. Merge pull request #2263 from gitpython-developers/dependabot/pre_com…

    …mit/pre-commit-96dc14c7b5
    
    build(deps): bump https://github.com/astral-sh/ruff-pre-commit from v0.16.5 to 0.16.9 in the pre-commit group
    Byron authored Oct 1, 2026
    Configuration menu
    Copy the full SHA
    6fe40b7 View commit details
    Browse the repository at this point in the history

Commits on Oct 2, 2026

  1. fix(submodule): validate destinations before mutation

    <!-- Byron -->
    
    Pretty much a rubber-stamp. It won't be out there long as the replacement
    with CLI + Gix is already on the way.
    
    <!-- agent -->
    Submodule checkout destinations could pass the containment check and be
    rejected by the index only after cloning had changed the filesystem. This
    addresses `GHSA-83vg-56qc-22m7` at the shared destination boundaries, including
    initialization and moves as well as creation.
    
    Reuse `_validate_repo_path` before checkout mutations to enforce portable
    NTFS/HFS metadata-alias checks and invalid-path rejection. Validate Windows
    filenames and submodule-name NULs before creating directories. Compare path
    components with `Repo.git_dir` and `Repo.common_dir` by filesystem identity,
    so separately named metadata directories and their aliases are protected too.
    
    Reject metadata destinations nested inside another submodule's Git directory
    before cloning, reuse, or renaming. Repeat the check after cloning and disable
    a clone that became nested. Preflight implicit metadata renames during moves,
    while preserving supported metadata symlinks and relocation of a submodule's
    own metadata directory.
    
    Git reference: `d38352cd43ab9745686d697872408bc3249a153f`, particularly
    `read-cache.c::verify_path_internal`, NTFS/HFS recognition,
    `compat/mingw.c::is_valid_win32_path`, and
    `submodule.c::validate_submodule_git_dir`. Related Git tests are in
    `t/t7450-bad-git-dotfiles.sh` and `t/t7406-submodule-update.sh`.
    
    Regression tests first demonstrated writes before rejection and acceptance
    of nested and separately named metadata destinations. Tests use harmless
    file content and compare portable aliases with native Git index validation.
    Coverage includes all 16 HFS ignored characters, Windows filename rules,
    relative and absolute paths, metadata reuse, and nesting during cloning.
    
    Assisted-by: GPT 6.0 Astra
    Co-authored-by: GPT 6.0 Astra <codex@openai.com>
    Byron and codex committed Oct 2, 2026
    Configuration menu
    Copy the full SHA
    97eadb8 View commit details
    Browse the repository at this point in the history
  2. fix(util): create lock files in one exclusive step

    `LockFile._obtain_lock_or_raise()` tested for the lock with `osp.isfile()`
    and then created it with `open(lock_file, "w")`. Nothing keeps another
    holder out between the two calls, so several can pass the test and all of
    them set `_owns_lock`. Racing eight holders on one lock file leaves seven
    believing they own it, which removes the mutual exclusion that
    `GitConfigParser` in write mode and `RefLog.append_entry()` rely on.
    
    `osp.isfile()` also resolves symbolic links. A dangling symlink planted at
    `<file>.lock` therefore reports no lock, and the following `open()` resolves
    it and creates the target, outside the repository.
    
    Create the lock with `os.open(lock_file, os.O_WRONLY | os.O_CREAT |
    os.O_EXCL, 0o600)` instead. That is the single-step exclusive create
    `gitdb`'s `LockedFD.open()` and Git's own `lock_file()` already use, and
    `O_EXCL` fails with `EEXIST` on a symbolic link rather than resolving it, so
    both problems close together. The creation mode matches `LockedFD`; nothing
    reads a lock file's contents, and breaking a stale lock needs write
    permission on the containing directory rather than on the file.
    
    `FileExistsError` is translated back into the existing "did already exist"
    `OSError`, so `BlockingLockFile`'s retry loop and the existing
    `test_lock_file` and `test_blocking_lock_file` cases are unaffected. A
    directory at the lock path is still reported through the generic `OSError`
    branch. This covers acquiring the lock only; writing the locked file stays
    the caller's concern, as before.
    
    Adds `test_lock_file_does_not_follow_a_symlink` and
    `test_lock_file_is_obtained_by_a_single_holder`. Both fail on the previous
    code (`1 != 7`, and the symlink target gets created) and pass here.
    Validation: full `pytest` suite green on Python 3.11 on macOS, plus `ruff
    check`, `ruff format`, `mypy` and `basedpyright --warnings` clean.
    Keerthana-64 committed Oct 2, 2026
    Configuration menu
    Copy the full SHA
    b0ae041 View commit details
    Browse the repository at this point in the history
  3. Merge pull request #2264 from gitpython-developers/submodule-destinat…

    …ion-fix
    
    fix(submodule): validate destinations before mutation
    Byron authored Oct 2, 2026
    Configuration menu
    Copy the full SHA
    f3ee6d4 View commit details
    Browse the repository at this point in the history
  4. fix(util): acquire Windows locks without following symlinks

    <!-- Byron -->
    
    Took brief look only. Hope this code soon won't be present anymore.
    
    <!-- agent -->
    Windows follows dangling symlinks even when `os.open` uses `O_CREAT | O_EXCL`,
    so acquiring a lock could create its symlink target and incorrectly report
    ownership. The `_winapi.CreateFile` workaround also uses the ANSI API on
    Python 3.8 through 3.10, causing failures in Unicode directories or creating
    locks under mangled filenames.
    
    Use `CreateFileW` with `CREATE_NEW` and `FILE_FLAG_OPEN_REPARSE_POINT` to
    create the lock atomically while rejecting existing links. Declare the
    `ctypes` argument and return types explicitly so Unicode paths and native
    handle sizes are preserved. Close the handle before recording ownership,
    propagate Windows errors, and reject embedded NULs before the native API
    can truncate a path. Preserve exclusive `os.open` creation on POSIX.
    
    Expand the lock tests to cover Unicode filenames and directories, including
    non-BMP characters, and verify that the requested lock path is actually
    created and removed. Check NUL rejection, preserve both existing and missing
    symlink targets, and explicitly release the concurrent test's acquired locks.
    
    Reproduced the CI failure in `test_clone_from_with_path_contains_unicode`
    on Windows/Python 3.8.10 before the fix. The affected utility, clone, and
    configuration modules pass on Python 3.8.10 and 3.13.14: 169 passed,
    41 skipped, and 2 expected failures on each version. The new Unicode and
    NUL regressions also failed before their respective fixes. `ruff check`,
    `ruff format --check`, `mypy --python-version=3.13`, and
    `basedpyright --warnings` pass.
    
    Assisted-by: GPT 6.0 Astra
    Co-authored-by: GPT 6 <codex@openai.com>
    Byron and codex committed Oct 2, 2026
    Configuration menu
    Copy the full SHA
    97a5468 View commit details
    Browse the repository at this point in the history
  5. Merge pull request #2267 from radhika1314/lock-file-exclusive-create

    fix(util): create lock files in one exclusive step
    Byron authored Oct 2, 2026
    Configuration menu
    Copy the full SHA
    6306c5c View commit details
    Browse the repository at this point in the history
  6. fix(commit): accumulate gpgsig continuation lines in linear time

    `Commit._deserialize` collected a `gpgsig` header by appending each
    continuation line to a `bytes` object with `+=`. `bytes` are immutable, so
    every line copied the whole signature read so far, and a signature with *n*
    continuation lines cost O(n^2) to parse.
    
    Commit headers are fully controlled by whoever wrote the commit, and
    `_deserialize` runs on the first access to any commit attribute (`author`,
    `message`, `parents`, ...). Reading the commits of an untrusted repository is
    therefore enough to hit it. Measured on Python 3.11 with a `gpgsig` header of
    `" x\n"` lines:
    
    | object size | before  | after  |
    | ----------- | ------- | ------ |
    | 2.4 MB      | 9.5 s   | 0.08 s |
    | 4.8 MB      | 116.8 s |        |
    | 9.6 MB      | 547.9 s | 0.32 s |
    
    Collect the lines in a list and join them once. This is linear and produces
    byte-identical `gpgsig` values, so the existing `test_gpgsig` round trip is
    unchanged.
    
    `test_gpgsig_deserialization_is_linear` deserializes a 1.8 MB signature under
    a 1 s CPU-time bound. It fails on the previous code and passes here. The full
    suite has no new failures; the 8 tests that fail locally (non-UTF-8 trailer
    encoding and NUL submodule names) fail identically without this change.
    `ruff`, `mypy` and `basedpyright --warnings` are clean.
    Keerthana-64 committed Oct 2, 2026
    Configuration menu
    Copy the full SHA
    226654a View commit details
    Browse the repository at this point in the history

Commits on Oct 3, 2026

  1. review

    - remove test as it can totally fail on slow runners, and extending the time budget makes it hard to see if it's actually working.
      Let's trust what we see and look forward to a time when the in-python parsing is gone as well.
    Byron committed Oct 3, 2026
    Configuration menu
    Copy the full SHA
    5fc5f34 View commit details
    Browse the repository at this point in the history
  2. Merge pull request #2268 from Keerthana-64/gpgsig-linear-parse

    fix(commit): accumulate gpgsig continuation lines in linear time
    Byron authored Oct 3, 2026
    Configuration menu
    Copy the full SHA
    574aec2 View commit details
    Browse the repository at this point in the history
  3. fix(index): accept a single PathLike in checkout

    `IndexFile.checkout()` documents accepting a single path, but only wraps
    strings before iterating. Passing one `pathlib.Path` or custom
    `os.PathLike` therefore raises `TypeError`, while a list containing the
    same object already works.
    
    Wrap single `os.PathLike` objects along with strings and widen the public
    annotation. Keep existing path normalization and iterable behavior.
    
    Add 36 real-repository cases covering path types, absolute and relative
    paths, files and directories, and single/list/iterator inputs. Eight
    single-PathLike cases failed before this fix. The focused tests pass,
    as do all pre-commit hooks, `mypy`, `basedpyright`, and strict Sphinx HTML.
    The full suite has 1,410 passing tests and 121 Windows symlink-privilege
    failures, all reproduced with identical node IDs on the pristine base.
    
    Assisted-by: OpenAI GPT-6 <noreply@openai.com>
    kokotatan committed Oct 3, 2026
    Configuration menu
    Copy the full SHA
    6795806 View commit details
    Browse the repository at this point in the history

Commits on Oct 5, 2026

  1. fix(util): redact URL credentials without corrupting the host

    remove_password_if_present() redacted credentials by substituting them
    into url.netloc with str.replace(), which rewrites every occurrence
    anywhere in the netloc -- including the host.
    
      https://git@github.com/user/repo.git
        -> https://*****@*****hub.com/user/repo.git
    
    "git" is the most common Git username and a substring of "github.com",
    so this hits the common case. An empty username or password makes it
    worse: str.replace("", "*****") matches at every position, so
    
      https://:token@fakerepo.example.com/testrepo
    
    comes back shredded into a URL roughly ten times longer, which is what
    lands in GitCommandError messages when a fetch fails.
    
    Rebuild the netloc from its userinfo instead, so only the credentials
    are replaced. The existing test already covered the empty-password case
    but only asserted the password is absent, which any mangling satisfies.
    
    The function is the single redaction path used for logged command lines
    and for exception messages (git/cmd.py, git/exc.py, git/repo/base.py),
    so this fixes all of them at once.
    yunaremaia committed Oct 5, 2026
    Configuration menu
    Copy the full SHA
    6fdfa31 View commit details
    Browse the repository at this point in the history
  2. review

    - add some edge cases to the tests.
    
    Assisted-by: GPT 6.1 Sol
    Co-authored-by: GPT 6.1 Sol <codex@openai.com>
    Byron and codex committed Oct 5, 2026
    Configuration menu
    Copy the full SHA
    0f89e36 View commit details
    Browse the repository at this point in the history
  3. Merge pull request #2269 from kokotatan/fix-index-checkout-pathlike

    fix(index): accept a single PathLike in checkout
    Byron authored Oct 5, 2026
    Configuration menu
    Copy the full SHA
    ae00cd2 View commit details
    Browse the repository at this point in the history
  4. Merge pull request #2270 from yunaremaia/fix-redact-url-credentials

    fix(util): redact URL credentials without corrupting the host
    Byron authored Oct 5, 2026
    Configuration menu
    Copy the full SHA
    4f0f54d View commit details
    Browse the repository at this point in the history
  5. change line for changelogs

    LE THANH LONG THANH TONG
    LE THANH LONG THANH TONG committed Oct 5, 2026
    Configuration menu
    Copy the full SHA
    af9ec3e View commit details
    Browse the repository at this point in the history
  6. Merge pull request #2272 from CrowZhen/main

    change line for changelogs
    Byron authored Oct 5, 2026
    Configuration menu
    Copy the full SHA
    b5d6a79 View commit details
    Browse the repository at this point in the history
Loading