|
| 1 | +# Monorepo Grafting |
| 2 | + |
| 3 | +This directory is intended to be the initial point of migration for |
| 4 | +other git repos being added to this repo. Such 'grafts' do not have to |
| 5 | +initially adhere to repo standards but will be expected to be |
| 6 | +refactored where necessary to meet such standards as part of a |
| 7 | +PR-based process of migrating to more permanent locations. |
| 8 | + |
| 9 | +## Migrating a Repo |
| 10 | + |
| 11 | +### Stacked Branches |
| 12 | + |
| 13 | +As with with any changes to a codebase, minimizing review friction is |
| 14 | +essential. While it would be possible to require review of a huge PR |
| 15 | +commit-by-commit, any changes to those commits would need to be |
| 16 | +correlated with their originals and the friction would be |
| 17 | +considerable. Instead, a [stacked |
| 18 | +branch](https://andrewlock.net/working-with-stacked-branches-in-git-part-1/) |
| 19 | +approach is suggested to enable effective review of a large migration |
| 20 | +in a piecemeal fashion: |
| 21 | + |
| 22 | + - Create a branch per reviewable task |
| 23 | + - Subtree merge would be one task, import rewrite another, etc |
| 24 | + - The branch for a task subsequent to the initial task would be |
| 25 | + based on the previous task branch |
| 26 | + - Create a PR per branch |
| 27 | + - The initial task would use the master branch as its base |
| 28 | + - A subsequent task would use the previous task's branch as its base |
| 29 | + - Mark each PR as draft to avoid premature merge |
| 30 | + - Request review in order from the initial PR but do not merge yet |
| 31 | + - Once all PRs in the series have been approved, merge from the top down |
| 32 | + - Avoids cascading rebases and merge conflicts |
| 33 | + |
| 34 | +Tooling such as |
| 35 | +[git-machete](https://github.com/VirtusLab/git-machete) or |
| 36 | +[jujutsu](https://github.com/jj-vcs/jj) is suggested to simplify |
| 37 | +maintaining the series of stacked branches. |
| 38 | + |
| 39 | +### Suggested Procedure |
| 40 | + |
| 41 | +The following do not represent an exhaustive list of tasks and are |
| 42 | +used for example purposes only. Regardless of the steps involved, the |
| 43 | +creation of an initial branch from master is assumed before the first |
| 44 | +step, and the commit of all changes and creation of a new branch from |
| 45 | +the current branch before beginning a subsequent step. |
| 46 | + |
| 47 | + - [ ] Add tasks for subtree merge and import rewrite to graft/Taskfile.yml (as per the example of existing tasks) |
| 48 | + - These tasks are intended to simplify the repeated invocation that |
| 49 | + will be required when a repo is being developed in parallel with |
| 50 | + migration. |
| 51 | + - [ ] Execute the subtree merge task (it will commit the result automatically) |
| 52 | + - [ ] Remove files made redundant by the migration |
| 53 | + - Prioritizing file removal before modification minimizes the changes requiring review |
| 54 | + - [ ] Execute the rewrite imports task (it will commit the result automatically) |
| 55 | + - [ ] Perform required go module changes |
| 56 | + - [ ] Migrate CI jobs (unit test, e2e, linting, etc) |
| 57 | + - [ ] Get CI jobs passing |
| 58 | + |
| 59 | +### Rebasing Inflight PRs |
| 60 | + |
| 61 | +Provided a subtree merge was used to perform the graft, a common merge |
| 62 | +base will exist with which to rebase PRs targeted at the original git |
| 63 | +repo. This allows for repo migration and ongoing development to |
| 64 | +proceed in parallel. Once a graft has been finalized, outstanding PR |
| 65 | +branches from the original repo can be migrated as follows: |
| 66 | + |
| 67 | +```bash |
| 68 | +# Fetch the PR branch from the standalone repo's remote |
| 69 | +git fetch REMOTE PR_BRANCH_NAME |
| 70 | + |
| 71 | +# Create a local branch from the PR branch. |
| 72 | +# Don't track since the new branch is intended to target the new repo. |
| 73 | +git checkout -b PR_BRANCH_NAME REMOTE/PR_BRANCH_NAME --no-track |
| 74 | + |
| 75 | +# Rebase onto the target branch in this repo, treating graft/REPO as the subtree root. |
| 76 | +# Conflict resolution may be required. |
| 77 | +git rebase -Xsubtree=graft/REPO --onto origin/master REMOTE/master |
| 78 | + |
| 79 | +# Push the new PR branch |
| 80 | +git push -u origin PR_BRANCH_NAME |
| 81 | +``` |
0 commit comments