I have a project main
that contains a submodule foo
. For this particular project, I would like to make a small change to foo
that only applies to this particular project main
.
main/
+ .git
+ main.c
+ lib/
| + bar.c
+ foo/ # My `foo` submodule
+ .git
+ config.h # The file I want to patch from `main`
+ ...
A common solution would be to go down to my submodule, make a commit Applied patch for main
on a new branch called main-project
, then push it. Unfortunately, this is a very bad approach because I am making changes to foo
that only matters to main
. Also, when I update foo
to the latest version, I will have to cherry-pick the patch too which introduces a lot of noise in foo
's history.
Another solution is to have a real patch file on main
that is applied to foo
just before the build. Unfortunately as this modifies the submodule content, and I will have uncommitted changed on foo
, so it is not a good solution either.
The ideal solution would be to track my patch using Git, but at the top-level (e.g. directly on main
, not on foo
). Theoretically, it would be possible to add a blob
on the Git tree
that points into the submodule location:
blob <sha> main.c
tree <sha> lib/
commit <sha> foo
blob <sha> foo/config.h
With this idea, the patched file config.h
belonging to foo
will be tracked on main
.
How is it possible to do it so?
In order to update an existing Git submodule, you need to execute the “git submodule update” with the “–remote” and the “–merge” option. Using the “–remote” command, you will be able to update your existing Git submodules without having to run “git pull” commands in each submodule of your project.
Once you have set up the submodules you can update the repository with fetch/pull like you would normally do. To pull everything including the submodules, use the --recurse-submodules and the --remote parameter in the git pull command .
The first thing you want to do is to add a Git submodule to your main project. In order to add a Git submodule, use the “git submodule add” command and specify the URL of the Git remote repository to be included as a submodule.
Now we can update the parent repository again by doing a git add and git commit on the submodule. This will put everything into a good state with the local content. If you are working in a team environment it is critical that you then git push the submodule updates, and the parent repository updates.
There are now two new files in the repository .gitmodules and the awesomelibrary directory. Looking at the contents of .gitmodules shows the new submodule mapping The default behavior of git submodule init is to copy the mapping from the .gitmodules file into the local ./.git/config file.
In that case, it is possible for git pull --recurse-submodules, or git submodule update, to fail if the superproject references a submodule commit that is not found in the submodule remote locally configured in your repository. In order to remedy this situation, the git submodule sync command is required:
I would still go with the second option (have a real patch file on main), but adapt my build process to:
config.h
in the submoduleconfig.h
to its original content.That way, I keep the submodule status unchanged.
The OP adds in the comments:
But your solution is not working in a IDE, Intellisense will be confused –
True: for that, I would apply automatically the patch on checkout, and remove it on checking, through a smudge/clean content filter driver.
That way, the patch remains in place during the all session, but would disappear on any git status/diff/checkin.
This is not ideal though, and there does not seem to be a native Git way to handle this.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With