Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to patch a submodule in Git from the parent project?

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?

like image 853
nowox Avatar asked Nov 29 '17 21:11

nowox


People also ask

Which command will you use to update all submodules in your repository?

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.

Will git pull update submodules?

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 .

How do I add a Git submodule to a project?

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.

How do I update parent and submodule in Git?

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.

Are there any new files in gitmodules?

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.

Why does git pull--recurse-submodules fail when using SuperProject?

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:


1 Answers

I would still go with the second option (have a real patch file on main), but adapt my build process to:

  • make a copy of the config.h in the submodule
  • apply the patch
  • build
  • restore config.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.

like image 62
VonC Avatar answered Sep 30 '22 18:09

VonC