5

I am moving several related projects into a monorepo, preserving every project's history.

Each of the projects in question had its own repo. Also, each project's development relied heavily on --no-ff merges for reintegration of topic branches into the master branch.

I have experimented with shopsys/monorepo-tools and have succeeded in producing a monorepo with joined histories.

I have also found out that most of the time the topic branches were rather long and contained histories of initial implementation, review fixes, and sometimes master -> topic merges. Naturally, it seems that this info is sort of irrelevant – only changes that made it into master really matter.

So I have been considering rewriting the histories of these projects before merging them all into one repo. I want to achieve rewriting history from this state:

...
|
* Merge branch 'feature/XYZ'
|\
| * feature/XYZ#3 Review fixes part 2
| * feature/XYZ#2 Review fixes
| * feature/XYZ#1 Hack, hack, hack 
|/
* Initial commit

To this state:

...
|
* squashed: feature/XYZ#1 + feature/XYZ#2 + feature/XYZ#3 
|
* Initial commit

I want to repeat this for every merge in history. I think I have to use git filter-branch, but I can't quite wrap my head around its multiple options yet, so I'd be really grateful if someone could nudge me in the right direction.

ivanmoskalev
  • 2,004
  • 1
  • 16
  • 25

1 Answers1

2

I would start by doing a specific branch to do this preserving the original state (just in case :) ) then use git rebase :

# git checkout -b trying_jo_solution
# git rebase -i <Initial comit sha or tag>

will show:

pick 11111 Initial commit
pick 22222 feature/XYZ#1 Hack, hack, hack
pick 33333 feature/XYZ#2 Review fixes
pick 44444 feature/XYZ#3 Review fixes part 2
pick 55555 Merge branch 'feature/XYZ'

change to:

pick 11111 Initial commit
r 22222 feature/XYZ#1 Hack, hack, hack
f 33333 feature/XYZ#2 Review fixes
f 44444 feature/XYZ#3 Review fixes part 2
f 55555 Merge branch 'feature/XYZ'

then you will have the chance to reword the comment (on 22222)

to : squashed: feature/XYZ#1 + feature/XYZ#2 + feature/XYZ#3

done ! check it look like wat you want

then you just have to change branch master position

#git branch -f master
#git push -f origin master
jo_
  • 8,324
  • 1
  • 18
  • 14
  • It works quite well! Thank you! Just a little addition: the merge commit will not participate in the interactive rebase if no `--preserve-merges` option was given. And when merges are preserved, git will refuse to squash it into any other commit. However, it is irrelevant, because I don't need merges, so I can just squash topic branch commits together and apply them to the master branch. – ivanmoskalev Aug 08 '18 at 08:49
  • The only 2 problems with rebase is that (1) there is a lot of manual work and (2) I have to resolve merge conflicts again. But since the team has worked with pull requests, and merge-time resolutions were virtually non-existent, the second problem is not so acute for me (but it may be a showstopper for other people in other scenarios). – ivanmoskalev Aug 08 '18 at 08:52