Metadata-Version: 2.4
Name: mgit
Version: 2.1.0
Summary: Fetch collections of git projects
Author-email: Zoran Simic <zoran@simicweb.com>
License-Expression: MIT
Project-URL: Source, https://github.com/zsimic/mgit
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Operating System :: MacOS :: MacOS X
Classifier: Operating System :: POSIX
Classifier: Operating System :: Unix
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Utilities
Requires-Python: >=3.10
Description-Content-Type: text/x-rst
License-File: LICENSE
Requires-Dist: runez<6
Dynamic: license-file

mgit
====

A small companion for humans who like tidy git checkouts.

.. image:: https://img.shields.io/pypi/v/mgit.svg
    :target: https://pypi.org/project/mgit/
    :alt: Version on pypi

.. image:: https://github.com/zsimic/mgit/workflows/Tests/badge.svg
    :target: https://github.com/zsimic/mgit/actions
    :alt: Tested with Github Actions

.. image:: https://img.shields.io/pypi/pyversions/mgit.svg
    :target: https://pypi.org/project/mgit/
    :alt: Python versions tested


What it is
==========

``mgit`` is a tiny CLI for people who like their git checkouts clean, current,
and easy to scan. It gives you a quick read on one repo, or on every repo
directly inside a workspace folder.

- What state did I leave this checkout in?
- Can I pull, or did I leave work pending here?
- Is a merged branch still hanging around, waiting to be cleaned?
- I just wrapped up a branch; can I safely get back to ``main`` and clear it away?

``mgit`` is not a git replacement. It is the compact, careful layer for those
ordinary moments where you would rather see the answer than reconstruct it
from a handful of commands.


The rhythm
==========

Start with a glance::

    mgit        # show status here, or across a workspace

Refresh or move forward only when you mean to::

    mgit f      # fetch --all --prune, then show the refreshed status
    mgit p      # pull --rebase, but never over pending work

And for the wonderfully common ``PR merged`` moment::

    mgit g      # fetch, return to the default branch, pull, clean this branch

The short names are the intended interface:

- ``status`` / ``s``: show whether anything here needs attention. This is the default.
- ``fetch`` / ``f``: refresh remote refs, then show what changed.
- ``pull`` / ``p``: pull with rebase only when pending work will not be disturbed.
- ``main`` / ``m``: checkout the default branch, even if it is ``master``.
- ``branches`` / ``b``: list local branches with presence and cleanup annotations.
- ``legend`` / ``l``: explain status and branch symbols.
- ``groom`` / ``g``: safely finish with the merged branch you are currently on.

The command shape is::

    mgit [-v] [--color auto|always|never] [COMMAND] [FOLDER]

You can pass a folder to most commands::

    mgit ~/github
    mgit f ~/github
    mgit g ~/github/mgit

Workspace scans are shallow on purpose: ``mgit ~/github`` inspects direct
children like ``~/github/*/.git`` and does not crawl nested folders.


What you see
============

A workspace stays pleasantly skimmable::

        mgit: main ✅
     pickley: main ☑️ [+1🪦] ⌛4w 6d
       runez: feature 🪦 ✏️1
    detached: HEAD 👻

In one glance you get:

- the current branch
- local diffs and untracked files
- ahead/behind/gone tracking state
- fetch freshness
- a compact hint that a stale local branch is still lurking

``✅`` means recently refreshed, ``☑️`` means the local picture may be older,
``⌛`` calls out notably stale fetch information, a branch-level ``🪦`` means
the branch has been proven cleanable, and ``👻`` means detached ``HEAD``. A bracket such as
``[+2🪦+1]`` says that, besides the current and default branches, two local
branches have been proven cleanable and one remains.

The branch list spells that state out when you need to decide what is done::

    mgit b
      commands-instead-of-flags💾☁️🪦 [cleanable]
      main                            [default]
    * more-cleanup💾                  [current]
      v2gpt💾☁️

Run ``mgit legend`` for the symbol key, or ``mgit b --legend`` to append it
below the branch listing.

``💾`` means the branch is local and ``☁️`` means its configured upstream is
still present in the fetched remote refs. ``🪦 [cleanable]`` appears only
when the local branch, and any shown upstream ref, is already merged into the
default branch or is content-equivalent after a squash merge. An unpublished
branch carrying new work therefore appears as ``💾`` rather than looking
abandoned.

For a single checkout, status also prints the pending paths. Workspace output
keeps to one line per repo, so you can keep checking a directory full of
projects without turning the terminal into a log dump::

    mgit ~/github/mgit

Color is automatic on terminals and can be controlled explicitly::

    mgit --color auto
    mgit --color always
    mgit --color never


Safety model
============

``mgit`` is read-only by default. Asking how things look does not change your repos.

Commands that act are explicit:

- ``mgit f`` updates local remote refs with ``git fetch --all --prune``.
- ``mgit p`` pulls with rebase only when the checkout passes safety checks.
- ``mgit g`` fetches, verifies that the current branch can be cleaned before
  switching branches, pulls safely, and deletes that local branch only. If it
  still exists on ``origin``, it deletes that one remote branch only after
  independently proving that the fetched remote ref is merged or
  content-equivalent to the fetched default branch; an exact-ref lease prevents
  deleting a branch that advanced meanwhile. No other branch is deleted.
  When already on the default branch, it fetches and reports that fact without
  pulling or cleaning branches. Use ``mgit m`` when you only want to switch to
  the default branch.


Coming next
===========

A larger convenience waiting in the wings is ``mgit clone``: give it a full
repo URL and let ``mgit`` choose the local destination from simple config
rules.

Planned config shape::

    locations = [
        { match = "github.com/zsimic/*", dir = "~/github" },
        { match = "github.com/*",        dir = "~/ext" },
        { match = "git.mycompany.com/*", dir = "~/dev" },
    ]

The goal is predictable placement without memorizing where each family of repos
belongs. Status, fetch, pull, main, and groom do not require any mgit config.


Install
=======

Install with pickley_ or pipx_::

    pickley install mgit

or::

    pipx install mgit

To work on mgit itself, see `contributing <https://github.com/zsimic/mgit/blob/main/docs/contributing.md>`_.


.. _pickley: https://pypi.org/project/pickley/

.. _pipx: https://pypi.org/project/pipx/
