{"id":30343591,"url":"https://github.com/jmnavarrol/python-multigit","last_synced_at":"2025-08-18T11:14:04.999Z","repository":{"id":43998950,"uuid":"373770694","full_name":"jmnavarrol/python-multigit","owner":"jmnavarrol","description":"A simple way to manage git repos within git repos.","archived":false,"fork":false,"pushed_at":"2025-05-10T12:29:01.000Z","size":2899,"stargazers_count":7,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-11T03:18:22.627Z","etag":null,"topics":["development-tools","git","python"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jmnavarrol.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2021-06-04T08:17:24.000Z","updated_at":"2025-05-10T12:29:04.000Z","dependencies_parsed_at":"2023-01-21T17:18:01.463Z","dependency_job_id":"f6eeb493-e952-4768-97a7-bfe57d74d279","html_url":"https://github.com/jmnavarrol/python-multigit","commit_stats":null,"previous_names":[],"tags_count":28,"template":false,"template_full_name":null,"purl":"pkg:github/jmnavarrol/python-multigit","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jmnavarrol%2Fpython-multigit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jmnavarrol%2Fpython-multigit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jmnavarrol%2Fpython-multigit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jmnavarrol%2Fpython-multigit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jmnavarrol","download_url":"https://codeload.github.com/jmnavarrol/python-multigit/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jmnavarrol%2Fpython-multigit/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":270982229,"owners_count":24679455,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-18T02:00:08.743Z","response_time":89,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["development-tools","git","python"],"created_at":"2025-08-18T11:14:00.835Z","updated_at":"2025-08-18T11:14:04.991Z","avatar_url":"https://github.com/jmnavarrol.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Python Multigit\u003ca name=\"top\"\u003e\u003c/a\u003e\n\nA Python version of the [multigit Bash script](https://github.com/jmnavarrol/simplest-git-subrepos).\n\nWhile the multigit Bash script at [simplest-git-subrepos](https://github.com/jmnavarrol/simplest-git-subrepos) was created for illustration purposes, this one is intended to be a full-fledged implementation.\n\nThe general idea is to offer a simple way of managing *\"workspaces\"* integrating multiple git repos starting from a top one, and without the need of difficult *\"arcanes\"* like *git submodules*, *git-subtree*, etc.: you only need to declare your intended *layout* in a YAML file, and let this script (**multigit**) do its job.  See the [simplest-git-subrepos README](https://github.com/jmnavarrol/simplest-git-subrepos#readme) for a long-wired explanation.\n\n**Contents:**\u003ca name=\"contents\"\u003e\u003c/a\u003e\n1. [usage](#usage)\n   1. [subrepos' file format](#subrepos-format)\n1. [development](#development)\n   1. [code documentation](#sphinx)\n   1. [build](#build)\n   1. [publish](#publish)\n   1. [CHANGELOG](./CHANGELOG.md)\n1. [license](#license)\n\n----\n\n## usage\u003ca name=\"usage\"\u003e\u003c/a\u003e\nThis project [is published to the PyPI index](https://pypi.org/project/multigit/) so, in order to install it you just need to run `pip install multigit`.\n\n*multigit* expects a YAML file named **subrepos** in the current dir (see [example](./example/subrepos)).  Optionally, if there's no *subrepos* file in the current dir **and** the current directory is within a git sandbox, *multigit* will try to find a *subrepos* file at the git sandbox's root.\n\nFor each defined *subrepo* within the *subrepos* file, it will clone/checkout it to the defined relative path.  Optionally, it will *checkout* the given *gitref* (either *commit*, *branch* or *tag*), provided the repo's local sandbox is *\"clean\"* (i.e. no pending modifications).  \n  **NOTE:** pay attention to the fact that if the *gitref* you record is a specific *commit* or *tag*, the related sandbox will be in disconnected state.\n\n*multigit* will also recursively look for new *subrepos* files on the root directory of the repositories it manages.\n\nWhen working within a git repository, **you should make sure** your [*.gitignore* file](./.gitignore) ignores all your *subrepos*.\n\nThis way you just need to manage your repos with `git` in the standard way, just as if they were individually checked out in isolation.\n\nRun `multigit` with no options or `multigit --help` for usage.\n\n\u003csub\u003e[back to top](#top).\u003c/sub\u003e\n\n### subrepos' file format\u003ca name=\"subrepos-format\"\u003e\u003c/a\u003e\nThe *'subrepos'* file holds a yaml dictionary describing the desired lay-out.\n\nIt starts with a **subrepos** key with a list of entries underneath, each of them describing a repository entry point (see ['subrepos' example](./example/subrepos) for further details).  Some detailed explanations follow:\n* **general description:**\n  ```yml\n  ---\n  # High-level structure\n  subrepos: # main key\n  - [first entry]   # first repository description\n  - [second entry]  # second repository description\n  - [third entry]   # third repository description\n  - [...]           # (more repositories)\n  ```\n* **each repository entry:** Each repository definition requires two mandatory keys and an optional one:\n  * **repository:** (mandatory) the [URI](https://en.wikipedia.org/wiki/Uniform_Resource_Identifier \"Uniform Resource Identifier\") to operate the remote repository.  \n  Its format is just the one you'd use to `git clone` the repository with same effect, i.e. if you need to pass a username/password for an https site, or a password to decrypt you ssh key, etc. here you'll be requested to do it too.\n  * **path:** (mandatory) the path the repository sandbox will the deployed to, relative to the subrepos file itself.\n  * **[commit|branch|tag]:** (optional) the *gitref* you want your sandbox to be *pinned* to.  \n    * You can provide **one** of either *'commit'*, *'branch'* or *'tag'*.\n    * Note that if you provide either a *commit* or a *tag* the resulting sandbox will be in a [*detached head state*](https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddefdetachedHEADadetachedHEAD).\n    * If you don't provide this key, your sandbox will track the remote's default branch.\n  \n**A full (conceptual) example:**\n```yml\n---\n# Don't forget including your subrepos' roots to .gitignore!\nsubrepos:\n- repo: 'git@github.com:jmnavarrol/python-multigit.git'  # the remote using git+ssh protocol.  It may request your ssh key's password\n  path: 'a-subdir'  # it will be cloned to 'subdir/' relative to 'subrepos' file\n  # no gitref, so this will track the remote's default branch\n- repo: 'https://github.com/jmnavarrol/python-multigit.git'  # the remote using https protocol.  It may request user/password\n  path: 'a-subdir/another-subdir'  # it will be cloned to 'a-subdir/subdir/' relative to 'subrepos' file\n  branch: 'a-branch'  # the sandbox will track the 'a-branch' branch.\n```\n\n**NOTE:** Since repositories are listed in an array, order matters: first repository is processed before the second one and so on.  This means that you can declare first a repository to be deployed to a subdirectory and then another repository to be deployed to a subdirectory of that first subdirectory and things will behave as expected.  \nIt's usually better that you declare the *\"deeper\"* subdirectory within its own 'subrepos' file in the intermediate repository, though.\n\n\u003csub\u003e[back to top](#top).\u003c/sub\u003e\n\n## development\u003ca name=\"development\"\u003e\u003c/a\u003e\nThis project uses the help of [Bash Magic Enviro](https://github.com/jmnavarrol/bash-magic-enviro) to configure its development environment.\n\nIt creates a Python 3 *virtualenv* using [the companion requirements file](./python-virtualenvs/multigit-development.requirements).\n\nOnce the *virtualenv* is (automatically) activated, you can run this code just invoking its main script, i.e.: `multigit`.\n\n\u003csub\u003e[back to top](#top).\u003c/sub\u003e\n\n### code documentation\u003ca name=\"sphinx\"\u003e\u003c/a\u003e\nCode documentation is produced with the help of [Sphinx](https://www.sphinx-doc.org), with configurations at [src/sphinx/](./src/sphinx/).  While sphinx includes [its own Makefile](./src/sphinx/Makefile), HTML doc can be generated from [the Makefile at src/](./src/Makefile), starting at the local `src/build/html/index.html` file.\n\nYou can browse it on-line at https://jmnavarrol.github.io/python-multigit.\n\n\u003csub\u003e[back to top](#top).\u003c/sub\u003e\n\n### build\u003ca name=\"build\"\u003e\u003c/a\u003e\nThe [included Makefile](./src/Makefile) will use Python's [Hatch](https://hatch.pypa.io) to build both *source* and *binary-based* Python *eggs*.  Provided everything went OK, look for packages under the *dist/* directory.\n\nRun `make` to see available *make targets*.\n\n\u003csub\u003e[back to top](#top).\u003c/sub\u003e\n\n### publish\u003ca name=\"publish\"\u003e\u003c/a\u003e\nProvided *Makefile* includes publication targets to both testing and live PyPi services by means of *twine*.  Make sure your ~/.pypi.rc file includes proper entries named *[testpypi]* and *[pypi]* respectively.  Remember, also, that you can't publish the same version twice to these services, so make sure you udpate the package's version before attempting an upload.\n\n\u003csub\u003e[back to top](#top).\u003c/sub\u003e\n\n------\n\n## License\u003ca name=\"license\"\u003e\u003c/a\u003e\nPython Multigit is made available under the terms of the **GPLv3**.\n\nSee the [license file](./LICENSE) that accompanies this distribution for the full text of the license.\n\n\u003csub\u003e[back to top](#top).\u003c/sub\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjmnavarrol%2Fpython-multigit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjmnavarrol%2Fpython-multigit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjmnavarrol%2Fpython-multigit/lists"}