The flow is simple:
- I have cloned a repo named
project
. I have also cloned another repoaddon
, embedding it as a submodule withinproject
.
- project
--- addon
------ z.c
--- x.c
--- y.c
- I've made changes to some files inside
addon
. I've committed these changes to bothaddon
and the super-projectproject
. 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, namedotherProject
. This new worktree should contain all the parent's files as they are currently, including theaddon
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 serverorigin
, which of course fails because the server doesn't have my localaddon
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 rungit 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'saddon
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.