VERSION

This is v2.1.0 of git multi … hooray!

SYNOPSIS

There are some options for git multi itself, in which case it is invoked as follows:

git multi --<option> [<option_arguments>]

To execute the same git command in multiple repositories, the invocation is as follows:

git multi <git_command> [<git_command_arguments>]

Both ways of running git multi take an optional, so-called "multi repo" argument to limit the operation to the list of repositories in the referenced "multi repo", ie. a single GitHub user or a single GitHub organization:

git multi ++<multi_repo> --<option> [<option_arguments>]

and…

git multi ++<multi_repo> <git_command> [<git_command_arguments>]

DESCRIPTION

Convenient way to execute the same git command in a set of related repositories, which could be all GitHub repos for a given user, or all repos for a given GitHub organization.

Multipe users and organizations can be configured, and by default git multi operates on all repositories for all users and all orgs; to limit the operation to a single user or a single org, the optional ++<multi_repo> argument can be used.

The list of repos for a user or an org is determined via a GitHub API v3 call and cached locally (in binary format) for performance and offline usage.

OPTIONS

--version

print out this script’s version number

--help

you’re looking at it: show the man page

--html

open the HTML version of the man page

--report

report on various repository stats and metrics

--count

print out the count of repos (per type)

--refresh

refresh the list of user & organization repos

--json

output repository details to JSON

--list

print out the names of all repos

--archived

print out the names of all repos

--forked

print out the names of all repos

--private

print out the names of all repos

--paths

print out the full path for each repos

--missing

print out names of repos that haven’t been cloned

--clone

clones missing repositories into ${HOME}/Workarea (by default)

--stale

list repos that have been deleted on github.com

--excess

list repos that don’t exist on github.com

--spurious

list cloned repos whose remote doesn’t match a github.com origin

--query (args)

query GitHub repo metadata for each repository

--find <ruby>

print out the repos for which the Ruby code evaluates to true

--eval <ruby>

execute the given Ruby code in the context of each repo

--raw <cmd>

execute the given shell command inside each git repository

EXAMPLES

count the number of repos

git multi --list | wc -l

disk usage of each locally cloned repo

git multi --paths | xargs -n 1 du -hs

disk usage using the --raw option

git multi --raw 'du -hs .'

group and count the repos by GitHub-determined language

git multi --query language | cut -f 2 -d : | sort | uniq -c | sort -n -r

find out the most-used Ruby versions

git multi --raw '[ -f .ruby-version ] && cat .ruby-version' | cut -f 2 -d : | sort | uniq -c | sort -n -r

find GitHub repos without a description

git multi --query description | egrep ': *$'

fetch remote branches for all repos

git multi fetch -p

print out the local branch for each repo (using symbolic-ref)

git multi symbolic-ref --quiet --short HEAD

print out the local branch for each repo (using rev-parse)

git multi rev-parse --abbrev-ref=strict HEAD

find all repos for which the origin remote isn’t github.com

git multi config --get remote.origin.url | fgrep -v git@github.com:

a kind of "repository creation" report: count the number of repos created in each quarter

git multi --eval "class ::Time; def quarter() (month.to_f / 3.0).ceil; end; end; puts format('%d-Q%d', created_at.year, created_at.quarter)" | sort | uniq -c

for each repo, list all remote branches, sorted by the "age" of the last commit on each branch

git multi for-each-ref --sort="-authordate" --format="%(refname)%09%(authordate:relative)%09%(authorname)" refs/remotes/origin

same as above, but columnize the generated output (NOTE: replace ^I with CTRL-V/CTRL-I in your terminal)

git multi for-each-ref --sort="-authordate" --format="%(refname)%09%(authordate:relative)%09%(authorname)" refs/remotes/origin | column -t -s "^I"

same as above, but refresh the list of remote branches first

git multi fetch -p ; git multi for-each-ref --sort="-authordate" --format="%(refname)%09%(authordate:relative)%09%(authorname)" refs/remotes/origin

find all Rails projects

git multi --raw '[ -f Gemfile ] && fgrep -q -l rails Gemfile && echo uses Rails' | cat

find all Mongoid dependencies

git multi --raw '[ -f Gemfile.lock ] && egrep -i "^    mongoid (.*)" Gemfile.lock' | column -s: -t

find all projects that have been pushed to in the last week

git multi --find '((Time.now.utc - pushed_at) / 60 / 60 / 24) <= 7'

print out the number of days since the last push to each repository

git multi --eval 'puts "%s - %d days" % [full_name, ((Time.now.utc - pushed_at) / 60 / 60 / 24).ceil]'

find all projects that have seen activity this calendar year

git multi --find 'pushed_at >= Date.civil(Date.today.year, 1, 1).to_time.utc'

print out all webhooks

git multi --eval '(hooks = client.hooks(full_name)).any? && begin print full_name ; print "\t" ; puts hooks.map { |hook| ["", hook.name, hook.config.url].join("\t") } ; end'

print out all deploy keys

git multi --eval '(keys = client.list_deploy_keys(full_name)).any? && begin print full_name ; print "\t" ; puts keys.map(&:title).sort.join("\t") ; end'

find all organization repositories that depend on a given org repo, e.g. business_rules

git multi --graph | fgrep business_rules

generate a dependency graph of all organization repositories using yuml.me

DEPENDENCIES=$( git multi --graph | ruby -n -e 'parent, children = $_.split(": ") ; puts children.split(" ").map { |child| "[#{parent}]->[#{child}]" }' | tr '\n' ',' ) ; open "http://yuml.me/diagram/scruffy/class/${DEPENDENCIES}"

generate a dependency graph of all organization repositories using Graphviz

git multi --graph | ruby -n -e 'parent, children = $_.split(": ") ; puts children.split(" ").map { |child| "\"#{parent}\"->\"#{child}\";" }' | awk 'BEGIN { print "digraph {\nrankdir=\"LR\";\n" } ; { print ; } END { print "}\n" } ; ' | dot -Tpng > /tmp/ghor.png ; open -a Preview /tmp/ghor.png

QUERY ARGUMENTS

The following is a list of valid arguments for the git multi --query option:

archive_url          archived             assignees_url
blobs_url            branches_url         clone_url
collaborators_url    comments_url         commits_url
compare_url          contents_url         contributors_url
created_at           default_branch       deployments_url
description          downloads_url        events_url
fork                 forks                forks_count
forks_url            full_name            git_commits_url
git_refs_url         git_tags_url         git_url
has_downloads        has_issues           has_pages
has_projects         has_wiki             homepage
hooks_url            html_url             id
issue_comment_url    issue_events_url     issues_url
keys_url             labels_url           language
languages_url        license              merges_url
milestones_url       mirror_url           name
network_count        node_id              notifications_url
open_issues          open_issues_count    organization
owner                permissions          private
pulls_url            pushed_at            releases_url
size                 ssh_url              stargazers_count
stargazers_url       statuses_url         subscribers_count
subscribers_url      subscription_url     svn_url
tags_url             teams_url            trees_url
updated_at           url                  watchers
watchers_count

JQ INTEGRATION

jq is like sed for JSON data… all of the above query arguments can be used in conjunction with jq to query, filter, map and transform the GitHub repository attributes stored in the local, binary repository cache; here are some examples:

# print out each repository's name and its description
git multi --json | jq -r '.[] | .name + ": " + .description'
# print out the name of all "forked" repositories
git multi --json | jq -r '.[] | select(.fork == true) | .full_name'

FILES

${HOME}/Workarea

root directory where repos will been cloned

${HOME}/.git/multi/repositories.byte

local, binary cache of GitHub repository metadata

${HOME}/.git/multi/superprojects.config

definitions for so-called "superproject" multi repos

REFERENCES