VERSION
This is v4.0.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
- --shell
-
run an interactive login shell inside each git directory
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 'puts client.hooks(full_name).map { |hook| [full_name, hook.name, hook.config.url].join("\t") }'
delete all webhooks with matching URLs (in this case: notify.travis-ci.org
)
git multi --eval 'client.hooks(full_name).find_all { |hook| hook.config.url =~ /notify.travis-ci.org/ }.each { |hook| client.remove_hook(full_name, hook.id) }'
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 disabled 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
temp_clone_token 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
-
homepage for
git-multi
: https://github.com/pvdb/git-multi -
the GitHub API: https://developer.github.com/v3/
-
the
jq
command-line utility: http://stedolan.github.io/jq/