GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — index: write blobs via git hash-object, not gitdb's odb.store by caroescm · Pull Request #2209 · gitpython-developers/GitPython

Conversation

@caroescm

@caroescm caroescm commented Aug 10, 2026

Copy link
Copy Markdown

Problem

repo.index.add() is GitPython's own way of adding files, separate from just running git add. To do that, it writes the file's content into .git/objects itself using Python, instead of asking git to do it. As part of that, it also tries to change the new file's permissions (chmod) — and in some setups, that permission change isn't allowed, even though writing the file itself worked fine.

So index.add() can crash with PermissionError in situations where plain git add (and repo.git.add(...), which just runs git add directly) work without any problem, on the same file.

There's also a smaller side effect: because GitPython reads the file itself instead of asking git, it skips any .gitattributes rules (like converting line endings), so the content it stores can end up slightly different from what git add would store.

What I changed

I changed index.add() to use the real git hash-object -w command to write the file into the object database, instead of doing it in Python. This means:

  • No more Python-side chmod, so the crash goes away.
  • The stored content now matches what git add would store, filters included.

Symlinks needed a small extra step: git hash-object normally follows a symlink and hashes the file it points to, but Git is supposed to store the symlink's target path itself, not the pointed-to file. So for symlinks, I write the target path to a temporary file and hash that instead.

Fixes #2021

Testing

  • Ran the existing test suite (test_index.py, test_base.py, test_repo.py) — all still pass.
  • Compared index.add()'s output to real git add for a normal file, a symlink, and a file in a subfolder — identical results.
  • Recreated the original bug by blocking chmod only on .git/objects files (same as the error in repo.index.add() method attempts to chmod files which it should not #2021) — index.add() now works instead of crashing.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@caroescm
caroescm force-pushed the fix-index-add-chmod branch from 4dbefc1 to 7ab02c6 Compare August 10, 2026 04:56
@Byron
Byron force-pushed the fix-index-add-chmod branch from 7ab02c6 to 139d0b1 Compare August 10, 2026 08:28
@Byron

Byron commented Aug 10, 2026

Copy link
Copy Markdown
Member

Thanks a lot for tackling this!

I will see if an alternative solution can do the trick, as such a localized override goes against the original architecture.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@Byron
Byron force-pushed the fix-index-add-chmod branch from 139d0b1 to f202503 Compare August 10, 2026 09:11
@Byron @codex
fix: index.add() now supports filters (gitpython-developers#2021)
93677a0
This is done by calling into `git hash-object` for correctness, instead
of using a mostly incorrect custom implementation for this (lacks filters).

<!-- agent -->
GitCmdObjectDB inherited LooseObjectDB.store(), so despite its name, object
writes bypassed Git and used gitdb's loose-object implementation. That path
creates and chmods object files itself, which can fail during Index.add() on
filesystems where those permission changes are unsupported.

Override store() to stream new objects through `git hash-object -w --stdin`.
This lets Git manage object creation and permissions consistently with the
repository configuration. Retain the inherited implementation for pre-hashed
objects and custom output streams, whose existing semantics hash-object cannot
provide.

Assisted-by: GPT 5.6
Co-authored-by: GPT 5.6 <[email protected]>
@Byron
Byron force-pushed the fix-index-add-chmod branch from f202503 to 93677a0 Compare August 10, 2026 09:54
@Byron
Byron merged commit 5ff52cc into gitpython-developers:main Aug 10, 2026
53 checks passed

Uh oh!

There was an error while loading. Please reload this page.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

No reviews

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

repo.index.add() method attempts to chmod files which it should not

Uh oh!

There was an error while loading. Please reload this page.

2 participants

@caroescm @Byron
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402520 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.