Last active
January 26, 2023 16:20
-
-
Save gilday/c92354c9f9154e3ba7350137b95c3082 to your computer and use it in GitHub Desktop.
utility script for merging repos into a monorepo while preserving history
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# merge-repos.py | |
# utility script for merging repos into a monorepo while preserving history | |
import argparse | |
from contextlib import contextmanager | |
import os | |
import shutil | |
import subprocess | |
import sys | |
import tempfile | |
def main(): | |
""" main function """ | |
parser = argparse.ArgumentParser( | |
description="merge repos into a monorepo preseving history") | |
parser.add_argument( | |
"repository", | |
type=str, | |
help="repo address to merge e.g. git@bitbucket.org:org/dependency-one.git") | |
parser.add_argument( | |
"directory", | |
type=str, | |
help="directory in which to merge the repository e.g. " | |
"dependency-one") | |
parser.add_argument( | |
"--branch", | |
type=str, | |
help="branch to merge", | |
default="develop") | |
parser.add_argument( | |
"--dry-run", | |
dest="dryRun", | |
help="skip the git steps in this repo", | |
action="store_true") | |
args = parser.parse_args() | |
print(args.repository) | |
print(args.directory) | |
with tempdir() as path: | |
subprocess.call(["git", "clone", args.repository, path]) | |
subprocess.call(["git", "checkout", args.branch], cwd=path) | |
newdir = os.path.join(path, args.directory) | |
files = [(os.path.join(path, x), os.path.join(newdir, x)) | |
for x in os.listdir(path) if x != '.git'] | |
os.makedirs(newdir) | |
for src, dest in files: | |
print("moving {} to {}".format(src, dest)) | |
os.rename(src, dest) | |
subprocess.call(["git", "add", "-A"], cwd=path) | |
subprocess.call( | |
[ | |
"git", | |
"commit", | |
"-m", | |
":truck: Merging repositories - moving files to {}".format( | |
args.directory)], | |
cwd=path) | |
if not args.dryRun: | |
remote = "merge-{}".format(args.directory) | |
subprocess.call(["git", "remote", "add", remote, path]) | |
subprocess.call(["git", | |
"pull", | |
remote, | |
args.branch, | |
"--no-edit", | |
"--allow-unrelated-histories"]) | |
subprocess.call(["git", "remote", "rm", remote]) | |
else: | |
print("dry-run: skipping git commands") | |
@contextmanager | |
def tempdir(): | |
""" creates a temporary directory that is automatically collected when finished with the | |
context """ | |
path = tempfile.mkdtemp() | |
try: | |
yield path | |
finally: | |
try: | |
shutil.rmtree(path) | |
except IOError: | |
print( | |
'Failed to clean up temp dir {}'.format(path), | |
file=sys.stderr) | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment