Skip to content

Instantly share code, notes, and snippets.

@OleksiyRudenko
Last active October 29, 2018 07:42
Show Gist options
  • Save OleksiyRudenko/3324acdab15fff52955979522c878a3e to your computer and use it in GitHub Desktop.
Save OleksiyRudenko/3324acdab15fff52955979522c878a3e to your computer and use it in GitHub Desktop.
Git: merging, rebasing

Merging a repo into another one

Initial situation:

  1. Repository A we want to become a part of another repository.
  2. Repository B we want repo A to be merged into.

Targets:

  1. We want source code from repo A to be located under a sub-directory in repo B and repo A history stored in a dedicated repo B branch.
  2. We do not want original repo A be changed or corrupted.

Inspirations:

  1. http://gbayer.com/development/moving-files-from-one-git-repository-to-another-preserving-history/
  2. https://stackoverflow.com/questions/10603671/how-to-add-a-local-repo-and-treat-it-as-a-remote-repo
  3. https://stackoverflow.com/questions/18667308/move-file-and-directory-into-a-sub-directory-along-with-commit-history

Solution:

  1. Clone repo A into A' and unbind it from original source to avoid corruption thereof.
  2. Restructure repo A' so it looks like it is already a part of repo B.
  3. Clone repo B into B'.
  4. Pull branch from repo A' into repo B'.
  5. Check if B' looks as it is expected to be and push it if OK.
  6. Remove temporary repos.

NB #1. Repo A' won't be pushed anywhere.

NB #2. Repo B should not contain a directory where codebase from A' will be placed, as it may result in merger conflicts.

Step 1 - Cloning repo A into A'

cd <sandboxDirectory>
# <repo A .git> can be a path to the local repo e.g. D:/myrepos/repoA/.git (under Windows make note of slashes!)
git clone <repo A .git> <repo A name>--tmp
cd <repo A' directory>
git remote rm origin

Step 2 - Restructuring repo A'

# Create a branch with a name as it will be in repo B
git checkout -b <target branch name>
# Remove files and directories that are not under version control if any. Check against '.gitignore'
rm node_modules <and/or other files/directories as appropriate>
# Patch history like your codebase has always been under target directory
git filter-branch --subdirectory-filter <target subdirectory name> -- --all 
mkdir <target subdirectory name>
mv * <target subdirectory name>
git add .
git commit -m 'Move codebase to <target subdirectory name>'

Optional : squashing commits:

# reset to commit to be sqush root;
git reset --soft <hash>
# commit squashed
git commit -m "App version ..."

Step 3 - Cloning repo B into B'

cd <sandboxDirectory>
git clone <repo B .git> <repo B name>--tmp
cd <repo B' directory>

Step 4 - Merging repo A' into repo B'

# Under Windows make sure using regular slashes in pathnames!
git remote add import <repository A' .git directory>
git checkout -b <target branch name>
# Pull branch from repo A'
git fetch import <target branch name as remote source branch name>
git merge import/<target branch name> --allow-unrelated-histories -m 'Import branch <target branch name> from repo A'
git remote rm import

Step 5 - Checking things are OK

# Check your repo B' if it is OK then proceed.
git push -u origin <target branch name>

NB! If you cloned repo B' from local repo (B) then B' will push back to your local repo B. You may need then to set branch tracking in repo B appropriately associated with your ultimate remote. Use git push -u... again.

Step 6 - Removing temporary repos A' and B'

Do so in your favourite way.

@yevhenorlov
Copy link

yevhenorlov commented Jan 28, 2018

You may also want removing files like 'package.json' etc for it may not have sense. You have rather to create/update those in repo B
git rm package.json <and/or other files/directories as appropriate>

It would probably make more sense to remove node_modules but to keep package.json files in their respective directories, as different projects nested in our combined repo may have different dependencies. This way, after we finish the merge it's only a matter of running $ npm install in each directory to automatically install their dependencies, specified in each respective package.json. And obviously it makes future maintaining of the repo easier, as we can safely delete individual projects with all their dependencies, without interfering with the rest of the repo.

@OleksiyRudenko
Copy link
Author

Thank you for your comment. Good point. Besides that it is also not a good idea to remove any files that are under version control. Just removed the lines with poor instructions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment