Home > Software design >  How to create branch/worktree from local repo containing local submodule commits
How to create branch/worktree from local repo containing local submodule commits

Time:12-01

The flow is simple:

  • I have cloned a repo named project. I have also cloned another repo addon, embedding it as a submodule within project.
- project
--- addon
------ z.c
--- x.c
--- y.c
  • I've made changes to some files inside addon. I've committed these changes to both addon and the super-project project. But I have not pushed them anywhere -- these changes are entirely local.
  • Now, I'd like to create a separate branch/worktree of project at another location, named otherProject. This new worktree should contain all the parent's files as they are currently, including the addon submodule at its current state, preserving its history.
git worktree add -b otherProject path/to/otherProject HEAD

How do I do this?

Currently, the above command doesn't transfer the submodule. Instead, the new worktree's addon folder is empty.


Some of what I've tried:
  • git submodule update --recursive does NOT work. When I run it in the new worktree, it tries to fetch the current submodule commit from the original server origin, which of course fails because the server doesn't have my local addon commits. The errors are along the lines of:
error: Server does not allow request for unadvertised object 987e772b2...
fatal: Fetched in submodule path `addon`, but it did not contain  987e772b2...
  • git checkout --recurse-submodules does NOT seem to work. It doesn't return any error but when I run git status -uno afterwards, I get this:
Submodules changed but not updated:

Warn: addon doesn't contain commit 987e772b2...
  • I tried changing the new worktree's URL in .gitmodules to the local path of the parent repo, but that doesn't help -- it still tries to pull from the remote server. (Some answers seem to imply that one can create submodules from absolute local paths as URL, though this isn't mentioned AT ALL in the docs.)

  • Running git checkout inside the new worktree's addon folder populates it with files -- but these are files taken from the remote server. They do not contain my local changes.

CodePudding user response:

Okay, my last comment on remote-origins led me to check out the submodule update command in more detail. It seems it accepts a --reference option which it passes to any potential clone calls internally. And this option can apparently accept a local path, per the Git-URLs page.

So, basically, I can run this command inside the new worktree otherProject:

git submodule update --recursive --reference <Absolute-Local-Path-To-Parent-Submodule>

e.g.

git submodule update --recursive --reference C:/project/addon

... and the addon submodule gets cloned from there directly, pointing at the submodule-commit bound to the worktree's HEAD.

So far, things look fine. The now-cloned submodule has a detached HEAD, which is easily fixed with git checkout -b newAddonBranchName.

I don't know if this is the "correct" way to do this -- if anyone has a better suggestion, they're most welcome to post it.

  • Related