Skip to content

Instantly share code, notes, and snippets.

@detunized
Last active June 27, 2025 09:18
Show Gist options
  • Save detunized/7c41718863ab94e7072f99a55a5bf9d4 to your computer and use it in GitHub Desktop.
Save detunized/7c41718863ab94e7072f99a55a5bf9d4 to your computer and use it in GitHub Desktop.
Join repos into subfolders with flat history
#!/bin/bash
set -euo pipefail
$REPO_DIR=~/devel
repos="1password bitwarden dashlane lastpass opvault passwordbox roboform stickypassword truekey zoho-vault"
# pull all repos
(
for repo in $repos; do
echo $repo
cd $REPO_DIR/$repo
git pull -v --ff
done
)
# merge
(
rm -rf joined
mkdir joined
cd joined
git init .
for repo in $repos; do
git remote add $repo ~/devel/$repo-sharp
git fetch $repo
git checkout -b $repo $repo/master
echo -n "$repo: " > prefix
git filter-branch \
-f \
--tree-filter "mkdir -p .original/$repo && rsync -a --remove-source-files ./ .original/$repo/" \
--msg-filter "cat $(pwd)/prefix -" \
--env-filter 'GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE"' \
$repo
rm prefix
done
# create master
git checkout --orphan master
git rm -rf .
# cherry pick into the master
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
done
# cleanup
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
)
@Schoaf
Copy link

Schoaf commented Apr 23, 2021

Why did you change line 25. I wanted to correct it but then I saw that you purposely changed that line. It just cannot work this way.

@mindplay-dk
Copy link

I suck at git and bash, but I couldn't get this to work.

I had Gemini write a new script:

https://gist.github.com/mindplay-dk/55f8a8f81049b2fd7f44dff3623659b2

This basically works - the only issue is I end up with giant, monolithic merge commit with a comment like feat: Merge repository 'backend', which is very much unwanted.

I don't know what your script does, because I couldn't get it to work.

Anyway, this sort of, mostly works, and I guess I could live with the result - but the resulting git history is definitely not optimal.

Ideally, I'd want a history that really looks like all of those commits were always made in a single repo with two (or more) subfolders.

I don't know if that's possible...

I can't believe there isn't a finished tool/script that does this, but I've looked seriously everywhere - there are tons of tools that can probably do this and a gazillion other things if you know how, but I am not at that level of git or bash knowledge...

Maybe someone else will see this and try to figure it out... 😌

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