Metadata-Version: 2.5
Name: git-project
Version: 0.0.42
Summary: The extensible stupid project manager
Author-email: "David A. Greene" <dag@obbligato.org>
License-Expression: AGPL-3.0-or-later
License-File: COPYING
Keywords: development,git,project
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Topic :: Software Development :: Version Control :: Git
Requires-Python: >=3.10
Requires-Dist: progressbar2>=4.4.2
Requires-Dist: pygit2>=1.18.2
Provides-Extra: test
Requires-Dist: pytest; extra == 'test'
Requires-Dist: pytest-console-scripts; extra == 'test'
Requires-Dist: pytest-cov; extra == 'test'
Requires-Dist: setuptools; extra == 'test'
Description-Content-Type: text/x-rst


===================================================
git-project - The extensible stupid project manager
===================================================

|VersionImageLink|_

|PythonVersionImageLink|_

.. |VersionImageLink| image:: https://img.shields.io/pypi/v/git-project.svg
.. _VersionImageLink: https://pypi.org/project/git-project
.. |PythonVersionImageLink| image:: https://img.shields.io/pypi/pyversions/git-project.svg
.. _PythonVersionImageLink: https://pypi.org/project/git-project


-------

.. contents:: Table of Contents


Installation
============
::

   pip install git-project
   pip install git-project-core-plugins

git-project needs Python 3.10 or later.

Overview
========

git-project is a git extension for managing development work in a git
repository. By itself it does almost nothing. It provides ``-h``,
``--version`` and ``--menu``, and plugins provide the commands.

`git-project-core-plugins
<https://github.com/greened/git-project-core-plugins>`_ provides the basic
commands, among them ``clone``, ``init``, ``worktree``, ``branch``, ``run``
and ``config``. Install it alongside git-project.

git-project aims to make switching between tasks in a repository fast,
without losing the state of the tasks you set aside. For example, the core
plugins can give each worktree its own build directory, so moving to another
worktree does not rebuild everything.

Projects
========

git-project runs under the name of a link to it, and that name selects the
*active project*. If ``git-fizzbin`` is a symlink to ``git-project``, then
``git fizzbin <command>`` runs git-project with ``fizzbin`` as the active
project. Run as ``git-project`` itself, the active project is ``project``.
These docs write ``git <project>`` for whichever name you use.

Create the link yourself, in a directory on your ``PATH``::

  ln -s "$(command -v git-project)" ~/.local/bin/git-fizzbin

Each project keeps its settings apart from the others, so one repository can
hold several projects, each run through its own link.

Configuration
=============

git-project stores its settings in the repository's git config. A project's
settings live in a section named after the project. git-project changes
``.`` and ``_`` in the name to ``-``, so the project ``fizz_bin`` uses the
section ``fizz-bin``.

Whenever they are missing, git-project sets two values in the project
section: ``branch``, the repository's main branch, and ``remote``, which is
``origin``.

Plugins keep their own settings in subsections of the project section. For
example, a project with one worktree might hold::

  [fizzbin]
      branch = main
      remote = origin
      srcdir = /src
  [fizzbin "worktree.main"]
      builddir = {srcdir}/build

A key can hold more than one value. On every run, git-project also checks
the config file and stops if one section holds the same ``key = value`` line
twice.

Scopes
======

A *scope* is a subsection that a plugin makes active for the current run.
While a scope is active, a value set in the scope overrides the same key in
the project section. For example, when you run inside a worktree, the core
plugins' ``worktree`` plugin makes that worktree's subsection a scope. A
value set for one worktree then applies only there.

The name of an active scope is also a substitution variable, and its value
is the scope's identifier. In the example above, ``{worktree}`` is ``main``
inside the ``main`` worktree.

Substitution
============

Some values are *substituted* before they are used, for example the
commands that the ``run`` plugin runs. Substitution replaces ``{name}`` with
the value of ``name``. A name can be:

* a key in the project section
* a key in the object being substituted, or in an active scope
* the name of an active scope, as above
* one of these built-in names

