https://github.com/vaastav-technologies/py-gitbolt
git command interfaces with default implementation using subprocess calls.
https://github.com/vaastav-technologies/py-gitbolt
git python python-3 python3
Last synced: about 1 month ago
JSON representation
git command interfaces with default implementation using subprocess calls.
- Host: GitHub
- URL: https://github.com/vaastav-technologies/py-gitbolt
- Owner: Vaastav-Technologies
- License: apache-2.0
- Created: 2025-05-16T14:22:34.000Z (about 1 year ago)
- Default Branch: main
- Last Pushed: 2025-07-02T19:42:56.000Z (11 months ago)
- Last Synced: 2025-07-02T19:48:29.586Z (11 months ago)
- Topics: git, python, python-3, python3
- Language: Python
- Homepage:
- Size: 183 KB
- Stars: 2
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# π Gitbolt


[](https://github.com/Vaastav-Technologies/py-gitbolt/actions/workflows/test.yml)
[](https://github.com/Vaastav-Technologies/py-gitbolt/actions/workflows/typecheck.yml)
[](https://github.com/Vaastav-Technologies/py-gitbolt/actions/workflows/lint.yml)
[](https://codecov.io/gh/Vaastav-Technologies/py-gitbolt)
[](https://github.com/Vaastav-Technologies/py-gitbolt/actions/workflows/python-publish.yml)

**Fast, flexible and type-safe Git command execution in Python using subprocess.**
---
## β¨ Features
* π§ **Typed:** All commands and options are statically type-checked.
* β‘ **Fast:** Minimal abstractions over subprocess, runs directly on your system Git.
* π§© **Composable:** Git commands and options can be passed around as objects.
* π **Overridable:** Easily override environment variables and options in a chainable, readable manner.
* π¦ **Lightweight:** No dependencies on heavy Git libraries or C extensions.
* π§° **Extensible:** Future support for output transformers and other plugins.
* π¨ **Exception Handling:** Raises any error as a Python-recognisable exception.
* π€ **Debuggable:** Exceptions capture `stdout`, `stderr`, and the return code of the run command.
* π€ **Lazy Execution:** Inherently lazily processed.
* π **Transparent Output:** Returns a Git command's `stdout` as-is.
* π§ͺ **Terminal Functions:** Git subcommands are terminal functions.
* π§Ό **Idiomatic Python:** Write commands in idiomatic Python at compile-time and be confident theyβll execute smoothly at runtime.
* π **Add-ons:** Special features provided to ease programming with git. These can be added if required.
* π» **CLI-cmd:** Take commands from cli and run in `gitbolt`.
---
## π¦ Installation
```bash
pip install gitbolt
```
---
## π‘ Motivation
Running system commands in Python can be tricky for the following reasons:
1. Arguments sent to `subprocess` may not be typed correctly and result in runtime errors.
2. Argument groups may be mutually exclusive or required conditionally β again causing runtime issues.
3. Errors from subprocess are often unhelpful and difficult to debug.
Also, using subprocess effectively means you must:
* Understand and manage process setup, piping, and teardown.
* Know your CLI command intricacies in depth.
> This project exists to fix all that β with ergonomics, speed, and type-safety.
---
## π― Project Goals
### β
Predictable Compile-Time Behavior
Type-checking ensures runtime safety.
### β
Ergonomic APIs
Make git command interfaces as ergonomic to the user as possible.
#### Provide versions of most used command combinations
`git hash-object` supports taking multiple files and outputs a hash per file. But in practice, it's most often used to write a single file to the Git object database and return its hash. To match this real-world usage, Gitbolt offers a more ergonomic method that accepts one file and returns one hash β while still giving you the flexibility to access the full range of `git hash-object` capabilities when needed.
#### Let subcommands be passed around as objects
Gitbolt lets you pass subcommands around as typed objects. This enables highly focused, minimal APIs β you can write functions that accept only the subcommands they truly need. This leads to cleaner logic, better separation of concerns, and compile-time guarantees that help prevent misuse.
```python
import gitbolt
git = gitbolt.get_git()
version_subcmd = git.version_subcmd
add_subcmd = git.add_subcmd
def method_which_only_adds_a_file(add_subcmd: gitbolt.base.Add):
"""
This method only requires the `add` subcommand.
"""
...
method_which_only_adds_a_file(add_subcmd)
```
### β
Subcommands as Objects
git subcommands are modeled as terminal functions that return stdout.
```python
import gitbolt
git = gitbolt.get_git()
version_stdout = git.version_subcmd.version().version()
print(version_stdout)
```
### πͺΌ Modular Architecture
#### π§βπ» Modular at the programmatic level
Commands are designed to be passed around as objects. This makes them modular and thus users can opt to use only
particular commands.
```python
from gitbolt import get_git
git = get_git() # get git object for the current working directory
add_subcmd = git.add_subcmd
ls_tree_subcmd = git.ls_tree_subcmd
# now, functions can be written to accept only the required subcommands and nothing more than that.
```
#### π½οΈ Modular at project level
Only required commands and hence their implementations can be installed as per user requirement.
e.g.
- To install only the `git add` command related logic:
- ```shell
pip install gitbolt[add]
```
- To install command logic related to `git add` and `git rm` commands:
- ```shell
pip install gitbolt[add,rm]
```
- Install all porcelain related commands:
- ```shell
pip install gitbolt[porcelain]
```
- Install high performance `pygit2` implementations:
- ```shell
pip install gitbolt[pygit2]
```
- ```shell
pip install gitbolt[add,pygit2,rm]
```
- At last, install every command's implementation:
- ```shell
pip install gitbolt[all]
```
---
## π§ Strong Typing Everywhere
Extensive use of type-hints ensures that invalid usages fail early β at *compile-time*. Write at compile-time and be sure that commands run error-free at runtime.
---
Allow users to set/unset/reset Git environment variables and main command options using typed, chainable, Pythonic methods β just before a subcommand is executed.
### 𧬠Git Environment Variables
#### π Override a single Git env (e.g., `GIT_TRACE`)
```python
import gitbolt
git = gitbolt.get_git()
git = git.git_envs_override(GIT_TRACE=True)
```
#### π Override multiple Git envs (e.g., `GIT_TRACE`, `GIT_DIR`, `GIT_EDITOR`)
```python
from pathlib import Path
import gitbolt
git = gitbolt.get_git()
git = git.git_envs_override(GIT_TRACE=1, GIT_DIR=Path('/tmp/git-dir/'), GIT_EDITOR='vim')
```
#### πͺ’ Chain multiple overrides fluently
```python
from pathlib import Path
import gitbolt
git = gitbolt.get_git()
overridden_git = git.git_envs_override(GIT_SSH=Path('/tmp/SSH')).git_envs_override(
GIT_TERMINAL_PROMPT=1,
GIT_NO_REPLACE_OBJECTS=True
)
re_overridden_git = overridden_git.git_envs_override(GIT_TRACE=True)
```
#### β Unset Git envs using a special `UNSET` marker
```python
import gitbolt
from vt.utils.commons.commons.core_py import UNSET
git = gitbolt.get_git()
overridden_git = git.git_envs_override(GIT_ADVICE=True, GIT_TRACE=True)
no_advice_unset_git = overridden_git.git_envs_override(GIT_TRACE=UNSET)
```
#### π Reset Git envs by setting new values
```python
import gitbolt
git = gitbolt.get_git()
overridden_git = git.git_envs_override(GIT_TRACE=True)
git_trace_reset_git = overridden_git.git_envs_override(GIT_TRACE=False)
```
---
Allow users to set/unset/reset git main command options in typed and pythonic manner just before subcommand run to provide maximal flexibility.
### βοΈ Git Main Command Options
#### π Override a single Git opt (e.g., `--no-replace-objects`)
```python
import gitbolt
git = gitbolt.get_git()
git = git.git_opts_override(no_replace_objects=True)
```
#### π Override multiple options (e.g., `--git-dir`, `--paginate`)
```python
from pathlib import Path
from gitbolt.subprocess.impl.simple import SimpleGitCommand
git = SimpleGitCommand()
git = git.git_opts_override(no_replace_objects=True, git_dir=Path(), paginate=True)
```
#### πͺ’ Chain multiple option overrides fluently
```python
import gitbolt
from pathlib import Path
git = gitbolt.get_git()
overridden_git = git.git_opts_override(exec_path=Path('tmp')).git_opts_override(
noglob_pathspecs=True,
no_advice=True
).git_opts_override(
config_env={'auth': 'suhas', 'comm': 'suyog'}
)
re_overridden_git = overridden_git.git_opts_override(glob_pathspecs=True)
```
#### β Unset Git opts using a special `UNSET` marker
```python
import gitbolt
from pathlib import Path
from vt.utils.commons.commons.core_py import UNSET
git = gitbolt.get_git()
overridden_git = git.git_opts_override(exec_path=Path('tmp'), no_advice=True)
no_advice_unset_git = overridden_git.git_opts_override(no_advice=UNSET)
```
#### π Reset Git opts by setting new values
```python
import gitbolt
git = gitbolt.get_git()
overridden_git = git.git_opts_override(no_advice=True)
no_advice_reset_git = overridden_git.git_opts_override(no_advice=False)
```
### π Run unchecked commands
At last, run unchecked commands in git.
Introduced in `0.0.0dev4` to
- experiment.
- have consistent interfaced commands run until all subcommands are provided by the library.
```python
import gitbolt
git = gitbolt.get_git_command()
git = git.git_opts_override(no_advice=True)
git.subcmd_unchecked.run(['--version']) # run the version option for git.
git.subcmd_unchecked.run(['version']) # run the version subcommand.
```
#### π» Run commands received from CLI
Introduced in `0.0.0dev11` is the ability to take commands from CLI and run it inside `gitbolt`.
While making a system it may be required to run cli commands as received from cli using gitbolt. An obvious example
would be to make a system that receives CLI commands and does certain modifications/additions inside `gitbolt` before
actually running them. An example:
```python
import gitbolt
opts = ["--no-pager", "--namespace", "n1"] # options received from outside your program.
envs = dict(GIT_AUTHOR_NAME="ss") # env-vars received form outside your program.
git = gitbolt.get_git_command(opts=opts, envs=envs)
# these can later be overridden
git = git.git_opts_override(namespace="n2")
```
---
## π Transparent by Default
Output of git commands is returned as-is. No transformations unless explicitly requested.
Transformers for formatting/parsing can be added later.
---
## β
Benefits Out-of-the-Box
* π Composable Git commands.
* π€ Returns raw stdout.
* π¨ Exceptions with full context.
* π€ Lazy execution.
* π§ Strong typing and compile-time guarantees.
* π§Ό Idiomatic Python.
* π§ͺ Terminal subcommands.
* π£ Fail-fast on invalid usage.
---
## π More Information
- π [License (Apache-2.0)](./LICENSE)
- π€ [Contributing Guide](./CONTRIBUTING.md)
---
## π§ Future Goals
* Support `pygit2` for direct, fast Git access.
* Enable `porcelain` support using `pygit2` where required.
> `pygit2` usage will automatically make all commands return in porcelain mode.