Last active
June 27, 2025 09:18
-
-
Save detunized/7c41718863ab94e7072f99a55a5bf9d4 to your computer and use it in GitHub Desktop.
Join repos into subfolders with flat history
This file contains hidden or 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
#!/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 | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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... 😌