``project``
    The active project's section name
``branch``
    The checked-out branch, or during a rebase the branch being rebased
``gitdir``
    The repository's git directory
``git_common_dir``
    The git directory that all worktrees share
``git_workdir``
    The root of the current worktree

Substitution repeats until the value stops changing, so a value can name
another value that itself contains ``{name}``. A value may not name itself. To
write a literal brace, write ``{{}`` for ``{`` and ``{}}`` for ``}``. A name is
ASCII letters, digits and underscores, and does not start with a digit. Other
text in single braces, such as ``{x.upper()}`` or ``{}``, stays as written, but
a doubled ``{{`` or ``}}`` becomes one brace. A name that is not defined is an
error.

Substitution inserts each value as written, and the ``run`` plugin runs
its commands through a shell. Treat the git config as code, and do not
include config from a source you do not trust.

Getting help
============

``git <project> -h`` lists the commands that the installed plugins provide.
Use ``-h`` there, because git turns ``git <project> --help`` into a request
for a man page. After a command name ``--help`` works as usual, and with the
core plugins installed ``git <project> help <command>`` shows a command's
full manual.

``--menu`` lists a command's subcommands, arguments and options in a form meant
for tools.

License
=======
`git-project` is distributed under the terms of the `GNU Affero General Public License v3.0 or later`_.

.. _`GNU Affero General Public License v3.0 or later`: https://spdx.org/licenses/AGPL-3.0-or-later.html


..
    SPDX-FileCopyrightText: 2024-present David A. Greene <dag@obbligato.org>

..
    SPDX-License-Identifier: AGPL-3.0-or-later

..
    Copyright 2023 David A. Greene

..
    This file is part of git-project

..
    git-project is free software: you can redistribute it and/or modify it under
    the terms of the GNU Affero General Public License as published by the Free
    Software Foundation, either version 3 of the License, or (at your option)
    any later version.

..
    This program is distributed in the hope that it will be useful, but WITHOUT
    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License
    for more details.

..
    You should have received a copy of the GNU Affero General Public License
    along with git-project. If not, see <https://www.gnu.org/licenses/>.

Authors
=======
*git-project* is written and maintained by |author|.

.. |author| replace:: `David Greene`_
.. _David Greene: https://github.com/greened


`0.0.42`_ - 2026-10-06
----------------------
Added
.....
- A command can set ``write_project_defaults=False`` on its parser, so that
  git-project does not write the project's default ``branch`` and
  ``remote`` to the config. A dry run can then leave the config as it was.
- ``Project.get`` takes ``set_defaults``, True by default. With False, it
  does not write the defaults.

Changed
.......
- git-project writes the project defaults after the command line is
  parsed, not when it builds the project. So ``-h``, ``--version``,
  ``--menu`` and a command-line error no longer write them. The plugin
  hooks ``add_class_hooks``, ``add_arguments`` and ``modify_arguments``
  can see a project without its default branch and remote.

Fixed
.....
- ``branch prune``, ``worktree rm`` and ``Project.prune_branch`` stopped
  and kept the local branch when a remote could not be reached, such as
  one whose URL names a host alias from ``~/.ssh/config``, which libgit2
  does not read, or when a remote refused the delete. They now warn about
  that remote on stderr and delete the local branch.

.. _Unreleased: https://github.com/greened/git-project/compare/v0.0.42...HEAD
.. _0.0.42: https://github.com/greened/git-project/compare/v0.0.41...v0.0.42
.. _0.0.41: https://github.com/greened/git-project/compare/v0.0.40...v0.0.41
.. _0.0.40: https://github.com/greened/git-project/compare/v0.0.39...v0.0.40
.. _0.0.39: https://github.com/greened/git-project/compare/v0.0.38...v0.0.39
.. _0.0.38: https://github.com/greened/git-project/compare/v0.0.37...v0.0.38

`Full Changelog <https://github.com/greened/git-project/blob/master/docs/changelog.rst>`_
