GitPython Documentation

GitPython is a python library used to interact with Git repositories.

5,150 stars Python Python 1 file Β· ~28,431 tokens #git-plumbing#git-porcelain#python-library
RAW Doc

Docker & Self-Hosted Deployment Verified OCI

Deploy GitPython on any server, homelab, or cloud container platform.

1-Click Terminal Command
bash (docker run)
docker run -d --name gitpython --restart always gitpython-developers/gitpython:latest

File: README.md


[Gitoxide](https://github.com/Byron/gitoxide): A peek into the future…

I started working on GitPython in 2009, back in the days when Python was 'my thing' and I had great plans with it.
Of course, back in the days, I didn't really know what I was doing and this shows in many places. Somewhat similar to
Python this happens to be 'good enough', but at the same time is deeply flawed and broken beyond repair.

By now, GitPython is widely used and I am sure there is a good reason for that, it's something to be proud of and happy about.
The community is maintaining the software and is keeping it relevant for which I am absolutely grateful. For the time to come I am happy to continue maintaining GitPython, remaining hopeful that one day it won't be needed anymore.

More than 15 years after my first meeting with 'git' I am still in excited about it, and am happy to finally have the tools and
probably the skills to scratch that itch of mine: implement git in a way that makes tool creation a piece of cake for most.

If you like the idea and want to learn more, please head over to gitoxide, an
implementation of 'git' in Rust.

(Please note that gitoxide is not currently available for use in Python, and that Rust is required.)

GitPython

GitPython is a python library used to interact with git repositories, high-level like git-porcelain,
or low-level like git-plumbing.

It provides abstractions of git objects for easy access of repository data often backed by calling the git
command-line program.

DEVELOPMENT STATUS

This project is in maintenance mode, which means that

  • …there will be no feature development, unless these are contributed
  • …there will be no bug fixes, unless they are relevant to the safety of users, or contributed
  • …issues will be responded to with waiting times of up to a month

The project is open to contributions of all kinds, as well as new maintainers.

REQUIREMENTS

GitPython needs the git executable to be installed on the system and available in your
PATH for most operations. If it is not in your PATH, you can help GitPython find it
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 installer takes care of installing them for you.

INSTALL

GitPython and its required package dependencies can be installed in any of the following ways, all of which should typically be done in a virtual environment.

From PyPI

To obtain and install a copy from PyPI, run:

sh
pip install GitPython

(A distribution package can also be downloaded for manual installation at the PyPI page.)

From downloaded source code

If you have downloaded the source code, run this from inside the unpacked GitPython directory:

sh
pip install .

By cloning the source code repository

To clone the the GitHub repository from source to work on the code, you can do it like so:

sh
git clone https://github.com/gitpython-developers/GitPython
cd GitPython
./init-tests-after-clone.sh

On Windows, ./init-tests-after-clone.sh can be run in a Git Bash shell.

If you are cloning your own fork, then replace the above git clone command with one that gives the URL of your fork. Or use this gh command (assuming you have gh and your fork is called GitPython):

sh
gh repo clone GitPython

Having cloned the repo, create and activate your virtual environment.

Then make an editable install:

sh
pip install -e ".[test]"

In the less common case that you do not want to install test dependencies, pip install -e . can be used instead.

With editable *dependencies* (not preferred, and rarely needed)

GitPython, gitdb, and smmap live in this repository as independently packaged projects. To work on all three at once, install each one editably in the same virtual environment:

sh
pip install -e smmap -e gitdb -e ".[test]"

You can use pip list to check which packages are installed editably and which are installed normally.

To reiterate, this approach should only rarely be used. For most development it is preferable to allow the gitdb and smmap dependencices to be retrieved automatically from PyPI in their latest stable packaged versions.

Limitations

Leakage of System Resources

GitPython is not suited for long-running processes (like daemons) as it tends to
leak system resources. It was written in a time where destructors (as implemented
in the __del__ method) still ran deterministically.

In case you still want to use it in such a context, you will want to search the
codebase for __del__ implementations and call these yourself when you see fit.

Another way assure proper cleanup of resources is to factor out GitPython into a
separate process which can be dropped periodically.

Windows support

See Issue #525.

RUNNING TESTS

Important: Right after cloning this repository, please be sure to have executed
the ./init-tests-after-clone.sh script in the repository root. Otherwise
you will encounter test failures.

Install test dependencies

Ensure testing libraries are installed. This is taken care of already if you installed with:

sh
pip install -e ".[test]"

If you had installed with a command like pip install -e . instead, you can still run
the above command to add the testing dependencies.

Test commands

To test, run:

sh
pytest

To lint, and apply some linting fixes as well as automatic code formatting, run:

sh
pre-commit run --all-files

This includes the linting and autoformatting done by Ruff, as well as some other checks.

To typecheck, run:

sh
mypy

CI (and tox)

Style and formatting checks, and running tests on all the different supported Python versions, will be performed:

  • Upon submitting a pull request.
  • On each push, if you have a fork with GitHub Actions enabled.
  • Locally, if you run tox (this skips any Python versions you don't have installed).

Configuration files

Specific tools are all configured in the ./pyproject.toml file:

  • pytest (test runner)
  • coverage.py (code coverage)
  • ruff (linter and formatter)
  • mypy (type checker)

Orchestration tools:

Contributions

Please have a look at the contributions file.

INFRASTRUCTURE

  • User Documentation
  • Questions and Answers
  • Please post on Stack Overflow and use the gitpython tag
  • Issue Tracker
    • Post reproducible bugs and feature requests as a new issue.
      Please be sure to provide the following information if posting bugs:
      • GitPython version (e.g. import git; git.__version__)
      • Python version (e.g. python --version)
      • The encountered stack-trace, if applicable
      • Enough information to allow reproducing the issue

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/<version>
  3. Commit everything.
  4. Run git tag -s <version> to tag the version in Git.
  5. Optionally create and activate a virtual environment. (Then the next step can install build and twine.)
  6. Run make release.
  7. Go to GitHub Releases and publish a new one with the recently pushed tag. Generate the changelog.

Projects using GitPython

LICENSE

3-Clause BSD License, also known as the New BSD License. See the LICENSE file.

One file exclusively used for fuzz testing is subject to a separate license, detailed here.
This file is not included in the wheel or sdist packages published by the maintainers of GitPython.


File: doc/source/changes.rst

========= Changelog

3.1.60

Security fixes for

If you can, also try and provide feedback on the upcoming v4 branch
https://github.com/gitpython-developers/GitPython/pull/2177 - patches welcome.

See the following for all changes.
https://github.com/gitpython-developers/GitPython/releases/tag/3.1.60

3.1.59

Security fixes for

If you can, also try and provide feedback on the upcoming v4 branch
https://github.com/gitpython-developers/GitPython/pull/2177 - patches welcome.

See the following for all changes.
https://github.com/gitpython-developers/GitPython/releases/tag/3.1.59

3.1.58

Security fixes for

If you can, also try and provide feedback on the upcoming v4 branch
https://github.com/gitpython-developers/GitPython/pull/2177 - patches welcome.

See the following for all changes.
https://github.com/gitpython-developers/GitPython/releases/tag/3.1.58

3.1.57

A security fix for

If you can, also try and provide feedback on the upcoming v4 branch
https://github.com/gitpython-developers/GitPython/pull/2177 - patches welcome.

See the following for all changes.
https://github.com/gitpython-developers/GitPython/releases/tag/3.1.57

3.1.56

A security fix for

If you can, also try and provide feedback on the upcoming v4 branch
https://github.com/gitpython-developers/GitPython/pull/2177 - patches welcome.

See the following for all changes.
https://github.com/gitpython-developers/GitPython/releases/tag/3.1.56

3.1.55

A security fix for

If you can, also try and provide feedback on the upcoming v4 branch
https://github.com/gitpython-developers/GitPython/pull/2177 - patches welcome.

See the following for all changes.
https://github.com/gitpython-developers/GitPython/releases/tag/3.1.55

3.1.54

A security fix for

If you can, also try and provide feedback on the upcoming v4 branch
https://github.com/gitpython-developers/GitPython/pull/2177 - patches welcome.

See the following for all changes.
https://github.com/gitpython-developers/GitPython/releases/tag/3.1.54

3.1.53

A security fix for
https://github.com/gitpython-developers/GitPython/security/advisories/GHSA-3rp5-jjmw-4wv2

If you can, also try and provide feedback on the upcoming v4 branch
https://github.com/gitpython-developers/GitPython/pull/2177 - patches welcome.

See the following for all changes.
https://github.com/gitpython-developers/GitPython/releases/tag/3.1.53

3.1.52

A security fix for
https://github.com/gitpython-developers/GitPython/security/advisories/GHSA-rwj8-pgh3-r573.

See the following for all changes.
https://github.com/gitpython-developers/GitPython/releases/tag/3.1.52

3.1.51

This is primarily a security release. It prevents additional argument-injection
paths that could allow execution of arbitrary commands or writing to arbitrary
files through unsafe Git options (GHSA-956x-8gvw-wg5v), and closes bypasses of
the existing protections using abbreviated long options or joined short options
(GHSA-2f96-g7mh-g2hx).

The release also improves support for relative worktree paths and diffs against
the empty tree, preserves stderr from failed diff processes, supports relative
configuration include paths, and includes assorted documentation, typing, test,
and CI improvements.

See the following for all changes.
https://github.com/gitpython-developers/GitPython/releases/tag/3.1.51

3.1.50

Save setting of configuration values, this time sections as well, as follow-up to 3.1.49.

See the following for all changes.
https://github.com/gitpython-developers/GitPython/releases/tag/3.1.50

3.1.49

Save setting of configuration values,
which could be used to inject other more configuration.

Also more conforming rev-parse implementation.

See the following for all changes.
https://github.com/gitpython-developers/GitPython/releases/tag/3.1.49

3.1.48

Safe reference creation in the face of untrusted input.

See the following for all changes.
https://github.com/gitpython-developers/GitPython/releases/tag/3.1.48

3.1.47

Address various security issues related to bypassing injection-protection
of unsafe Git flags.

See the following for all changes.
https://github.com/gitpython-developers/GitPython/releases/tag/3.1.47

3.1.46

See the following for all changes.
https://github.com/gitpython-developers/GitPython/releases/tag/3.1.46

3.1.45

See the following for all changes.
https://github.com/gitpython-developers/GitPython/releases/tag/3.1.45

3.1.44

See the following for all changes.
https://github.com/gitpython-developers/GitPython/releases/tag/3.1.44

3.1.43

A major visible change will be the added deprecation- or user-warnings,
and greatly improved typing.

See the following for all changes.
https://github.com/gitpython-developers/GitPython/releases/tag/3.1.43

3.1.42

See the following for all changes.
https://github.com/gitpython-developers/GitPython/releases/tag/3.1.42

3.1.41

This release is relevant for security as it fixes a possible arbitrary
code execution on Windows.

See this PR for details: https://github.com/gitpython-developers/GitPython/pull/1792
An advisory is available soon at: https://github.com/gitpython-developers/GitPython/security/advisories/GHSA-2mqj-m65w-jghx

See the following for all changes.
https://github.com/gitpython-developers/GitPython/releases/tag/3.1.41

3.1.40

See the following for all changes.
https://github.com/gitpython-developers/GitPython/releases/tag/3.1.40

3.1.38

See the following for all changes.
https://github.com/gitpython-developers/GitPython/releases/tag/3.1.38

3.1.37

This release contains another security fix that further improves validation of symbolic references
and thus properly fixes this CVE: https://github.com/advisories/GHSA-cwvm-v4w8-q58c .

See the following for all changes.
https://github.com/gitpython-developers/gitpython/milestone/67?closed=1

3.1.36

Note that this release should be a no-op, it's mainly for testing the changed release-process.

See the following for all changes.
https://github.com/gitpython-developers/gitpython/milestone/66?closed=1

3.1.35

See the following for all changes.
https://github.com/gitpython-developers/gitpython/milestone/65?closed=1

3.1.34

See the following for all changes.
https://github.com/gitpython-developers/gitpython/milestone/64?closed=1

3.1.33

See the following for all changes.
https://github.com/gitpython-developers/gitpython/milestone/63?closed=1

3.1.32

See the following for all changes.
https://github.com/gitpython-developers/gitpython/milestone/62?closed=1

3.1.31

See the following for all changes.
https://github.com/gitpython-developers/gitpython/milestone/61?closed=1

3.1.30

See the following for all changes.
https://github.com/gitpython-developers/gitpython/milestone/60?closed=1

3.1.29

  • Make the git.version re-appear.

See the following for all changes.
https://github.com/gitpython-developers/gitpython/milestone/59?closed=1

3.1.28

See the following for all changes.
https://github.com/gitpython-developers/gitpython/milestone/58?closed=1

3.1.27

  • Reduced startup time due to optimized imports.
  • Fix a vulenerability that could cause great slowdowns when encountering long remote path names
    when pulling/fetching.

See the following for all changes.
https://github.com/gitpython-developers/gitpython/milestone/57?closed=1

3.1.26

See the following for all changes.
https://github.com/gitpython-developers/gitpython/milestone/56?closed=1

3.1.25

See the following for all changes.
https://github.com/gitpython-developers/gitpython/milestone/55?closed=1

3.1.24

  • Newly added timeout flag is not be enabled by default, and was renamed to kill_after_timeout

See the following for details:
https://github.com/gitpython-developers/gitpython/milestone/54?closed=1
https://github.com/gitpython-developers/gitpython/milestone/53?closed=1

3.1.23 (YANKED)

  • This is the second typed release with a lot of improvements under the hood.

  • General:

    • Remove python 3.6 support

    • Remove distutils ahead of deprecation in standard library.

    • Update sphinx to 4.1.12 and use autodoc-typehints.

    • Include README as long_description on PyPI

    • Test against earliest and latest minor version available on Github Actions (e.g. 3.9.0 and 3.9.7)

  • Typing:

    • Add types to ALL functions.

    • Ensure py.typed is collected.

    • Increase mypy strictness with disallow_untyped_defs, warn_redundant_casts, warn_unreachable.

    • Use typing.NamedTuple and typing.OrderedDict now 3.6 dropped.

    • Make Protocol classes ABCs at runtime due to new behaviour/bug in 3.9.7 & 3.10.0-rc1

    • Remove use of typing.TypeGuard until later release, to allow dependent libs time to update.

    • Tracking issue: https://github.com/gitpython-developers/GitPython/issues/1095

  • Runtime improvements:

    • Add clone_multi_options support to submodule.add()

    • Delay calling get_user_id() unless essential, to support sand-boxed environments.

    • Add timeout to handle_process_output(), in case thread.join() hangs.

See the following for details:
https://github.com/gitpython-developers/gitpython/milestone/53?closed=1

3.1.20 (YANKED)

See the following for details:
https://github.com/gitpython-developers/gitpython/milestone/52?closed=1

3.1.19 (YANKED)

See the following for details:
https://github.com/gitpython-developers/gitpython/milestone/51?closed=1

3.1.18

  • drop support for python 3.5 to reduce maintenance burden on typing. Lower patch levels of python 3.5 would break, too.

See the following for details:
https://github.com/gitpython-developers/gitpython/milestone/50?closed=1

3.1.17

See the following for details:
https://github.com/gitpython-developers/gitpython/milestone/49?closed=1

3.1.16 (YANKED)

See the following for details:
https://github.com/gitpython-developers/gitpython/milestone/48?closed=1

3.1.15 (YANKED)

  • add deprecation warning for python 3.5

See the following for details:
https://github.com/gitpython-developers/gitpython/milestone/47?closed=1

3.1.14

  • git.Commit objects now have a replace method that will return a
    copy of the commit with modified attributes.
  • Add python 3.9 support
  • Drop python 3.4 support

See the following for details:
https://github.com/gitpython-developers/gitpython/milestone/46?closed=1

3.1.13

See the following for details:
https://github.com/gitpython-developers/gitpython/milestone/45?closed=1

3.1.12

See the following for details:
https://github.com/gitpython-developers/gitpython/milestone/44?closed=1

3.1.11

Fixes regression of 3.1.10.

See the following for details:
https://github.com/gitpython-developers/gitpython/milestone/43?closed=1

3.1.10

See the following for details:
https://github.com/gitpython-developers/gitpython/milestone/42?closed=1

3.1.9

See the following for details:
https://github.com/gitpython-developers/gitpython/milestone/41?closed=1

3.1.8

  • support for 'includeIf' in git configuration files
  • tests are now excluded from the package, making it conisderably smaller

See the following for more details:
https://github.com/gitpython-developers/gitpython/milestone/40?closed=1

3.1.7

  • Fix tutorial examples, which disappeared in 3.1.6 due to a missed path change.

3.1.6

3.1.5

3.1.4

  • all exceptions now keep track of their cause
  • package size was reduced significantly not placing tests into the package anymore.

See the following for details:
https://github.com/gitpython-developers/gitpython/milestone/39?closed=1

3.1.3

See the following for details:
https://github.com/gitpython-developers/gitpython/milestone/38?closed=1

3.1.2

  • Re-release of 3.1.1, with known signature

See the following for details:
https://github.com/gitpython-developers/gitpython/milestone/37?closed=1

3.1.1

  • support for PyOxidizer, which previously failed due to usage of __file__.

See the following for details:
https://github.com/gitpython-developers/gitpython/milestone/36?closed=1

3.1.0

  • Switched back to using gitdb package as requirement
    (gitdb#59 <https://github.com/gitpython-developers/gitdb/issues/59>_)

3.0.9

  • Restricted GitDB (gitdb2) version requirement to < 4
  • Removed old nose library from test requirements

Bugfixes

  • Changed to use UTF-8 instead of default encoding when getting information about a symbolic reference
    (#774 <https://github.com/gitpython-developers/GitPython/issues/774>_)
  • Fixed decoding of tag object message so as to replace invalid bytes
    (#943 <https://github.com/gitpython-developers/GitPython/issues/943>_)

3.0.8

  • Added support for Python 3.8
  • Bumped GitDB (gitdb2) version requirement to > 3

Bugfixes

  • Fixed Repo.repr when subclassed
    (#968 <https://github.com/gitpython-developers/GitPython/pull/968>_)
  • Removed compatibility shims for Python < 3.4 and old mock library
  • Replaced usage of deprecated unittest aliases and Logger.warn
  • Removed old, no longer used assert methods
  • Replaced usage of nose assert methods with unittest

3.0.7

Properly signed re-release of v3.0.6 with new signature
(See #980 <https://github.com/gitpython-developers/GitPython/issues/980>_)

3.0.6

| Note: There was an issue that caused this version to be released to PyPI without a signature
| See the changelog for v3.0.7 and #980 <https://github.com/gitpython-developers/GitPython/issues/980>_

Bugfixes

  • Fixed warning for usage of environment variables for paths containing $ or %
    (#832 <https://github.com/gitpython-developers/GitPython/issues/832>,
    #961 <https://github.com/gitpython-developers/GitPython/pull/961>
    )
  • Added support for parsing Git internal date format (@ )
    (#965 <https://github.com/gitpython-developers/GitPython/pull/965>_)
  • Removed Python 2 and < 3.3 compatibility shims
    (#979 <https://github.com/gitpython-developers/GitPython/pull/979>_)
  • Fixed GitDB (gitdb2) requirement version specifier formatting in requirements.txt
    (#979 <https://github.com/gitpython-developers/GitPython/pull/979>_)

3.0.5 - Bugfixes

see the following for details:
https://github.com/gitpython-developers/gitpython/milestone/32?closed=1

3.0.4 - Bugfixes

see the following for details:
https://github.com/gitpython-developers/gitpython/milestone/31?closed=1

3.0.3 - Bugfixes

see the following for (most) details:
https://github.com/gitpython-developers/gitpython/milestone/30?closed=1

3.0.2 - Bugfixes

  • fixes an issue with installation

3.0.1 - Bugfixes and performance improvements

  • Fix a performance regression <https://github.com/gitpython-developers/GitPython/issues/906>__ which could make certain workloads 50% slower
  • Add currently_rebasing_on method on Repo, see the PR <https://github.com/gitpython-developers/GitPython/pull/903/files#diff-c276fc3c4df38382ec884e59657b869dR1065>__
  • Fix incorrect requirements.txt which could lead to broken installations, see this issue <https://github.com/gitpython-developers/GitPython/issues/908>__ for details.

3.0.0 - Remove Python 2 support

Motivation for this is a patch which improves unicode handling when dealing with filesystem paths.
Python 2 compatibility was introduced to deal with differences, and I thought it would be a good idea
to 'just' drop support right now, mere 5 months away from the official maintenance stop of python 2.7.

The underlying motivation clearly is my anger when thinking python and unicode, which was a hassle from the
start, at least in a codebase as old as GitPython, which totally doesn't handle encodings correctly in many cases.

Having migrated to using Rust exclusively for tooling, I still see that correct handling of encodings isn't entirely
trivial, but at least Rust makes clear what has to be done at compile time, allowing to write software that is pretty
much guaranteed to work once it compiles.

Again, my apologies if removing Python 2 support caused inconveniences, please see release 2.1.13 which returns it.

see the following for (most) details:
https://github.com/gitpython-developers/gitpython/milestone/27?closed=1

or run have a look at the difference between tags v2.1.12 and v3.0.0:
https://github.com/gitpython-developers/GitPython/compare/2.1.12...3.0.0.

2.1.15

  • Fixed GitDB (gitdb2) requirement version specifier formatting in requirements.txt
    (Backported from #979 <https://github.com/gitpython-developers/GitPython/pull/979>_)
  • Restricted GitDB (gitdb2) version requirement to < 3
    (#897 <https://github.com/gitpython-developers/GitPython/issues/897>_)

2.1.14

  • Fixed handling of 0 when transforming kwargs into Git command arguments
    (Backported from #899 <https://github.com/gitpython-developers/GitPython/pull/899>_)

2.1.13 - Bring back Python 2.7 support

My apologies for any inconvenience this may have caused. Following semver, backward incompatible changes
will be introduced in a minor version.

2.1.12 - Bugfixes and Features

  • Multi-value support and interface improvements for Git configuration. Thanks to A. Jesse Jiryu Davis.

or run have a look at the difference between tags v2.1.11 and v2.1.12:
https://github.com/gitpython-developers/GitPython/compare/2.1.11...2.1.12

2.1.11 - Bugfixes

see the following for (most) details:
https://github.com/gitpython-developers/gitpython/milestone/26?closed=1

or run have a look at the difference between tags v2.1.10 and v2.1.11:
https://github.com/gitpython-developers/GitPython/compare/2.1.10...2.1.11

2.1.10 - Bugfixes

see the following for (most) details:
https://github.com/gitpython-developers/gitpython/milestone/25?closed=1

or run have a look at the difference between tags v2.1.9 and v2.1.10:
https://github.com/gitpython-developers/GitPython/compare/2.1.9...2.1.10

2.1.9 - Dropping support for Python 2.6

see the following for (most) details:
https://github.com/gitpython-developers/gitpython/milestone/24?closed=1

or run have a look at the difference between tags v2.1.8 and v2.1.9:
https://github.com/gitpython-developers/GitPython/compare/2.1.8...2.1.9

2.1.8 - bugfixes

see the following for (most) details:
https://github.com/gitpython-developers/gitpython/milestone/23?closed=1

or run have a look at the difference between tags v2.1.7 and v2.1.8:
https://github.com/gitpython-developers/GitPython/compare/2.1.7...2.1.8

2.1.6 - bugfixes

  • support for worktrees

2.1.3 - Bugfixes

All issues and PRs can be viewed in all detail when following this URL:
https://github.com/gitpython-developers/GitPython/milestone/21?closed=1

2.1.1 - Bugfixes

All issues and PRs can be viewed in all detail when following this URL:
https://github.com/gitpython-developers/GitPython/issues?q=is%3Aclosed+milestone%3A%22v2.1.1+-+Bugfixes%22

2.1.0 - Much better windows support!

Special thanks to @ankostis, who made this release possible (nearly) single-handedly.
GitPython is run by its users, and their PRs make all the difference, they keep
GitPython relevant. Thank you all so much for contributing !

Notable fixes

  • The GIT_DIR environment variable does not override the path argument when
    initializing a Repo object anymore. However, if said path unset, GIT_DIR
    will be used to fill the void.

All issues and PRs can be viewed in all detail when following this URL:
https://github.com/gitpython-developers/GitPython/issues?q=is%3Aclosed+milestone%3A%22v2.1.0+-+proper+windows+support%22

2.0.9 - Bugfixes

  • tag.commit will now resolve commits deeply.

  • Repo objects can now be pickled, which helps with multi-processing.

  • Head.checkout() now deals with detached heads, which is when it will return
    the HEAD reference instead.

  • DiffIndex.iter_change_type(...) produces better results when diffing

2.0.8 - Features and Bugfixes

  • DiffIndex.iter_change_type(...) produces better results when diffing
    an index against the working tree.
  • Repo().is_dirty(...) now supports the path parameter, to specify a single
    path by which to filter the output. Similar to git status
  • Symbolic refs created by this library will now be written with a newline
    character, which was previously missing.
  • blame() now properly preserves multi-line commit messages.
  • No longer corrupt ref-logs by writing multi-line comments into them.

2.0.7 - New Features

  • IndexFile.commit(...,skip_hooks=False) added. This parameter emulates the
    behaviour of --no-verify on the command-line.

2.0.6 - Fixes and Features

  • Fix: remote output parser now correctly matches refs with non-ASCII
    chars in them
  • API: Diffs now have a_rawpath, b_rawpath, raw_rename_from,
    raw_rename_to properties, which are the raw-bytes equivalents of their
    unicode path counterparts.
  • Fix: TypeError about passing keyword argument to string decode() on
    Python 2.6.
  • Feature: setUrl API on Remotes <https://github.com/gitpython-developers/GitPython/pull/446#issuecomment-224670539>__

2.0.5 - Fixes

  • Fix: parser of fetch info lines choked on some legitimate lines

2.0.4 - Fixes

  • Fix: parser of commit object data is now robust against cases where
    commit object contains invalid bytes. The invalid characters are now
    replaced rather than choked on.
  • Fix: non-ASCII paths are now properly decoded and returned in
    .diff() output
  • Fix: RemoteProgress will now strip the ', ' prefix or suffix from messages.
  • API: Remote.fetch|push|pull methods now allow the progress argument to
    be a callable. This saves you from creating a custom type with usually just one
    implemented method.

2.0.3 - Fixes

  • Fix: bug in git-blame --incremental output parser that broken when
    commit messages contained \r characters
  • Fix: progress handler exceptions are not caught anymore, which would usually just hide bugs
    previously.
  • Fix: The Git.execute method will now redirect stdout to devnull if with_stdout is false,
    which is the intended behaviour based on the parameter's documentation.

2.0.2 - Fixes

  • Fix: source package does not include *.pyc files
  • Fix: source package does include doc sources

2.0.1 - Fixes

  • Fix: remote output parser now correctly matches refs with "@" in them

2.0.0 - Features

Please note that due to breaking changes, we have to increase the major version.

  • IMPORTANT: This release drops support for python 2.6, which is
    officially deprecated by the python maintainers.
  • CRITICAL: Diff objects created with patch output will now not carry
    the --- and +++ header lines anymore. All diffs now start with the
    @@ header line directly. Users that rely on the old behaviour can now
    (reliably) read this information from the a_path and b_path properties
    without having to parse these lines manually.
  • Commit now has extra properties authored_datetime and
    committer_datetime (to get Python datetime instances rather than
    timestamps)
  • Commit.diff() now supports diffing the root commit via
    Commit.diff(NULL_TREE).
  • Repo.blame() now respects incremental=True, supporting incremental
    blames. Incremental blames are slightly faster since they don't include
    the file's contents in them.
  • Fix: Diff objects created with patch output will now have their
    a_path and b_path properties parsed out correctly. Previously, some
    values may have been populated incorrectly when a file was added or
    deleted.
  • Fix: diff parsing issues with paths that contain "unsafe" chars, like
    spaces, tabs, backslashes, etc.

1.0.2 - Fixes

  • IMPORTANT: Changed default object database of Repo objects to GitCmdObjectDB. The pure-python implementation
    used previously usually fails to release its resources (i.e. file handles), which can lead to problems when working
    with large repositories.
  • CRITICAL: fixed incorrect Commit object serialization when authored or commit date had timezones which were not
    divisiblej by 3600 seconds. This would happen if the timezone was something like +0530 for instance.
  • A list of all additional fixes can be found on GitHub <https://github.com/gitpython-developers/GitPython/issues?q=milestone%3A%22v1.0.2+-+Fixes%22+is%3Aclosed>__
  • CRITICAL: Tree.cache was removed without replacement. It is technically impossible to change individual trees and expect their serialization results to be consistent with what git expects. Instead, use the IndexFile facilities to adjust the content of the staging area, and write it out to the respective tree objects using IndexFile.write_tree() instead.

1.0.1 - Fixes

  • A list of all issues can be found on GitHub <https://github.com/gitpython-developers/GitPython/issues?q=milestone%3A%22v1.0.1+-+Fixes%22+is%3Aclosed>__

1.0.0 - Notes

This version is equivalent to v0.3.7, but finally acknowledges that GitPython is stable and production ready.

It follows the semantic version scheme <http://semver.org>_, and thus will not break its existing API unless it goes 2.0.

0.3.7 - Fixes

  • IndexFile.add() will now write the index without any extension data by default. However, you may override this behaviour with the new write_extension_data keyword argument.

    • Renamed ignore_tree_extension_data keyword argument in IndexFile.write(...) to ignore_extension_data
  • If the git command executed during Remote.push(...)|fetch(...) returns with an non-zero exit code and GitPython didn't
    obtain any head-information, the corresponding GitCommandError will be raised. This may break previous code which expected
    these operations to never raise. However, that behaviour is undesirable as it would effectively hide the fact that there
    was an error. See this issue <https://github.com/gitpython-developers/GitPython/issues/271>__ for more information.

  • If the git executable can't be found in the PATH or at the path provided by GIT_PYTHON_GIT_EXECUTABLE, this is made
    obvious by throwing GitCommandNotFound, both on unix and on windows.

    • Those who support GUI on windows will now have to set git.Git.USE_SHELL = True to get the previous behaviour.
  • A list of all issues can be found on GitHub <https://github.com/gitpython-developers/GitPython/issues?q=milestone%3A%22v0.3.7+-+Fixes%22+is%3Aclosed>__

0.3.6 - Features

  • DOCS

    • special members like __init__ are now listed in the API documentation
    • tutorial section was revised entirely, more advanced examples were added.
  • POSSIBLY BREAKING CHANGES

    • As rev_parse will now throw BadName as well as BadObject, client code will have to catch both exception types.
    • Repo.working_tree_dir now returns None if it is bare. Previously it raised AssertionError.
    • IndexFile.add() previously raised AssertionError when paths where used with bare repository, now it raises InvalidGitRepositoryError
  • Added Repo.merge_base() implementation. See the respective issue on GitHub <https://github.com/gitpython-developers/GitPython/issues/169>__

  • [include] sections in git configuration files are now respected

  • Added GitConfigParser.rename_section()

  • Added Submodule.rename()

  • A list of all issues can be found on GitHub <https://github.com/gitpython-developers/GitPython/issues?q=milestone%3A%22v0.3.6+-+Features%22+>__

0.3.5 - Bugfixes

  • push/pull/fetch operations will not block anymore
  • diff() can now properly detect renames, both in patch and raw format. Previously it only worked when create_patch was True.
  • repo.odb.update_cache() is now called automatically after fetch and pull operations. In case you did that in your own code, you might want to remove your line to prevent a double-update that causes unnecessary IO.
  • Repo(path) will not automatically search upstream anymore and find any git directory on its way up. If you need that behaviour, you can turn it back on using the new search_parent_directories=True flag when constructing a Repo object.
  • IndexFile.commit() now runs the pre-commit and post-commit hooks. Verified to be working on posix systems only.
  • A list of all fixed issues can be found here: https://github.com/gitpython-developers/GitPython/issues?q=milestone%3A%22v0.3.5+-+bugfixes%22+

0.3.4 - Python 3 Support

  • Internally, hexadecimal SHA1 are treated as ascii encoded strings. Binary SHA1 are treated as bytes.
  • Id attribute of Commit objects is now hexsha, instead of binsha. The latter makes no sense in python 3 and I see no application of it anyway besides its artificial usage in test cases.
  • IMPORTANT: If you were using the config_writer(), you implicitly relied on del to work as expected to flush changes. To be sure changes are flushed under PY3, you will have to call the new release() method to trigger a flush. For some reason, del is not called necessarily anymore when a symbol goes out of scope.
  • The Tree now has a .join('name') method which is equivalent to tree / 'name'

0.3.3

  • When fetching, pulling or pushing, and an error occurs, it will not be reported on stdout anymore. However, if there is a fatal error, it will still result in a GitCommandError to be thrown. This goes hand in hand with improved fetch result parsing.

  • Code Cleanup (in preparation for python 3 support)

    • Applied autopep8 and cleaned up code
    • Using python logging module instead of print statements to signal certain kinds of errors

0.3.2.1

  • Fix for #207 <https://github.com/gitpython-developers/GitPython/issues/207>_

0.3.2

0.3.2 RC1

  • git command wrapper

  • Added version_info property which returns a tuple of integers representing the installed git version.

  • Added GIT_PYTHON_GIT_EXECUTABLE environment variable, which can be used to set the desired git executable to be used. despite of what would be found in the path.

  • Blob Type

  • Added mode constants to ease the manual creation of blobs

  • IterableList

  • Added contains and delitem methods

  • More Changes

  • Configuration file parsing is more robust. It should now be able to handle everything that the git command can parse as well.

  • The progress parsing was updated to support git 1.7.0.3 and newer. Previously progress was not enabled for the git command or only worked with ssh in case of older git versions.

  • Parsing of tags was improved. Previously some parts of the name could not be parsed properly.

  • The rev-parse pure python implementation now handles branches correctly if they look like hexadecimal sha's.

  • GIT_PYTHON_TRACE is now set on class level of the Git type, previously it was a module level global variable.

  • GIT_PYTHON_GIT_EXECUTABLE is a class level variable as well.

0.3.1 Beta 2

  • Added reflog support ( reading and writing )

  • New types: RefLog and RefLogEntry

  • Reflog is maintained automatically when creating references and deleting them

  • Non-intrusive changes to SymbolicReference, these don't require your code to change. They allow to append messages to the reflog.

    • abspath property added, similar to abspath of Object instances
    • log() method added
    • log_append(...) method added
    • set_reference(...) method added (reflog support)
    • set_commit(...) method added (reflog support)
    • set_object(...) method added (reflog support)
  • Intrusive Changes to Head type

  • create(...) method now supports the reflog, but will not raise GitCommandError anymore as it is a pure python implementation now. Instead, it raises OSError.

  • Intrusive Changes to Repo type

  • create_head(...) method does not support kwargs anymore, instead it supports a logmsg parameter

  • Repo.rev_parse now supports the [ref]@{n} syntax, where n is the number of steps to look into the reference's past

  • BugFixes

    • Removed incorrect ORIG_HEAD handling
  • Flattened directory structure to make development more convenient.

  • .. note:: This alters the way projects using git-python as a submodule have to adjust their sys.path to be able to import git-python successfully.

  • Misc smaller changes and bugfixes

0.3.1 Beta 1

  • Full Submodule-Support

  • Added unicode support for author names. Commit.author.name is now unicode instead of string.

  • Head Type changes

  • config_reader() & config_writer() methods added for access to head specific options.

  • tracking_branch() & set_tracking_branch() methods added for easy configuration of tracking branches.

0.3.0 Beta 2

  • Added python 2.4 support

0.3.0 Beta 1

Renamed Modules

  • For consistency with naming conventions used in sub-modules like gitdb, the following modules have been renamed

    • git.utils -> git.util
    • git.errors -> git.exc
    • git.objects.utils -> git.objects.util

General

  • Object instances, and everything derived from it, now use binary sha's internally. The 'sha' member was removed, in favor of the 'binsha' member. An 'hexsha' property is available for convenient conversions. They may only be initialized using their binary shas, reference names or revision specs are not allowed anymore.
  • IndexEntry instances contained in IndexFile.entries now use binary sha's. Use the .hexsha property to obtain the hexadecimal version. The .sha property was removed to make the use of the respective sha more explicit.
  • If objects are instantiated explicitly, a binary sha is required to identify the object, where previously any rev-spec could be used. The ref-spec compatible version still exists as Object.new or Repo.commit|Repo.tree respectively.
  • The .data attribute was removed from the Object type, to obtain plain data, use the data_stream property instead.
  • ConcurrentWriteOperation was removed, and replaced by LockedFD
  • IndexFile.get_entries_key was renamed to entry_key
  • IndexFile.write_tree: removed missing_ok keyword, its always True now. Instead of raising GitCommandError it raises UnmergedEntriesError. This is required as the pure-python implementation doesn't support the missing_ok keyword yet.
  • diff.Diff.null_hex_sha renamed to NULL_HEX_SHA, to be conforming with the naming in the Object base class

0.2 Beta 2

  • Commit objects now carry the 'encoding' information of their message. It wasn't parsed previously, and defaults to UTF-8
  • Commit.create_from_tree now uses a pure-python implementation, mimicking git-commit-tree

0.2

General

  • file mode in Tree, Blob and Diff objects now is an int compatible to definitions
    in the stat module, allowing you to query whether individual user, group and other
    read, write and execute bits are set.
  • Adjusted class hierarchy to generally allow comparison and hash for Objects and Refs
  • Improved Tag object which now is a Ref that may contain a tag object with additional
    Information
  • id_abbrev method has been removed as it could not assure the returned short SHA's
    where unique
  • removed basename method from Objects with path's as it replicated features of os.path
  • from_string and list_from_string methods are now private and were renamed to
    _from_string and _list_from_string respectively. As part of the private API, they
    may change without prior notice.
  • Renamed all find_all methods to list_items - this method is part of the Iterable interface
    that also provides a more efficients and more responsive iter_items method
  • All dates, like authored_date and committer_date, are stored as seconds since epoch
    to consume less memory - they can be converted using time.gmtime in a more suitable
    presentation format if needed.
  • Named method parameters changed on a wide scale to unify their use. Now git specific
    terms are used everywhere, such as "Reference" ( ref ) and "Revision" ( rev ).
    Previously multiple terms where used making it harder to know which type was allowed
    or not.
  • Unified diff interface to allow easy diffing between trees, trees and index, trees
    and working tree, index and working tree, trees and index. This closely follows
    the git-diff capabilities.
  • Git.execute does not take the with_raw_output option anymore. It was not used
    by anyone within the project and False by default.

Item Iteration

  • Previously one would return and process multiple items as list only which can
    hurt performance and memory consumption and reduce response times.
    iter_items method provide an iterator that will return items on demand as parsed
    from a stream. This way any amount of objects can be handled.
  • list_items method returns IterableList allowing to access list members by name

objects Package

  • blob, tree, tag and commit module have been moved to new objects package. This should
    not affect you though unless you explicitly imported individual objects. If you just
    used the git package, names did not change.

Blob

  • former 'name' member renamed to path as it suits the actual data better

GitCommand

  • git.subcommand call scheme now prunes out None from the argument list, allowing
    to be called more comfortably as None can never be a valid to the git command
    if converted to a string.
  • Renamed 'git_dir' attribute to 'working_dir' which is exactly how it is used

Commit

  • 'count' method is not an instance method to increase its ease of use
  • 'name_rev' property returns a nice name for the commit's sha

Config

  • The git configuration can now be read and manipulated directly from within python
    using the GitConfigParser
  • Repo.config_reader() returns a read-only parser
  • Repo.config_writer() returns a read-write parser

Diff

  • Members a a_commit and b_commit renamed to a_blob and b_blob - they are populated
    with Blob objects if possible
  • Members a_path and b_path removed as this information is kept in the blobs
  • Diffs are now returned as DiffIndex allowing to more quickly find the kind of
    diffs you are interested in

Diffing

  • Commit and Tree objects now support diffing natively with a common interface to
    compare against other Commits or Trees, against the working tree or against the index.

Index

  • A new Index class allows to read and write index files directly, and to perform
    simple two and three way merges based on an arbitrary index.

References

  • References are object that point to a Commit
  • SymbolicReference are a pointer to a Reference Object, which itself points to a specific
    Commit
  • They will dynamically retrieve their object at the time of query to assure the information
    is actual. Recently objects would be cached, hence ref object not be safely kept
    persistent.

Repo

  • Moved blame method from Blob to repo as it appeared to belong there much more.

  • active_branch method now returns a Head object instead of a string with the name
    of the active branch.

  • tree method now requires a Ref instance as input and defaults to the active_branch
    instead of master

  • is_dirty now takes additional arguments allowing fine-grained control about what is
    considered dirty

  • Removed the following methods:

    • 'log' method as it as effectively the same as the 'commits' method
    • 'commits_since' as it is just a flag given to rev-list in Commit.iter_items
    • 'commit_count' as it was just a redirection to the respective commit method
    • 'commits_between', replaced by a note on the iter_commits method as it can achieve the same thing
    • 'commit_delta_from' as it was a very special case by comparing two different repjrelated repositories, i.e. clones, git-rev-list would be sufficient to find commits that would need to be transferred for example.
    • 'create' method which equals the 'init' method's functionality
    • 'diff' - it returned a mere string which still had to be parsed
    • 'commit_diff' - moved to Commit, Tree and Diff types respectively
  • Renamed the following methods:

    • commits to iter_commits to improve the performance, adjusted signature
    • init_bare to init, implying less about the options to be used
    • fork_bare to clone, as it was to represent general clone functionality, but implied
      a bare clone to be more versatile
    • archive_tar_gz and archive_tar and replaced by archive method with different signature
  • 'commits' method has no max-count of returned commits anymore, it now behaves like git-rev-list

  • The following methods and properties were added

    • 'untracked_files' property, returning all currently untracked files
    • 'head', creates a head object
    • 'tag', creates a tag object
    • 'iter_trees' method
    • 'config_reader' method
    • 'config_writer' method
    • 'bare' property, previously it was a simple attribute that could be written
  • Renamed the following attributes

    • 'path' is now 'git_dir'
    • 'wd' is now 'working_dir'
  • Added attribute

    • 'working_tree_dir' which may be None in case of bare repositories

Remote

  • Added Remote object allowing easy access to remotes
  • Repo.remotes lists all remotes
  • Repo.remote returns a remote of the specified name if it exists

Test Framework

  • Added support for common TestCase base class that provides additional functionality
    to receive repositories tests can also write to. This way, more aspects can be
    tested under real-world ( un-mocked ) conditions.

Tree

  • former 'name' member renamed to path as it suits the actual data better
  • added traverse method allowing to recursively traverse tree items
  • deleted blob method
  • added blobs and trees properties allowing to query the respective items in the
    tree
  • now mimics behaviour of a read-only list instead of a dict to maintain order.
  • content_from_string method is now private and not part of the public API anymore

0.1.6

General

  • Added in Sphinx documentation.

  • Removed ambiguity between paths and treeishs. When calling commands that
    accept treeish and path arguments and there is a path with the same name as
    a treeish git cowardly refuses to pick one and asks for the command to use
    the unambiguous syntax where '--' separates the treeish from the paths.

  • Repo.commits, Repo.commits_between, Repo.commits_since,
    Repo.commit_count, Repo.commit, Commit.count and
    Commit.find_all all now optionally take a path argument which
    constrains the lookup by path. This changes the order of the positional
    arguments in Repo.commits and Repo.commits_since.

Commit

  • Commit.message now contains the full commit message (rather than just
    the first line) and a new property Commit.summary contains the first
    line of the commit message.

  • Fixed a failure when trying to lookup the stats of a parentless commit from
    a bare repo.

Diff

  • The diff parser is now far faster and also addresses a bug where
    sometimes b_mode was not set.

  • Added support for parsing rename info to the diff parser. Addition of new
    properties Diff.renamed, Diff.rename_from, and Diff.rename_to.

  • Corrected problem where branches was only returning the last path component
    instead of the entire path component following refs/heads/.

Repo

  • Modified the gzip archive creation to use the python gzip module.

  • Corrected commits_between always returning None instead of the reversed
    list.

0.1.5

General

  • upgraded to Mock 0.4 dependency.

  • Replace GitPython with git in repr() outputs.

  • Fixed packaging issue caused by ez_setup.py.

Blob

  • No longer strip newlines from Blob data.

Commit

Repo

  • Corrected problems with creating bare repositories.

  • Repo.tree no longer accepts a path argument. Use:

    dict(k, o for k, o in tree.items() if k in paths)

  • Made daemon export a property of Repo. Now you can do this:

    exported = repo.daemon_export
    repo.daemon_export = True

  • Allows modifying the project description. Do this:

    repo.description = "Foo Bar"
    repo.description
    'Foo Bar'

  • Added a read-only property Repo.is_dirty which reflects the status of the
    working directory.

  • Added a read-only Repo.active_branch property which returns the name of the
    currently active branch.

Tree

  • Switched to using a dictionary for Tree contents since you will usually want
    to access them by name and order is unimportant.

  • Implemented a dictionary protocol for Tree objects. The following:

    child = tree.contents['grit']

    becomes:

    child = tree['grit']

  • Made Tree.content_from_string a static method.

0.1.4.1

  • removed method_missing stuff and replaced with a __getattr__
    override in Git.

0.1.4

  • renamed git_python to git. Be sure to delete all pyc files before
    testing.

Commit

  • Fixed problem with commit stats not working under all conditions.

Git

  • Renamed module to cmd.

  • Removed shell escaping completely.

  • Added support for stderr, stdin, and with_status.

  • git_dir is now optional in the constructor for git.Git. Git now
    falls back to os.getcwd() when git_dir is not specified.

  • add a with_exceptions keyword argument to git commands.
    GitCommandError is raised when the exit status is non-zero.

  • add support for a GIT_PYTHON_TRACE environment variable.
    GIT_PYTHON_TRACE allows us to debug GitPython's usage of git through
    the use of an environment variable.

Tree

  • Fixed up problem where name doesn't exist on root of tree.

Repo

  • Corrected problem with creating bare repo. Added Repo.create alias.

0.1.2

Tree

  • Corrected problem with Tree.__div__ not working with zero length files.
    Removed __len__ override and replaced with size instead. Also made size
    cache properly. This is a breaking change.

0.1.1

Fixed up some urls because I'm a moron

0.1.0

initial release


File: doc/source/index.rst

.. GitPython documentation master file, created by sphinx-quickstart on Sat Jan 24 11:51:01 2009.
You can adapt this file completely to your liking, but it should at least
contain the root toctree directive.

GitPython Documentation

.. toctree::
:maxdepth: 2

intro
quickstart
tutorial
reference
roadmap
changes

Indices and tables

  • :ref:genindex
  • :ref:modindex
  • :ref:search

File: doc/source/intro.rst

.. _intro_toplevel:

================== Overview / Install

GitPython is a python library used to interact with git repositories, high-level like git-porcelain, or low-level like git-plumbing.

It provides abstractions of git objects for easy access of repository data, and additionally allows you to access the git repository more directly using either a pure python implementation, or the faster, but more resource intensive git command implementation.

The object database implementation is optimized for handling large quantities of objects and large datasets, which is achieved by using low-level structures and data streaming.

Requirements

  • Python_ >= 3.7
  • Git_ 1.7.0 or newer
    It should also work with older versions, but it may be that some operations
    involving remotes will not work as expected.
  • GitDB_ - a pure python git database implementation
  • typing_extensions_ >= 3.7.3.4 (if python < 3.10)

.. _Python: https://www.python.org
.. _Git: https://git-scm.com/
.. _GitDB: https://pypi.python.org/pypi/gitdb
.. _typing_extensions: https://pypi.org/project/typing-extensions/

Installing GitPython

Installing GitPython is easily done using
pip_. Assuming it is
installed, just run the following from the command-line:

.. sourcecode:: none

text
# pip install GitPython

This command will download the latest version of GitPython from the
Python Package Index <http://pypi.python.org/pypi/GitPython>_ and install it
to your system. More information about pip and pypi can be found
here:

  • install pip <https://pip.pypa.io/en/latest/installing.html>_
  • pypi <https://pypi.python.org/pypi/GitPython>_

.. _pip: https://pip.pypa.io/en/latest/installing.html

Alternatively, you can install from the distribution using the setup.py
script:

.. sourcecode:: none

text
# python setup.py install

.. note:: In this case, you have to manually install GitDB_ as well. It would be recommended to use the :ref:git source repository in that case.

Limitations

Leakage of System Resources

GitPython is not suited for long-running processes (like daemons) as it tends to
leak system resources. It was written in a time where destructors (as implemented
in the __del__ method) still ran deterministically.

In case you still want to use it in such a context, you will want to search the
codebase for __del__ implementations and call these yourself when you see fit.

Another way assure proper cleanup of resources is to factor out GitPython into a
separate process which can be dropped periodically.

Getting Started

  • :ref:tutorial-label - This tutorial provides a walk-through of some of
    the basic functionality and concepts used in GitPython. It, however, is not
    exhaustive so you are encouraged to spend some time in the
    :ref:api_reference_toplevel.

API Reference

An organized section of the GitPython API is at :ref:api_reference_toplevel.

.. _source-code-label:

Source Code

GitPython's git repo is available on GitHub, which can be browsed at:

and cloned using::

text
$ git clone https://github.com/gitpython-developers/GitPython git-python

Finally verify the installation by running unit tests::

text
$ python -m unittest

Questions and Answers

Please use stackoverflow for questions, and don't forget to tag it with gitpython to assure the right people see the question in a timely manner.

http://stackoverflow.com/questions/tagged/gitpython

Issue Tracker

The issue tracker is hosted by GitHub:

https://github.com/gitpython-developers/GitPython/issues

License Information

GitPython is licensed under the New BSD License. See the LICENSE file for
more information.


File: doc/source/quickstart.rst

.. _quickdoc_toplevel:

.. highlight:: python

.. _quickdoc-label:

============================== GitPython Quick Start Tutorial

Welcome to the GitPython Quickstart Guide! Designed for developers seeking a practical and interactive learning experience, this concise resource offers step-by-step code snippets to swiftly initialize/clone repositories, perform essential Git operations, and explore GitPython's capabilities. Get ready to dive in, experiment, and unleash the power of GitPython in your projects!

git.Repo


There are a few ways to create a :class:git.Repo <git.repo.base.Repo> object

Initialize a new git Repo
#########################

text
.. literalinclude:: ../../test/test_quick_doc.py
    :language: python
    :dedent: 8
    :start-after: # [1-test_init_repo_object]
    :end-before: # ![1-test_init_repo_object]

Existing local git Repo
#######################

text
.. literalinclude:: ../../test/test_quick_doc.py
    :language: python
    :dedent: 8
    :start-after: # [2-test_init_repo_object]
    :end-before: # ![2-test_init_repo_object]

Clone from URL
##############

For the rest of this tutorial we will use a clone from https://github.com/gitpython-developers/QuickStartTutorialFiles.git

text
.. literalinclude:: ../../test/test_quick_doc.py
    :language: python
    :dedent: 8
    :start-after: # [1-test_cloned_repo_object]
    :end-before: # ![1-test_cloned_repo_object]

Trees & Blobs


Latest Commit Tree
##################

text
.. literalinclude:: ../../test/test_quick_doc.py
        :language: python
        :dedent: 8
        :start-after: # [12-test_cloned_repo_object]
        :end-before: # ![12-test_cloned_repo_object]

Any Commit Tree
###############

text
.. literalinclude:: ../../test/test_quick_doc.py
        :language: python
        :dedent: 8
        :start-after: # [13-test_cloned_repo_object]
        :end-before: # ![13-test_cloned_repo_object]

Display level 1 Contents
########################

text
.. literalinclude:: ../../test/test_quick_doc.py
        :language: python
        :dedent: 8
        :start-after: # [14-test_cloned_repo_object]
        :end-before: # ![14-test_cloned_repo_object]

Recurse through the Tree
########################

text
.. literalinclude:: ../../test/test_quick_doc.py
        :language: python
        :dedent: 8
        :start-after: # [15-test_cloned_repo_object]
        :end-before: # ![15-test_cloned_repo_object]

.. literalinclude:: ../../test/test_quick_doc.py
        :language: python
        :dedent: 8
        :start-after: # [16-test_cloned_repo_object]
        :end-before: # ![16-test_cloned_repo_object]

Usage


Add file to staging area
########################

text
.. literalinclude:: ../../test/test_quick_doc.py
    :language: python
    :dedent: 8
    :start-after: # [2-test_cloned_repo_object]
    :end-before: # ![2-test_cloned_repo_object]

Now lets add the updated file to git

.. literalinclude:: ../../test/test_quick_doc.py
    :language: python
    :dedent: 8
    :start-after: # [3-test_cloned_repo_object]
    :end-before: # ![3-test_cloned_repo_object]

Notice the add method requires a list as a parameter

Warning: If you experience any trouble with this, try to invoke :class:`git <git.cmd.Git>` instead via repo.git.add(path)

Commit

text
.. literalinclude:: ../../test/test_quick_doc.py
    :language: python
    :dedent: 8
    :start-after: # [4-test_cloned_repo_object]
    :end-before: # ![4-test_cloned_repo_object]

List of commits associated with a file
#######################################

text
.. literalinclude:: ../../test/test_quick_doc.py
    :language: python
    :dedent: 8
    :start-after: # [5-test_cloned_repo_object]
    :end-before: # ![5-test_cloned_repo_object]

Notice this returns a generator object

.. literalinclude:: ../../test/test_quick_doc.py
    :language: python
    :dedent: 8
    :start-after: # [6-test_cloned_repo_object]
    :end-before: # ![6-test_cloned_repo_object]

returns list of :class:`Commit <git.objects.commit.Commit>` objects

Printing text files
####################
Lets print the latest version of <local_dir>/dir1/file2.txt

text
.. literalinclude:: ../../test/test_quick_doc.py
        :language: python
        :dedent: 8
        :start-after: # [17-test_cloned_repo_object]
        :end-before: # ![17-test_cloned_repo_object]

.. literalinclude:: ../../test/test_quick_doc.py
        :language: python
        :dedent: 8
        :start-after: # [18-test_cloned_repo_object]
        :end-before: # ![18-test_cloned_repo_object]

Previous version of `<local_dir>/dir1/file2.txt`

.. literalinclude:: ../../test/test_quick_doc.py
        :language: python
        :dedent: 8
        :start-after: # [18.1-test_cloned_repo_object]
        :end-before: # ![18.1-test_cloned_repo_object]

Status

text
* Untracked files

    Lets create a new file

    .. literalinclude:: ../../test/test_quick_doc.py
        :language: python
        :dedent: 8
        :start-after: # [7-test_cloned_repo_object]
        :end-before: # ![7-test_cloned_repo_object]

    .. literalinclude:: ../../test/test_quick_doc.py
        :language: python
        :dedent: 8
        :start-after: # [8-test_cloned_repo_object]
        :end-before: # ![8-test_cloned_repo_object]

* Modified files

    .. literalinclude:: ../../test/test_quick_doc.py
        :language: python
        :dedent: 8
        :start-after: # [9-test_cloned_repo_object]
        :end-before: # ![9-test_cloned_repo_object]

    .. literalinclude:: ../../test/test_quick_doc.py
        :language: python
        :dedent: 8
        :start-after: # [10-test_cloned_repo_object]
        :end-before: # ![10-test_cloned_repo_object]

    returns a list of :class:`Diff <git.diff.Diff>` objects

    .. literalinclude:: ../../test/test_quick_doc.py
        :language: python
        :dedent: 8
        :start-after: # [11-test_cloned_repo_object]
        :end-before: # ![11-test_cloned_repo_object]

Diffs

Compare staging area to head commit

text
.. literalinclude:: ../../test/test_quick_doc.py
        :language: python
        :dedent: 8
        :start-after: # [11.1-test_cloned_repo_object]
        :end-before: # ![11.1-test_cloned_repo_object]

.. literalinclude:: ../../test/test_quick_doc.py
        :language: python
        :dedent: 8
        :start-after: # [11.2-test_cloned_repo_object]
        :end-before: # ![11.2-test_cloned_repo_object]

Compare commit to commit

text
.. literalinclude:: ../../test/test_quick_doc.py
        :language: python
        :dedent: 8
        :start-after: # [11.3-test_cloned_repo_object]
        :end-before: # ![11.3-test_cloned_repo_object]

More Resources


Remember, this is just the beginning! There's a lot more you can achieve with GitPython in your development workflow.
To explore further possibilities and discover advanced features, check out the full :ref:GitPython tutorial <tutorial_toplevel>
and the :ref:API Reference <api_reference_toplevel>. Happy coding!


File: doc/source/reference.rst

.. _api_reference_toplevel:

API Reference

Top-Level

.. py:data:: git.version

Current GitPython version.

.. automodule:: git
:members: refresh

Objects.Base

.. automodule:: git.objects.base
:members:
:undoc-members:
:special-members:

Objects.Blob

.. automodule:: git.objects.blob
:members:
:undoc-members:
:special-members:

Objects.Commit

.. automodule:: git.objects.commit
:members:
:undoc-members:
:special-members:

Objects.Tag

.. automodule:: git.objects.tag
:members:
:undoc-members:
:special-members:

Objects.Tree

.. automodule:: git.objects.tree
:members:
:undoc-members:
:special-members:

Objects.Functions

.. automodule:: git.objects.fun
:members:
:undoc-members:
:special-members:

Objects.Submodule.base

.. automodule:: git.objects.submodule.base
:members:
:undoc-members:
:special-members:

Objects.Submodule.root

.. automodule:: git.objects.submodule.root
:members:
:undoc-members:
:special-members:

Objects.Submodule.util

.. automodule:: git.objects.submodule.util
:members:
:undoc-members:
:special-members:

Objects.Util

.. automodule:: git.objects.util
:members:
:undoc-members:
:private-members: _get_intermediate_items, _list_traverse, _traverse
:special-members:

Index.Base

.. automodule:: git.index.base
:members:
:undoc-members:
:special-members:

Index.Functions

.. automodule:: git.index.fun
:members:
:undoc-members:
:special-members:

Index.Types

.. automodule:: git.index.typ
:members:
:undoc-members:
:special-members:

Index.Util

.. automodule:: git.index.util
:members:
:undoc-members:
:special-members:

GitCmd

.. automodule:: git.cmd
:members:
:undoc-members:
:special-members:

Config

.. automodule:: git.config
:members:
:undoc-members:
:special-members:

Diff

.. automodule:: git.diff
:members:
:undoc-members:
:special-members:

Exceptions

.. automodule:: git.exc
:members:
:undoc-members:
:special-members:

Refs.symbolic

.. automodule:: git.refs.symbolic
:members:
:undoc-members:
:special-members:

Refs.reference

.. automodule:: git.refs.reference
:members:
:undoc-members:
:special-members:

Refs.head

.. automodule:: git.refs.head
:members:
:undoc-members:
:special-members:

Refs.tag

.. automodule:: git.refs.tag
:members:
:undoc-members:
:special-members:

Refs.remote

.. automodule:: git.refs.remote
:members:
:undoc-members:
:special-members:

Refs.log

.. automodule:: git.refs.log
:members:
:undoc-members:
:special-members:

Remote

.. automodule:: git.remote
:members:
:undoc-members:
:special-members:

Repo.Base

.. automodule:: git.repo.base
:members:
:undoc-members:
:special-members:

Repo.Functions

.. automodule:: git.repo.fun
:members:
:undoc-members:
:special-members:

Compat

.. automodule:: git.compat
:members:
:undoc-members:
:special-members:

DB

.. automodule:: git.db
:members:
:undoc-members:
:special-members:

Types

.. automodule:: git.types
:members:
:undoc-members:
:special-members:

Util

.. automodule:: git.util
:members:
:undoc-members:
:special-members:


File: doc/source/roadmap.rst

#######
Roadmap
#######
The full list of milestones including associated tasks can be found on GitHub:
https://github.com/gitpython-developers/GitPython/issues

Select the respective milestone to filter the list of issues accordingly.


File: doc/source/tutorial.rst

.. _tutorial_toplevel:

.. highlight:: python

.. _tutorial-label:

================== GitPython Tutorial

GitPython provides object model access to your git repository. This tutorial is composed of multiple sections, most of which explain a real-life use case.

All code presented here originated from test_docs.py <https://github.com/gitpython-developers/GitPython/blob/main/test/test_docs.py>_ to assure correctness. Knowing this should also allow you to more easily run the code for your own testing purposes. All you need is a developer installation of git-python.

Meet the Repo type


The first step is to create a :class:git.Repo <git.repo.base.Repo> object to represent your repository.

.. literalinclude:: ../../test/test_docs.py
:language: python
:dedent: 8
:start-after: # [1-test_init_repo_object]
:end-before: # ![1-test_init_repo_object]

In the above example, the directory self.rorepo.working_tree_dir equals /Users/mtrier/Development/git-python and is my working repository which contains the .git directory. You can also initialize GitPython with a bare repository.

.. literalinclude:: ../../test/test_docs.py
:language: python
:dedent: 8
:start-after: # [2-test_init_repo_object]
:end-before: # ![2-test_init_repo_object]

A repo object provides high-level access to your data, it allows you to create and delete heads, tags and remotes and access the configuration of the repository.

.. literalinclude:: ../../test/test_docs.py
:language: python
:dedent: 8
:start-after: # [3-test_init_repo_object]
:end-before: # ![3-test_init_repo_object]

Query the active branch, query untracked files or whether the repository data has been modified.

.. literalinclude:: ../../test/test_docs.py
:language: python
:dedent: 8
:start-after: # [4-test_init_repo_object]
:end-before: # ![4-test_init_repo_object]

Clone from existing repositories or initialize new empty ones.

.. literalinclude:: ../../test/test_docs.py
:language: python
:dedent: 8
:start-after: # [5-test_init_repo_object]
:end-before: # ![5-test_init_repo_object]

Archive the repository contents to a tar file.

.. literalinclude:: ../../test/test_docs.py
:language: python
:dedent: 8
:start-after: # [6-test_init_repo_object]
:end-before: # ![6-test_init_repo_object]

Advanced Repo Usage

And of course, there is much more you can do with this type, most of the following will be explained in greater detail in specific tutorials. Don't worry if you don't understand some of these examples right away, as they may require a thorough understanding of git's inner workings.

Query relevant repository paths ...

.. literalinclude:: ../../test/test_docs.py
:language: python
:dedent: 8
:start-after: # [7-test_init_repo_object]
:end-before: # ![7-test_init_repo_object]

:class:Heads <git.refs.head.Head> Heads are branches in git-speak. :class:References <git.refs.reference.Reference> are pointers to a specific commit or to other references. Heads and :class:Tags <git.refs.tag.TagReference> are a kind of references. GitPython allows you to query them rather intuitively.

.. literalinclude:: ../../test/test_docs.py
:language: python
:dedent: 8
:start-after: # [8-test_init_repo_object]
:end-before: # ![8-test_init_repo_object]

You can also create new heads ...

.. literalinclude:: ../../test/test_docs.py
:language: python
:dedent: 8
:start-after: # [9-test_init_repo_object]
:end-before: # ![9-test_init_repo_object]

... and tags ...

.. literalinclude:: ../../test/test_docs.py
:language: python
:dedent: 8
:start-after: # [10-test_init_repo_object]
:end-before: # ![10-test_init_repo_object]

You can traverse down to :class:git objects <git.objects.base.Object> through references and other objects. Some objects like :class:commits <git.objects.commit.Commit> have additional meta-data to query.

.. literalinclude:: ../../test/test_docs.py
:language: python
:dedent: 8
:start-after: # [11-test_init_repo_object]
:end-before: # ![11-test_init_repo_object]

:class:Remotes <git.remote.Remote> allow to handle fetch, pull and push operations, while providing optional real-time progress information to :class:progress delegates <git.util.RemoteProgress>.

.. literalinclude:: ../../test/test_docs.py
:language: python
:dedent: 8
:start-after: # [12-test_init_repo_object]
:end-before: # ![12-test_init_repo_object]

The :class:index <git.index.base.IndexFile> is also called stage in git-speak. It is used to prepare new commits, and can be used to keep results of merge operations. Our index implementation allows to stream date into the index, which is useful for bare repositories that do not have a working tree.

.. literalinclude:: ../../test/test_docs.py
:language: python
:dedent: 8
:start-after: # [13-test_init_repo_object]
:end-before: # ![13-test_init_repo_object]

:class:Submodules <git.objects.submodule.Submodule> represent all aspects of git submodules, which allows you query all of their related information, and manipulate in various ways.

.. literalinclude:: ../../test/test_docs.py
:language: python
:dedent: 8
:start-after: # [14-test_init_repo_object]
:end-before: # ![14-test_init_repo_object]

Examining References


:class:References <git.refs.reference.Reference> are the tips of your commit graph from which you can easily examine the history of your project.

.. literalinclude:: ../../test/test_docs.py
:language: python
:dedent: 8
:start-after: # [1-test_references_and_objects]
:end-before: # ![1-test_references_and_objects]

:class:Tags <git.refs.tag.TagReference> are (usually immutable) references to a commit and/or a tag object.

.. literalinclude:: ../../test/test_docs.py
:language: python
:dedent: 8
:start-after: # [2-test_references_and_objects]
:end-before: # ![2-test_references_and_objects]

A :class:symbolic reference <git.refs.symbolic.SymbolicReference> is a special case of a reference as it points to another reference instead of a commit.

.. literalinclude:: ../../test/test_docs.py
:language: python
:dedent: 8
:start-after: # [3-test_references_and_objects]
:end-before: # ![3-test_references_and_objects]

Access the :class:reflog <git.refs.log.RefLog> easily.

.. literalinclude:: ../../test/test_docs.py
:language: python
:dedent: 8
:start-after: # [4-test_references_and_objects]
:end-before: # ![4-test_references_and_objects]

Modifying References


You can easily create and delete :class:reference types <git.refs.reference.Reference> or modify where they point to.

.. literalinclude:: ../../test/test_docs.py
:language: python
:dedent: 8
:start-after: # [5-test_references_and_objects]
:end-before: # ![5-test_references_and_objects]

Create or delete :class:tags <git.refs.tag.TagReference> the same way except you may not change them afterwards.

.. literalinclude:: ../../test/test_docs.py
:language: python
:dedent: 8
:start-after: # [6-test_references_and_objects]
:end-before: # ![6-test_references_and_objects]

Change the :class:symbolic reference <git.refs.symbolic.SymbolicReference> to switch branches cheaply (without adjusting the index or the working tree).

.. literalinclude:: ../../test/test_docs.py
:language: python
:dedent: 8
:start-after: # [7-test_references_and_objects]
:end-before: # ![7-test_references_and_objects]

Understanding Objects


An Object is anything storable in git's object database. Objects contain information about their type, their uncompressed size as well as the actual data. Each object is uniquely identified by a binary SHA1 hash, being 20 bytes in size, or 40 bytes in hexadecimal notation.

Git only knows 4 distinct object types being :class:Blobs <git.objects.blob.Blob>, :class:Trees <git.objects.tree.Tree>, :class:Commits <git.objects.commit.Commit> and :class:Tags <git.objects.tag.TagObject>.

In GitPython, all objects can be accessed through their common base, can be compared and hashed. They are usually not instantiated directly, but through references or specialized repository functions.

.. literalinclude:: ../../test/test_docs.py
:language: python
:dedent: 8
:start-after: # [8-test_references_and_objects]
:end-before: # ![8-test_references_and_objects]

Common fields are ...

.. literalinclude:: ../../test/test_docs.py
:language: python
:dedent: 8
:start-after: # [9-test_references_and_objects]
:end-before: # ![9-test_references_and_objects]

:class:Index objects <git.objects.base.IndexObject> are objects that can be put into git's index. These objects are trees, blobs and submodules which additionally know about their path in the file system as well as their mode.

.. literalinclude:: ../../test/test_docs.py
:language: python
:dedent: 8
:start-after: # [10-test_references_and_objects]
:end-before: # ![10-test_references_and_objects]

Access :class:blob <git.objects.blob.Blob> data (or any object data) using streams.

.. literalinclude:: ../../test/test_docs.py
:language: python
:dedent: 8
:start-after: # [11-test_references_and_objects]
:end-before: # ![11-test_references_and_objects]

The Commit object


:class:Commit <git.objects.commit.Commit> objects contain information about a specific commit. Obtain commits using references as done in Examining References_ or as follows.

Obtain commits at the specified revision

.. literalinclude:: ../../test/test_docs.py
:language: python
:dedent: 8
:start-after: # [12-test_references_and_objects]
:end-before: # ![12-test_references_and_objects]

Iterate 50 commits, and if you need paging, you can specify a number of commits to skip.

.. literalinclude:: ../../test/test_docs.py
:language: python
:dedent: 8
:start-after: # [13-test_references_and_objects]
:end-before: # ![13-test_references_and_objects]

A commit object carries all sorts of meta-data

.. literalinclude:: ../../test/test_docs.py
:language: python
:dedent: 8
:start-after: # [14-test_references_and_objects]
:end-before: # ![14-test_references_and_objects]

Note: date time is represented in a seconds since epoch format. Conversion to human readable form can be accomplished with the various time module <http://docs.python.org/library/time.html>_ methods.

.. literalinclude:: ../../test/test_docs.py
:language: python
:dedent: 8
:start-after: # [15-test_references_and_objects]
:end-before: # ![15-test_references_and_objects]

You can traverse a commit's ancestry by chaining calls to parents

.. literalinclude:: ../../test/test_docs.py
:language: python
:dedent: 8
:start-after: # [16-test_references_and_objects]
:end-before: # ![16-test_references_and_objects]

The above corresponds to master^^^ or master~3 in git parlance.

The Tree object


A :class:tree <git.objects.tree.Tree> records pointers to the contents of a directory. Let's say you want the root tree of the latest commit on the master branch

.. literalinclude:: ../../test/test_docs.py
:language: python
:dedent: 8
:start-after: # [17-test_references_and_objects]
:end-before: # ![17-test_references_and_objects]

Once you have a tree, you can get its contents

.. literalinclude:: ../../test/test_docs.py
:language: python
:dedent: 8
:start-after: # [18-test_references_and_objects]
:end-before: # ![18-test_references_and_objects]

It is useful to know that a tree behaves like a list with the ability to query entries by name

.. literalinclude:: ../../test/test_docs.py
:language: python
:dedent: 8
:start-after: # [19-test_references_and_objects]
:end-before: # ![19-test_references_and_objects]

There is a convenience method that allows you to get a named sub-object from a tree with a syntax similar to how paths are written in a posix system

.. literalinclude:: ../../test/test_docs.py
:language: python
:dedent: 8
:start-after: # [20-test_references_and_objects]
:end-before: # ![20-test_references_and_objects]

You can also get a commit's root tree directly from the repository

.. literalinclude:: ../../test/test_docs.py
:language: python
:dedent: 8
:start-after: # [21-test_references_and_objects]
:end-before: # ![21-test_references_and_objects]

As trees allow direct access to their intermediate child entries only, use the traverse method to obtain an iterator to retrieve entries recursively

.. literalinclude:: ../../test/test_docs.py
:language: python
:dedent: 8
:start-after: # [22-test_references_and_objects]
:end-before: # ![22-test_references_and_objects]

.. note:: If trees return Submodule objects, they will assume that they exist at the current head's commit. The tree it originated from may be rooted at another commit though, that it doesn't know. That is why the caller would have to set the submodule's owning or parent commit using the set_parent_commit(my_commit) method.

The Index Object


The git index is the stage containing changes to be written with the next commit or where merges finally have to take place. You may freely access and manipulate this information using the :class:IndexFile <git.index.base.IndexFile> object.
Modify the index with ease

.. literalinclude:: ../../test/test_docs.py
:language: python
:dedent: 8
:start-after: # [23-test_references_and_objects]
:end-before: # ![23-test_references_and_objects]

Create new indices from other trees or as result of a merge. Write that result to a new index file for later inspection.

.. literalinclude:: ../../test/test_docs.py
:language: python
:dedent: 8
:start-after: # [24-test_references_and_objects]
:end-before: # ![24-test_references_and_objects]

Handling Remotes


:class:Remotes <git.remote.Remote> are used as alias for a foreign repository to ease pushing to and fetching from them

.. literalinclude:: ../../test/test_docs.py
:language: python
:dedent: 8
:start-after: # [25-test_references_and_objects]
:end-before: # ![25-test_references_and_objects]

You can easily access configuration information for a remote by accessing options as if they were attributes. The modification of remote configuration is more explicit though.

.. literalinclude:: ../../test/test_docs.py
:language: python
:dedent: 8
:start-after: # [26-test_references_and_objects]
:end-before: # ![26-test_references_and_objects]

You can also specify per-call custom environments using a new context manager on the Git command, e.g. for using a specific SSH key. The following example works with git starting at v2.3::

text
ssh_cmd = 'ssh -i id_deployment_key'
with repo.git.custom_environment(GIT_SSH_COMMAND=ssh_cmd):
    repo.remotes.origin.fetch()

This one sets a custom script to be executed in place of ssh, and can be used in git prior to v2.3::

text
ssh_executable = os.path.join(rw_dir, 'my_ssh_executable.sh')
with repo.git.custom_environment(GIT_SSH=ssh_executable):
    repo.remotes.origin.fetch()

Here's an example executable that can be used in place of the ssh_executable above:

.. code-block:: shell

text
#!/bin/sh
ID_RSA=/var/lib/openshift/5562b947ecdd5ce939000038/app-deployments/id_rsa
exec /usr/bin/ssh -o StrictHostKeyChecking=no -i $ID_RSA "$@"

Please note that the script must be executable (i.e. chmod +x script.sh). StrictHostKeyChecking=no is used to avoid prompts asking to save the hosts key to ~/.ssh/known_hosts, which happens in case you run this as daemon.

You might also have a look at Git.update_environment(...) in case you want to setup a changed environment more permanently.

Submodule Handling


:class:Submodules <git.objects.submodule.base.Submodule> can be conveniently handled using the methods provided by GitPython, and as an added benefit, GitPython provides functionality which behave smarter and less error prone than its original c-git implementation, that is GitPython tries hard to keep your repository consistent when updating submodules recursively or adjusting the existing configuration.

.. literalinclude:: ../../test/test_docs.py
:language: python
:dedent: 8
:start-after: # [1-test_submodules]
:end-before: # ![1-test_submodules]

In addition to the query functionality, you can move the submodule's repository to a different path <move(...)>,
write its configuration <config_writer().set_value(...).release()>, update its working tree <update(...)>,
and remove or add them <remove(...), add(...)>.

If you obtained your submodule object by traversing a tree object which is not rooted at the head's commit,
you have to inform the submodule about its actual commit to retrieve the data from
by using the set_parent_commit(...) method.

The special :class:RootModule <git.objects.submodule.root.RootModule> type allows you to treat your superproject (master repository) as root of a hierarchy of submodules, which allows very convenient submodule handling. Its update(...) method is reimplemented to provide an advanced way of updating submodules as they change their values over time. The update method will track changes and make sure your working tree and submodule checkouts stay consistent, which is very useful in case submodules get deleted or added to name just two of the handled cases.

Additionally, GitPython adds functionality to track a specific branch, instead of just a commit. Supported by customized update methods, you are able to automatically update submodules to the latest revision available in the remote repository, as well as to keep track of changes and movements of these submodules. To use it, set the name of the branch you want to track to the submodule.$name.branch option of the .gitmodules file, and use GitPython update methods on the resulting repository with the to_latest_revision parameter turned on. In the latter case, the sha of your submodule will be ignored, instead a local tracking branch will be updated to the respective remote branch automatically, provided there are no local changes. The resulting behaviour is much like the one of svn::externals, which can be useful in times.

Obtaining Diff Information


Diffs can generally be obtained by subclasses of :class:Diffable <git.diff.Diffable> as they provide the diff method. This operation yields a :class:DiffIndex <git.diff.DiffIndex> allowing you to easily access diff information about paths.

Diffs can be made between the Index and Trees, Index and the working tree, trees and trees as well as trees and the working copy. If commits are involved, their tree will be used implicitly.

.. literalinclude:: ../../test/test_docs.py
:language: python
:dedent: 8
:start-after: # [27-test_references_and_objects]
:end-before: # ![27-test_references_and_objects]

The item returned is a DiffIndex which is essentially a list of Diff objects. It provides additional filtering to ease finding what you might be looking for.

.. literalinclude:: ../../test/test_docs.py
:language: python
:dedent: 8
:start-after: # [28-test_references_and_objects]
:end-before: # ![28-test_references_and_objects]

Use the diff framework if you want to implement git-status like functionality.

  • A diff between the index and the commit's tree your HEAD points to

  • use repo.index.diff(repo.head.commit)

  • A diff between the index and the working tree

  • use repo.index.diff(None)

  • A list of untracked files

  • use repo.untracked_files

Switching Branches


To switch between branches similar to git checkout, you effectively need to point your HEAD symbolic reference to the new branch and reset your index and working copy to match. A simple manual way to do it is the following one

.. literalinclude:: ../../test/test_docs.py
:language: python
:dedent: 8
:start-after: # [29-test_references_and_objects]
:end-before: # ![29-test_references_and_objects]

The previous approach would brutally overwrite the user's changes in the working copy and index though and is less sophisticated than a git-checkout. The latter will generally prevent you from destroying your work. Use the safer approach as follows.

.. literalinclude:: ../../test/test_docs.py
:language: python
:dedent: 8
:start-after: # [30-test_references_and_objects]
:end-before: # ![30-test_references_and_objects]

Initializing a repository


In this example, we will initialize an empty repository, add an empty file to the index, and commit the change.

.. literalinclude:: ../../test/test_docs.py
:language: python
:dedent: 8
:start-after: def test_add_file_and_commit
:end-before: # ![test_add_file_and_commit]

Please have a look at the individual methods as they usually support a vast amount of arguments to customize their behavior.

Using git directly


In case you are missing functionality as it has not been wrapped, you may conveniently use the :class:git <git.cmd.Git> command directly. It is owned by each repository instance.

.. literalinclude:: ../../test/test_docs.py
:language: python
:dedent: 8
:start-after: # [31-test_references_and_objects]
:end-before: # ![31-test_references_and_objects]

The return value will by default be a string of the standard output channel produced by the command.

Keyword arguments translate to short and long keyword arguments on the command-line.
The special notion git.command(flag=True) will create a flag without value like command --flag.

If None is found in the arguments, it will be dropped silently. Lists and tuples passed as arguments will be unpacked recursively to individual arguments. Objects are converted to strings using the str(...) function.

Object Databases


:class:git.Repo <git.repo.base.Repo> instances are powered by its object database instance which will be used when extracting any data, or when writing new objects.

The type of the database determines certain performance characteristics, such as the quantity of objects that can be read per second, the resource usage when reading large data files, as well as the average memory footprint of your application.

GitDB

The GitDB is a pure-python implementation of the git object database. It is the default database to use in GitPython 0.3. It uses less memory when handling huge files, but will be 2 to 5 times slower when extracting large quantities of small objects from densely packed repositories::

text
repo = Repo("path/to/repo", odbt=GitDB)

.. warning::
GitDB may fail or become extremely slow when traversing trees in
repositories with very large commits (thousands of changed files in a
single commit). If you encounter RecursionError or excessive
slowness during tree traversal, switch to GitCmdObjectDB instead.

GitCmdObjectDB

The git command database uses persistent git-cat-file instances to read repository information. These operate very fast under all conditions, but will consume additional memory for the process itself. When extracting large files, memory usage will be much higher than GitDB::

text
repo = Repo("path/to/repo", odbt=GitCmdObjectDB)

Git Command Debugging and Customization


Using environment variables, you can further adjust the behaviour of the git command.

  • GIT_PYTHON_TRACE

  • If set to non-0, all executed git commands will be shown as they happen

  • If set to full, the executed git command and its entire output on stdout and stderr will be shown as they happen

NOTE: All logging is outputted using a Python logger, so make sure your program is configured to show INFO-level messages. If this is not the case, try adding the following to your program::

text
import logging
logging.basicConfig(level=logging.INFO)
  • GIT_PYTHON_GIT_EXECUTABLE

  • If set, it should contain the full path to the git executable, e.g. c:\Program Files (x86)\Git\bin\git.exe on windows or /usr/bin/git on linux.

And even more ...


There is more functionality in there, like the ability to archive repositories, get stats and logs, blame, and probably a few other things that were not mentioned here.

Check the unit tests for an in-depth introduction on how each function is supposed to be used.


File: fuzzing/README.md

Fuzzing GitPython

This directory contains files related to GitPython's suite of fuzz tests that are executed daily on automated
infrastructure provided by OSS-Fuzz. This document aims to provide necessary information for working
with fuzzing in GitPython.

The latest details regarding OSS-Fuzz test status, including build logs and coverage reports, is available
on the Open Source Fuzzing Introspection website.

How to Contribute

There are many ways to contribute to GitPython's fuzzing efforts! Contributions are welcomed through issues,
discussions, or pull requests on this repository.

Areas that are particularly appreciated include:

  • Tackling the existing backlog of open issues. While fuzzing is an effective way to identify bugs, that information
    isn't useful unless they are fixed. If you are not sure where to start, the issues tab is a great place to get ideas!
  • Improvements to this (or other) documentation make it easier for new contributors to get involved, so even small
    improvements can have a large impact over time. If you see something that could be made easier by a documentation
    update of any size, please consider suggesting it!

For everything else, such as expanding test coverage, optimizing test performance, or enhancing error detection
capabilities, jump into the "Getting Started" section below.

Getting Started with Fuzzing GitPython

[!TIP]
New to fuzzing or unfamiliar with OSS-Fuzz?

These resources are an excellent place to start:

  • OSS-Fuzz documentation - Continuous fuzzing service for open source software.
  • Google/fuzzing - Tutorials, examples, discussions, research proposals, and other resources
    related to fuzzing.

Setting Up Your Local Environment

Before contributing to fuzzing efforts, ensure Python and Docker are installed on your machine. Docker is required for
running fuzzers in containers provided by OSS-Fuzz and for safely executing test files directly. Install Docker following the official guide if you do not already have it.

Understanding Existing Fuzz Targets

Review the fuzz-targets/ directory to familiarize yourself with how existing tests are implemented. See
the Files & Directories Overview for more details on the directory structure.

Contributing to Fuzz Tests

Start by reviewing the Atheris documentation and the section
on Running Fuzzers Locally to begin writing or improving fuzz tests.

Files & Directories Overview

The fuzzing/ directory is organized into three key areas:

Fuzz Targets (`fuzz-targets/`)

Contains Python files for each fuzz test.

Things to Know:

  • Each fuzz test targets a specific part of GitPython's functionality.
  • Test files adhere to the naming convention: fuzz_<API Under Test>.py, where <API Under Test> indicates the
    functionality targeted by the test.
  • Any functionality that involves performing operations on input data is a possible candidate for fuzz testing, but
    features that involve processing untrusted user input or parsing operations are typically going to be the most
    interesting.
  • The goal of these tests is to identify previously unknown or unexpected error cases caused by a given input. For that
    reason, fuzz tests should gracefully handle anticipated exception cases with a try/except block to avoid false
    positives that halt the fuzzing engine.

OSS-Fuzz Scripts (`oss-fuzz-scripts/`)

Includes scripts for building and integrating fuzz targets with OSS-Fuzz:

  • container-environment-bootstrap.sh - Sets up the execution environment. It is responsible for fetching default
    dictionary entries and ensuring all required build dependencies are installed and up-to-date.
  • build.sh - Executed within the Docker container, this script builds fuzz targets with necessary instrumentation
    and prepares seed corpora and dictionaries for use.

Where to learn more:

Local Development Helpers (`local-dev-helpers/`)

Contains tools to make local development tasks easier.
See the "Running Fuzzers Locally" section below for further documentation and use cases related to files found here.

Running Fuzzers Locally

[!WARNING]
Some fuzz targets in this repository write to the filesystem during execution.
For that reason, it is strongly recommended to always use Docker when executing fuzz targets, even when it may be
possible to do so without it.

Although I/O operations such as writing to disk are not considered best practice, the current implementation of at least one test requires it.
See the "Setting Up Your Local Environment" section above if you do not already have Docker installed on your machine.

PRs that replace disk I/O with in-memory alternatives are very much welcomed!

Direct Execution of Fuzz Targets

Directly executing fuzz targets allows for quick iteration and testing of changes which can be helpful during early
development of new fuzz targets or for validating changes made to an existing test.
The Dockerfile located in the local-dev-helpers/ subdirectory provides a lightweight
container environment preconfigured with Atheris that makes it easy to execute a fuzz target directly.

From the root directory of your GitPython repository clone:

  1. Build the local development helper image:
shell
docker build -f fuzzing/local-dev-helpers/Dockerfile -t gitpython-fuzzdev .
  1. Then execute a fuzz target inside the image, for example:
shell
docker run -it -v "$PWD":/src gitpython-fuzzdev python fuzzing/fuzz-targets/fuzz_config.py -atheris_runs=10000

The above command executes fuzz_config.py and exits after 10000 runs, or earlier if
the fuzzer finds an error.

Docker CLI's -v flag specifies a volume mount in Docker that maps the directory in which the command is run (which
should be the root directory of your local GitPython clone) to a directory inside the container, so any modifications
made between invocations will be reflected immediately without the need to rebuild the image each time.

Running OSS-Fuzz Locally

This approach uses Docker images provided by OSS-Fuzz for building and running fuzz tests locally. It offers
comprehensive features but requires a local clone of the OSS-Fuzz repository and sufficient disk space for Docker
containers.

Build the Execution Environment

Clone the OSS-Fuzz repository and prepare the Docker environment:

shell
git clone --depth 1 https://github.com/google/oss-fuzz.git oss-fuzz
cd oss-fuzz
python infra/helper.py build_image gitpython
python infra/helper.py build_fuzzers --sanitizer address gitpython

[!TIP]
The build_fuzzers command above accepts a local file path pointing to your GitPython repository clone as the last
argument.
This makes it easy to build fuzz targets you are developing locally in this repository without changing anything in
the OSS-Fuzz repo!
For example, if you have cloned this repository (or a fork of it) into: ~/code/GitPython
Then running this command would build new or modified fuzz targets using the ~/code/GitPython/fuzzing/fuzz-targets
directory:

shell
python infra/helper.py build_fuzzers --sanitizer address gitpython ~/code/GitPython

Verify the build of your fuzzers with the optional check_build command:

shell
python infra/helper.py check_build gitpython

Run a Fuzz Target

Setting an environment variable for the fuzz target argument of the execution command makes it easier to quickly select
a different target between runs:

shell
# specify the fuzz target without the .py extension:
export FUZZ_TARGET=fuzz_config

Execute the desired fuzz target:

shell
python infra/helper.py run_fuzzer gitpython $FUZZ_TARGET -- -max_total_time=60 -print_final_stats=1

[!TIP]
In the example above, the "-- -max_total_time=60 -print_final_stats=1" portion of the command is optional but quite
useful.

Every argument provided after "--" in the above command is passed to the fuzzing engine directly. In this case:

  • -max_total_time=60 tells the LibFuzzer to stop execution after 60 seconds have elapsed.
  • -print_final_stats=1 tells the LibFuzzer to print a summary of useful metrics about the target run upon
    completion.

But almost any LibFuzzer option listed in the documentation should
work as well.

Next Steps

For detailed instructions on advanced features like reproducing OSS-Fuzz issues or using the Fuzz Introspector, refer
to the official OSS-Fuzz documentation.

LICENSE

All files located within the fuzzing/ directory are subject to the same license
as the other files in this repository with one exception:

fuzz_config.py was migrated to this repository from the OSS-Fuzz project's repository
where it was originally created. As such, fuzz_config.py retains its original license
and copyright notice (Apache License, Version 2.0 and Copyright 2023 Google LLC respectively) as in a header
comment, followed by a notice stating that it has have been modified contributors to GitPython.
LICENSE-APACHE contains the original license used by the OSS-Fuzz project repository at the time the
file was migrated.