Hacker News new | ask | show | jobs
by vkoskiv 961 days ago
I too just discovered these a few days ago! I've been trying to work out a satisfactory way to combine multiple repositories into a monorepo at work. Since I'm building a new repo, I'm free to rewrite history, so I've used `git-filter-branch` to modify the sub-repositories into a form suitable for merging (moved all files to subdirectories, matching the final monorepo structure). Merging them with `--allow-unrelated-histories` is... Okay. No conflicts, the linear git log looks good, and I also prepended the module name to commit messages before merging, so it reads well. But the graph is super ugly (Merges with many years of commits in between, because I just merged the repos in one by one). What I'd really like to do is to "zip" all the histories together into a single, linear history, with all the commits in chronological order. Thus far I haven't found a way to do this with git. I'm probably missing some obvious reason why that couldn't work, but I haven't come up with any.
2 comments

Funny, I did just exactly that at work yesterday. If your branches have linear histories, here's what to do:

1. Make sure all branches touch separate files. I would strongly recommend git-filter-repo over git-filter-branch. It's way simpler to use and orders of magnitudes faster.

2. Generate the list of commits in the correct order:

git rev-list --date-order --reverse branchA BranchB BranchC > revisions.txt

3. Go to any branch and: git rebase -i --root --force-rebase

Paste the contents of revisions.txt into the sequence editor and add "p " at the bigging of every line. Run the rebase and you are done.

I figured out a way to not have to paste in manually to the sequence editor. I wrote a script like this:

-----

#!/bin/bash

if [[ ! -f "$1" ]]; then

exit 1

fi

git rev-list --no-merges --date-order --reverse $(git branch -a | grep -v '*' | grep master) | awk '{print "p " $0}' > $1

exit 0

-----

Then I can just:

-----

pushd monorepo

GIT_SEQUENCE_EDITOR=../inject_reflist.sh git rebase -i --root --force-rebase

popd

-----

And off we go! Apparently there were a few branches + merges, and we have some ongoing feature branches, so I need to find a way to bring in branches other than master as well, preferably while conserving the merges as-is, instead of skipping them like I do above.

Thank you! This looks like exactly what I want. I actually am already using `git-filter-repo` - I just confused the two names in my comment there. Super useful tool!
Have you seen reposurgeon? It’s not something I’ve personally used, but it might be able to help you out!

http://www.catb.org/esr/reposurgeon/