Skip to content

Instantly share code, notes, and snippets.

@rahul286
Forked from icholy/merge_repos.sh
Last active April 25, 2022 07:47
Show Gist options
  • Save rahul286/494f0fac6c553cffb5d2df7f4e9da5ef to your computer and use it in GitHub Desktop.
Save rahul286/494f0fac6c553cffb5d2df7f4e9da5ef to your computer and use it in GitHub Desktop.
#!/bin/bash
# This script takes a remote repository and merges it into
# the current one as a subdirectory
set -e
if [ -z "$1" ]
then
echo "Usage:"
echo " ./merge_repos.sh <repository> [name]"
echo " <repository> remote repository to merge"
echo " [name] sub-directory name (optional)"
exit
fi
REPO_REMOTE="$1"
REPO_NAME="$2"
# infer a name if one is not provided
if [ -z "$REPO_NAME" ]
then
REPO_NAME="${REPO_REMOTE##*/}"
# REPO_NAME="${REPO_NAME%.*}"
fi
#REPO_DIR_TMP="$(mktemp -d -t "${REPO_NAME}.XXXX")"
REPO_DIR_TMP="$(mktemp -d)"
echo "REPO REMOTE: $REPO_REMOTE"
echo "REPO NAME: $REPO_NAME"
echo "REPO TMP DIR: $REPO_DIR_TMP"
echo
# read -p "Press <Enter> to continue"
# clone other repo
git clone "$REPO_REMOTE" "$REPO_DIR_TMP"
# rewrite the entire history into sub-directory
export REPO_NAME
(
cd $REPO_DIR_TMP &&
git filter-branch -f --prune-empty --tree-filter '
mkdir -p "${REPO_NAME}_tmp"
git ls-tree --name-only $GIT_COMMIT | xargs -I{} mv {} "${REPO_NAME}_tmp"
mv "${REPO_NAME}_tmp" "$REPO_NAME"
'
)
# merge the rewritten repo
git remote add "$REPO_NAME" "$REPO_DIR_TMP"
git fetch "$REPO_NAME"
# if you're running an older version of git, remove --allow-unrelated-histories
git merge --allow-unrelated-histories "$REPO_NAME/master" -m "Merging $REPO_REMOTE into $REPO_NAME"
# delete the rewritten repo
rm -rf "$REPO_DIR_TMP"
git remote rm "$REPO_NAME"
@thelovekesh
Copy link

Node script to execute this bash script.

const {execSync} = require('child_process');

let gitReposToMergeInOne = [
    'https://github.com/project/proj-1',
    'https://github.com/project/proj-2',
    // ...more similar repo URLs
]

/**
 * Merge all the repos in one
 * 
 * @param {Array} repos
 * @param {String} branch
 */
const mergeRepos = (repos, branch) => {
    for (let repo of repos) {
        const repoName = repo.split('/').pop()
        execSync(
            `sh merge_repos.sh ${repo} ${repoName} ${branch}`,
            (error) => {
                if (error) {
                    console.error(`exec error: ${error}`);
                    return;
                }
            }
        )
        console.log(`Merging ${repo}`)
    };
}

mergeRepos([...new Set(gitReposToMergeInOne)], 'main')

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment