Created
August 15, 2023 22:48
-
-
Save coisa/d8115aac022c9ed836b6a8db3323dca4 to your computer and use it in GitHub Desktop.
Convert GIT repository monorepo path into a submodule of an external repository
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 | |
| ######################################################################################### | |
| # SCRIPT: Git Monorepo Splitter | |
| # | |
| # DESCRIPTION: | |
| # This script is designed to help teams and individuals transition from a monorepo | |
| # (a single repository containing multiple projects or directories) to a multi-repo setup | |
| # (each project or directory in its own repository). The primary function is to take a | |
| # directory from a monorepo and transform it into its own standalone repository, while | |
| # maintaining its git history. | |
| # | |
| # A common scenario is when a particular project or directory within a monorepo grows | |
| # to a point where it makes sense to manage it separately, or when different teams need | |
| # to focus on different parts of a monorepo without interfering with each other. | |
| # | |
| # ADVANTAGES OF SPLITTING A MONOREPO: | |
| # 1. **Focused Repositories:** Each repository has a clear and specific purpose. | |
| # 2. **Independent Development Cycles:** Projects can evolve, release, and scale at their own pace. | |
| # 3. **Reduced Complexity:** Developers can focus on a specific project without sifting through unrelated code. | |
| # 4. **Enhanced Access Control:** Limit access based on project-specific needs. | |
| # 5. **Optimized CI/CD:** Build and deploy processes can be tailored for each project. | |
| # 6. **Modularity:** Encourages development of modular and decoupled systems. | |
| # | |
| # USAGE: | |
| # ./convert-path-into-submodule.sh <REPOSITORY_URL> <BRANCH_NAME> <SUBMODULE_REPOSITORY_URL> <SUBMODULE_ROOT_DIRECTORY> | |
| # (See the 'Usage' section within the script for argument details.) | |
| # | |
| # NOTE: Ensure Git LFS is installed if you're dealing with large files. | |
| ######################################################################################### | |
| # Check if the necessary number of arguments are passed | |
| if [ "$#" -ne 4 ]; then | |
| echo "Usage: $0 <REPOSITORY_URL> <BRANCH_NAME> <SUBMODULE_REPOSITORY_URL> <SUBMODULE_ROOT_DIRECTORY>" | |
| echo | |
| echo "Arguments:" | |
| echo " REPOSITORY_URL URL of the original repository from which you want to isolate a directory." | |
| echo " BRANCH_NAME Name of the new branch that will be created based on the master (or main) branch." | |
| echo " SUBMODULE_REPOSITORY_URL URL of the new empty repository where the isolated directory will be pushed." | |
| echo " SUBMODULE_ROOT_DIRECTORY Path of the directory in the original repository that you want to isolate as a submodule." | |
| exit 1 | |
| fi | |
| # Assign arguments to variables | |
| REPOSITORY_URL="$1" | |
| BRANCH_BASE="master" # This can be changed to "main" or any other default branch name if needed | |
| BRANCH_NAME="$2" | |
| SUBMODULE_REPOSITORY_URL="$3" | |
| SUBMODULE_ROOT_DIRECTORY="$4" | |
| # Check if Git LFS is installed | |
| if ! command -v git-lfs &> /dev/null | |
| then | |
| echo "Error: git-lfs is not installed. Please install it before running the script." | |
| exit 1 | |
| fi | |
| # Use system temporary directory | |
| TMP_DIR=${TMPDIR:-/tmp} | |
| WORK_DIR="$TMP_DIR/repo_$(date +%Y%m%d%H%M%S)" | |
| mkdir $WORK_DIR | |
| # Clone the original repository to the temporary directory | |
| git lfs clone $REPOSITORY_URL $WORK_DIR | |
| cd $WORK_DIR | |
| # Create a new branch for the submodule | |
| git checkout -b ${BRANCH_NAME}-submodule $BRANCH_BASE | |
| # Isolate directory | |
| git filter-branch --prune-empty --subdirectory-filter $SUBMODULE_ROOT_DIRECTORY ${BRANCH_NAME}-submodule | |
| # Migrate LFS pointers (if required) | |
| git lfs migrate export --everything | |
| # Add new remote repository and push the branch | |
| git remote add new-repo $SUBMODULE_REPOSITORY_URL | |
| git push new-repo ${BRANCH_NAME}-submodule:$BRANCH_NAME | |
| # Reset to the original branch and set up the submodule | |
| git checkout $BRANCH_BASE | |
| git checkout -b $BRANCH_NAME $BRANCH_BASE | |
| git rm -r $SUBMODULE_ROOT_DIRECTORY | |
| git commit -m "Removing $SUBMODULE_ROOT_DIRECTORY to convert into a submodule" | |
| git submodule add $SUBMODULE_REPOSITORY_URL $SUBMODULE_ROOT_DIRECTORY | |
| git commit -m "Adding $SUBMODULE_ROOT_DIRECTORY as a submodule" | |
| git push origin $BRANCH_NAME | |
| # Cleanup | |
| cd .. | |
| rm -rf $WORK_DIR | |
| echo "Process completed!" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment