Merge git submodule into main repository
Asked Answered
L

2

8

Ok, we have a repository with 3 submodules. Now we want to merge this submodules back into main repository, keeping all history (well, using submodules turned out to be more headache than being usefull). How do we proceed?

Lanyard answered 24/1, 2014 at 9:7 Comment(1)
Possible duplicate of un-submodule a git submoduleHorseman
P
6

Let's say you have the following filesystem (and let's assume you only have one submodule, to simply the answer)

myRepoRoot
├── myMainFiles/
└── submodule/

You just need to do:

# Preparing the filesystems
cd submodule
# "submodule" is basically the path where you need your submodule code to be in the new repository,
# e.g. app/code/x/y (<-- in this case you need to create multiple folders ofc, not just one like seen here)
mkdir submodule
git mv file1 file2 dir1 dir2 submodule 
git commit -am "Moved file"

# Actually merging
cd myRepoRoot
git remote add sub url_to_submodule
git fetch sub
git merge sub/master

To explain it with words: you have several trees with no commit in common, and you just need to merge those trees. That's what the second part is doing.

The first part is just needed to ensure the filesystem of the submodule will be what you could expect.

Pleuron answered 24/1, 2014 at 9:16 Comment(1)
I've modified a bit your solution - I've checked all the repositories to separate directories, removed submodules from main repository, moved files in submodules repositories (sibling directories to main repository directory), commited changes, in the main repository add 'remote' repositories as paths like "../submoduleA" etc and then fetched changes from this directories and merged them -- no need to push to remote repository.Lanyard
P
3

I've added an example based on the answer of @gturri, i hope it helps someone:

Example

Let's say this is your submodule:

app/
├─ code/
│  ├─ Foo/
│  │  ├─ Bar/
│  │  │  ├─ .git/
│  │  │  ├─ .gitignore
│  │  │  ├─ registration.php
│  │  │  ├─ etc/
│  │  │  │  └─ modules.xml
│  │  │  ├─ view/
│  │  │  │  ├─ frontend/
│  │  │  │  │  ├─ templates/
│  │  │  │  │  │  ├─ foo.phtml

Your submodule is stored in app/code/Foo/Bar and you need it to be in the exact location in the new repo, then do it like this:

# CD into the submodule
cd app/code/Foo/Bar

# Create the same directory tree as the current submodule path, in your submodule
mkdir -p app/code/Foo/Bar

Pro Tip: Use git submodule foreach 'mkdir -p "$sm_path"' to automatically create the directory structure in all submodules.

See Documentation


New Directory added:

app/
├─ code/
│  ├─ Foo/
│  │  ├─ Bar/
│  │  │  ├─ .git/
│  │  │  ├─ .gitignore
│  │  │  ├─ registration.php
│  │  │  ├─ etc/
│  │  │  │  └─ modules.xml
│  │  │  ├─ view/
│  │  │  │  ├─ frontend/
│  │  │  │  │  ├─ templates/
│  │  │  │  │  │  ├─ foo.phtml
│  │  │  ├─ app/
│  │  │  │  ├─ code/
│  │  │  │  │  ├─ Foo/
│  │  │  │  │  │  ├─ Bar/

Move files to new folder via GIT:

git checkout <target_branch>
git pull
git mv .gitignore registration.php etc/ view/ app/code/Foo/Bar
git commit -am "Moved files"
git push

Now it looks like this:

app/
├─ code/
│  ├─ Foo/
│  │  ├─ Bar/
│  │  │  ├─ .git/
│  │  │  ├─ app/
│  │  │  │  ├─ code/
│  │  │  │  │  ├─ Foo/
│  │  │  │  │  │  ├─ Bar/
│  │  │  │  │  │  │  ├─ .gitignore
│  │  │  │  │  │  │  ├─ registration.php
│  │  │  │  │  │  │  ├─ etc/
│  │  │  │  │  │  │  │  └─ modules.xml
│  │  │  │  │  │  │  ├─ view/
│  │  │  │  │  │  │  │  ├─ frontend/
│  │  │  │  │  │  │  │  │  ├─ templates/
│  │  │  │  │  │  │  │  │  │  ├─ foo.phtml

Delete submodule folder:

rm -rf <my_repo_root>/app/code/Foo/Bar

Merge your submodule to your repo:

cd myRepoRoot
git remote add sub <url_to_submodule>
git fetch sub
git merge sub/master --allow-unrelated-histories

Remove submodule from repo (helps from https://mcmap.net/q/12767/-how-do-i-remove-a-submodule)

rm -rf .git/modules/app/code/Foo/Bar
git config --remove-section submodule.app/code/Foo/Bar

Your submodule should now be located in your repository at app/code/Foo/Bar

Profanatory answered 7/10, 2021 at 11:21 Comment(3)
I think you must use --allow-unrelated-histories as you can see in https://mcmap.net/q/12641/-git-refusing-to-merge-unrelated-histories-on-rebaseWachter
and I think remove sub module with something like https://mcmap.net/q/12767/-how-do-i-remove-a-submoduleWachter
This was very helpful, thank you. I had to entirely remove the submodule - using git rm <path-to-submodule> - before it allowed the merge. (stackoverflow.com/a/1260982). I also had to use a local copy of the submodule as the remote, git remote add sub ../localcopyofsubmodule, as otherwise git-lfs absolutely refused to work.Dubonnet

© 2022 - 2024 — McMap. All rights reserved.