Skip to content

Instantly share code, notes, and snippets.

@ziazon
Created March 24, 2022 14:48
Show Gist options
  • Save ziazon/8ef594063663afe53b981ae9a22685c6 to your computer and use it in GitHub Desktop.
Save ziazon/8ef594063663afe53b981ae9a22685c6 to your computer and use it in GitHub Desktop.
Merge multiple repos into single monorepo maintaining git history
#!/bin/bash
set -euo pipefail
NEW_REPO_DIR=${NEW_REPO_DIR:-'new-repo'}
BASE_CODE_DIR=${BASE_CODE_DIR:-'apps'}
# expected starting structue:
# merge.sh
# repo1
# repo2
# repo3
BASE_DIR=$(pwd)
repos="repo1 repo2 repo3"
rm -rf $NEW_REPO_DIR
mkdir $NEW_REPO_DIR
cd $NEW_REPO_DIR
git init .
# add all service repos
for repo in $repos; do
git remote add $repo ../$repo
git fetch $repo
git checkout -b $repo $repo/main
git filter-branch \
-f \
--tree-filter "mkdir -p $BASE_CODE_DIR/$repo && rsync -a --remove-source-files ./ $BASE_CODE_DIR/$repo/" \
--msg-filter "cat | tr '\n' ' ' | awk '{print \"$repo: \" \$0}'" \
--env-filter 'GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE"' \
$repo
git tag -d $(git tag -l)
done
# create main
git checkout --orphan main
git rm -rf .
# cherry pick into the main
for i in $(git log --pretty='%H' --author-date-order --reverse $repos); do
GIT_COMMITTER_DATE=$(git log -1 --pretty='%at' $i) \
git cherry-pick $i || git commit --allow-empty
done
for repo in $repos; do
git branch -D $repo
git remote remove $repo
git update-ref -d refs/original/refs/heads/$repo
done
git gc --aggressive
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment