There was a problem hiding this comment.
Adds a first-class Submodule.deinit(force=False) API to GitPython’s submodule object model, so callers can deinitialize a submodule without manually invoking repo.git.submodule('deinit', ...).
Changes:
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Sorry, something went wrong.
| @unbare_repo | ||
| def deinit(self, force: bool = False) -> "Submodule": | ||
| """Run ``git submodule deinit`` on this submodule. | ||
|
|
||
| This is a thin wrapper around ``git submodule deinit <path>``, paralleling | ||
| :meth:`add`, :meth:`update`, and :meth:`remove`. It unregisters the | ||
| submodule (removes its entry from ``.git/config`` and empties the | ||
| working-tree directory) without deleting the submodule from | ||
| ``.gitmodules`` or its checked-out repository under ``.git/modules/``. | ||
| A subsequent :meth:`update` will re-initialize the submodule from the | ||
| retained contents. | ||
|
|
||
| :param force: | ||
| If ``True``, pass ``--force`` to ``git submodule deinit``. This | ||
| allows deinitialization even when the submodule's working tree has | ||
| local modifications that would otherwise block the command. | ||
|
|
||
| :return: | ||
| self | ||
|
|
||
| :note: | ||
| Doesn't work in bare repositories. | ||
| """ | ||
| args: List[str] = [] | ||
| if force: | ||
| args.append("--force") | ||
| args.extend(["--", self.path]) | ||
| self.repo.git.submodule("deinit", *args) | ||
| return self |
There was a problem hiding this comment.
The new public API Submodule.deinit() isn't covered by tests. Please add a targeted unit test that asserts the underlying git invocation (e.g., by mocking submodule.repo.git.submodule) for both force=False and force=True, including verifying the -- separator and the provided path argument.
Sorry, something went wrong.
|
Added test_deinit_calls_git_submodule in 8e24b0f -- mocks Git.submodule and asserts both arg orderings:
Verified locally with pytest test/test_submodule.py -k deinit -v (passed) plus ruff check and ruff format --check clean. Marking the PR ready for human review. |
Sorry, something went wrong.
|
I set this back to draft while CI fails. |
Sorry, something went wrong.
Closes #2014.
Adds a `Submodule.deinit(force=False)` method that wraps `git submodule deinit [--force] -- `, paralleling the existing `add` / `update` / `remove` methods. Callers no longer need the `repo.git.submodule('deinit', ...)` workaround mentioned in the issue.
Behavior
Why a thin wrapper
The full semantics of `git submodule deinit` (recursive children, working-tree checks, .git/modules retention) are already handled correctly by the git porcelain. Re-implementing that logic in Python for parity with the existing `remove` method would duplicate significant behavior. A thin wrapper gives callers a typed entry point without duplicating git's state machine.
Verification
🤖 AI-assisted.