Package: ingit
Tool for managing a large collection of repositories in git.If you have 100 git-versioned projects, keeping tabs on everything can be quite troublesome.That’s whereingitcomes in. It mimics selected git commands, however you can perform the same
action on a group of repositories instead of just one.Additionally, it has an interactive mode in which you can go over your repositories and quickly
perform typical suggested actions in each individual repository based on its current status.ContentsOverviewBasic usageFiltering the repositoriesFiltering repositories by regular expressionFiltering repositories by predicateConfigurationRuntime configurationRepositories configurationCommand detailsingit summaryingit registeringit foreachingit cloneingit initingit fetchingit checkoutingit mergeingit pushingit gcingit statusRequirementsOverviewBasic usageFor general help, see:ingit-hFor command-specific help, see:ingitcommand-hCommands are of two kinds in general:git-like commands, which work similar to their git versions;ingit-only commands, which you won’t find in git.Currently available ingit-only commands are:ingit summarywill show summary of repositories registered in ingit;ingit registerwill add an existing git repository to ingit configuration;ingit foreachwill execute a custom command for each repository.Currently available git-like commands are:ingit clonewill mass-clone registered repositories;ingit initwill mass-init registered repositories;ingit fetchwill mass-fetch existing registered repositories;ingit checkoutwill interactively checkout branches;ingit mergewill interactively merge branches;ingit pushwill mass-push existing registered repositories;ingit gcwill do mass garbage collection of existing registered repositories;ingit statuswill give comprehensive status report for every existing registered repository.Filtering the repositoriesGit-like commands of ingit
(namely:ingit clone,ingit init,ingit fetch,ingit checkout,ingit merge,ingit push,ingit gcandingit status),
as well asingit summaryandingit foreach,
by default operate on all registered repositories.However, they all can take the options--regex/-rand--predicate/-pthat filter out the repositories using repository metadata (i.e. name, tags, path and remotes)
which is stored in the repositories configuration.If both--regex/-rand--predicate/-pare provided,
predicate is applied first.Filtering repositories by regular expressionThe--regex/-roption accepts any regular expression (also a simple string)
and filters the repos by trying to simply find a match in any of the metadata.Specifically, ingit will forward your input regular expression into this function:defregex_predicate(regex,name,tags,path,remotes):return(re.search(regex,name)isnotNoneorany(re.search(regex,tag)isnotNonefortagintags)orre.search(regex,str(path))isnotNoneorany(re.search(regex,name)forname,urlinremotes.items()))The actual implementation is here:ingit/runtime.py#L24Filtering repositories by predicateThe--predicate/-poption accepts a python boolean expression which will be inserted
into a predicate function template, as below:lambdaname,tags,path,remotes:(predicate)The actual implementation is here:ingit/main.py#L266Therefore, executingingit--predicate"'python' in tags" fetchresults
in the following predicate being applied:lambdaname,tags,path,remotes:('python'intags)And thus only repositories that have'python'in their tags are fetched.ConfigurationIngit works based on configuration in 2 JSON files:runtime configurationrepositories configurationIf either of the files doesn’t exist, defaults will be generated.The default paths to the files can be overridden via--configand--reposcommand-line options.Runtime configurationMost importantly, stores repositories root directory – it’s a directory which ingit assumes
to contain git-versioned projects.Example:{"description":"ingit runtime configuration file","ingit-version":"0.4.0","machines":[{"name":"desktop","repos_path":"~/Projects"},{"interactive":false,"names":["server","server.domain.com"],"repos_path":"$HOME/Projects"}]}Repositories configurationIt’s a file that lists all registered projects and keeps their metadata.It is automatically updated wheningit registeris used.Example:{"description":"ingit repositories configuration file","ingit-version":"0.4.0","repos":[{"name":"ingit","remotes":{"github":"git@github.com:mbdevpl/ingit.git"},"tags":["active","git","github","my","python"]},{"name":"pylint","remotes":{"github":"git@github.com:mbdevpl/pylint.git","source":"https://github.com/PyCQA/pylint"},"tags":["external","github","python"]}]}Entry of each repository is a JSON object that can have the following fields:{"name":"name of the project","path":"path doesn't have to be specified, by default it will be 'repos_path/name'","paths":{"machine name 1":"path used only on machine 1","machine name 2":"path used only on machine 2","":"if no machine name is given, the path is used in all other cases"},"remotes":{"remote name 1":"url 1","remote name 2":"url 2"},"tags":["tags are completely optional","but repositories are much easier to manage if they are consistently tagged"]}Therepos_pathmentioned above is taken from the runtime configuration of ingit.At most one ofpathorpathsis allowed for each repo.The two path specifications below are equivalent:{"name":"name of the project","path":"some path"}{"name":"name of the project","paths":{"":"some path"}}Command detailsBelow, details of each command are described.ingit summaryShow summary of registered repositories and status of configured repository root.First of all, print a list of registered repositories. By default, all
registered repositories are listed, but, as in case of most commands, the
results can be filtered via a predicate or regex.Independently, print a list of all unregistered repositories and all not
versioned paths present in the configured repositories root.ingit registerStart tracking a repository in ingit.ingitregister[PATH][--tagsTAG...]The initial configuration is set according to basic repository information:
its root directory name becomes “name” and its currently configured remotes
become “remotes”. You can edit the configuration manually afterwards.The final “path” to the repository stored in the configuration depends on therepos_pathin runtime configuration. The configured “path” will be:resolved absolute path if there is norepos_pathconfigured or
repository path is outside of therepos_path;resolved relative path to therepos_path, if the repository path is
within it;nothing (i.e. not stored) if the if the repository is stored directly inrepos_path(i.e. there are no intermediate directories).Behaviour of storing relative/no paths in some cases is implemented to make
configuration file much less verbose in typical usage scenarios. To prevent
this behaviour, and force all repository paths to be absolute, simply set therepos_pathin your runtime configuration to JSONnull.UsePATHto provide the path to root directory of repository.
If not provided, current working directory is used.Use--tagsto provide tags for this repository, they will be added to the
initial configuration. Tags have no other effect than making repository
filtering easier.ingit foreachThe given command is executed in a shell in working directory of each
project.Use--timeoutto set timeout of the command (in seconds).ingit cloneExecutegit clone<remote-url>--recursive--origin<remote-name><path>,
where values of<path>and<remote-...>are taken from default remote
configuration of the repository.After cloning, add all remaining configured remotes to the repository and
fetch them.For example, if repository configuration is as follows:{"name":"Spack","path":"~/Software/Spack","remotes":{"source":"https://github.com/spack/spack.git","github":"git@github.com:mbdevpl/spack.git"},"tags":[]}The clone command will be:git clonehttps://github.com/spack/spack.git--recursive--originsource ~/Software/Spackbecausesourceis the first configured remote.
The subsequent commands will begit remote add github git@github.com:mbdevpl/spack.gitandgit fetch github.ingit initExecutegit initfollowed bygit remote addfor each configured
remote.ingit fetchExecutegit fetch<remote-name>, where the remote name is the remote of
the current tracking branch, or all remotes of the repository if there’s no
tracking branch, or repository is in detached head state.Use--allto fetch all remotes in all cases.ingit checkoutInteractively select revision to checkout from list of local branches, remote
non-tracking branches and local tags.The list of branches to select from is composed by combining:local branchesnon-tracking branches on all remoteslocal tagsChecking out a remote branch will create a local branch with the same unless
it already exists. If it already exists, repository will end up in detached
head state.Also, checking out any tag will put repository in a detached head state.ingit mergeNot yet implemented!The following functionality is intended.Interactively merge all branches to their tracking branches. For each not
merged<branch>-<tracking-branch>pair, executegit checkout <branch>and then if the merge is fast-forward,
automatically executegit merge<tracking-branch>--ff-only. If not, then
show more information about the situation of the repository, and propose:git merge--log<tracking-branch>,git rebase-i<tracking-branch>andgit reset--hard<tracking-branch>.If repository is dirty when this command is executed, do nothing. After work
is done, return to the originally checked-out branch.ingit pushExecutegit push<remote-name><branch>:<tracking-branch-name>for the
active branch.The above functionality works, but the following functionality isnot yet implemented.Use--allto execute the push for every branch that has a remote tracking
branch.ingit gcExecutegit gc--aggressive--prune.ingit statusPerform git status, as well as other diagnostic git commands.Execute:git status--short--branchto inform about any uncommitted changes,git logtracking_branch..branchto inform about commits that are not
yet pushed to the remote,git logbranch..tracking_branchto inform about commits that are not
yet merged from the remote.Additionally, compare registered remotes with actual remotes to make sure
that ingit configuration is in sync with the repository metadata.Use--ignoredto include ignored files in the status report, just as withgit status.RequirementsPython version 3.8 or later.Python libraries as specified inrequirements.txt.Building and running tests additionally requires packages listed inrequirements_test.txt.Tested on Linux, macOS and Windows.