Skip to content

Instantly share code, notes, and snippets.

@mwhite
Created November 7, 2012 17:24
Show Gist options
  • Save mwhite/4033061 to your computer and use it in GitHub Desktop.
Save mwhite/4033061 to your computer and use it in GitHub Desktop.
#!/bin/bash
# git subtree merge one repo into another, copying all branches in the source
# repo to the destination repo, with the source repo's name added as a prefix
# to the branch name in the destination repo
# with handling of weird edge cases in subtree merge
# See http://git-scm.com/book/ch6-7.html for an overview of git subtree merge
PARENT_NAME=commcare-hq
CHILD_NAME=core-hq
PARENT_REPO=git@github.com:dimagi/commcare-hq.git
CHILD_REPO=git@github.com:dimagi/core-hq.git
SUBMODULE_DIR=submodules
SUBMODULE=core-hq-src
CHILD_PATH=$SUBMODULE_DIR/$SUBMODULE
PARENT_TARGET_REPO=git@github.com:mwhite/commcare-hq-merge-testing.git
CHILD_TEMP_REPO=git@github.com:mwhite/core-hq-merge-testing.git
ALREADY_FILTERED=true
if [[ ! $CHILD_TEMP_REPO ]]; then
exit 1
fi
# see http://stackoverflow.com/a/4042965/373514
if [[ $ALREADY_FILTERED != 'true' ]]; then
rm -rf $CHILD_NAME
git clone $CHILD_REPO $CHILD_NAME
cd $CHILD_NAME
git fetch
# make sure we do it to all the branches
child_branches=$(git branch -r | grep -v -e "\->" -e "master" | grep origin | cut -d/ -f 2)
for branch in $child_branches; do
git checkout -b $branch origin/$branch
done
git filter-branch --tree-filter "
mkdir -p $CHILD_PATH
git ls-tree --name-only \$GIT_COMMIT | xargs -I files mv files $CHILD_PATH" -- --all
git remote rm origin
git remote add origin $CHILD_TEMP_REPO
git push -f --all --dry-run
cd ..
fi
cd $CHILD_NAME
child_branches=$(git branch -r --no-merged | grep -v "\->" | grep origin | cut -d/ -f 2)
cd ..
rm -rf $PARENT_NAME
git clone $PARENT_REPO $PARENT_NAME
cd $PARENT_NAME
parent_branches=$(git branch -r --no-merged | grep -v "\->" | grep origin | cut -d/ -f 2)
for branch in $parent_branches; do
git checkout -b $branch origin/$branch
done
git remote add -f $CHILD_NAME $CHILD_TEMP_REPO
for branch in $child_branches; do
git checkout -b $CHILD_NAME-$branch HEAD
# See http://stackoverflow.com/a/11400433/373514
git config -f .gitmodules --remove-section submodule.$CHILD_PATH
git config -f .git/config --remove-section submodule.$CHILD_PATH
git rm --cached -r $CHILD_PATH
git add .gitmodules
git commit -m "remove $CHILD_NAME submodule in preparation for subtree merge"
rm -rf $CHILD_PATH
rm -rf .git/modules/$CHILD_PATH
# See http://stackoverflow.com/a/6442034/373514
git read-tree -m --aggressive -u $CHILD_NAME/$branch
#git mv TEMP/$SUBMODULE_DIR/$SUBMODULE $SUBMODULE_DIR/
git commit -m "subtree merge $branch from $CHILD_NAME into $CHILD_PATH (branch $CHILD_NAME-$branch)"
done
git remote rm $CHILD_NAME
# merge core-hq-master into master, leave the rest alone
git checkout master
git merge core-hq-master
if [[ $PARENT_TARGET_REPO ]]; then
git remote rm origin
git remote add origin $PARENT_TARGET_REPO
git push --dry-run -f --all
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment