Skip to content

Instantly share code, notes, and snippets.

@edudobay
Last active May 7, 2019 17:19
Show Gist options
  • Save edudobay/6b70f48a4fe46d68454a1ed674fe678a to your computer and use it in GitHub Desktop.
Save edudobay/6b70f48a4fe46d68454a1ed674fe678a to your computer and use it in GitHub Desktop.
Script to sync (fetch) all git repos within a directory
#!/usr/bin/env python3
from argparse import ArgumentParser, Namespace
import os
import subprocess
def is_git_repo(entry):
from os.path import join, isdir
return isdir(entry) and isdir(join(entry, '.git'))
class ProcessUncleanExit(Exception): pass
def parse():
parser = ArgumentParser()
parser.add_argument(
'--depth', '-d', type=int, default=0, metavar='N',
help='scan recursively into up to N subdirectory levels [default: 0]'
)
parser.add_argument(
'--null', '-0', action='store_true', dest='null_separator',
help='separate entries by NUL (\\0) instead of newline'
)
args = parser.parse_args()
return args
def candidates_from(root, max_depth=0):
from os.path import realpath, join, isdir
for d in os.listdir(root):
d = realpath(join(root, d))
if is_git_repo(d):
yield d
elif max_depth > 0 and isdir(d):
yield from candidates_from(d, max_depth - 1)
def find_child_repos(root, max_depth):
return sorted(candidates_from(root, max_depth))
def main():
args = parse()
separator = '\0' if args.null_separator else '\n'
dirs = find_child_repos('.', args.depth)
for subdir in dirs:
print(subdir, end=separator)
if __name__ == '__main__':
try:
main()
except KeyboardInterrupt:
pass
# fetch from all repositories
alias gfa="git-allrepos -0 | xargs -0 -n1 -P10 -I\% bash -c '(cd %; git fetch --prune)'"

# fetch and merge only if it would be a fast-forward
alias gma="git-allrepos -0 | xargs -0 -n1 -P10 -I\% bash -c '(cd %; git fetch --prune && git merge --ff-only)'"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment