In the following example I want to demonstrate that making changes to a Git sub-module and commit it locally can lead to a very bad situation in which I would like to find a working solution (other than the answer "Dude, don't use Git sub-modules it's evil")
The example
I first create two repositories: a main project and its sub-module:
~ $ for r in main sub; do mkdir $r; cd $r; git init; cd ..; done
Initialized empty Git repository in ~/main/.git/
Initialized empty Git repository in ~/sub/.git/
Let's put some content to the sub-module:
~/ $ cd sub
~/sub $ touch sub && git add sub
~/sub $ git commit -m "Added sub"
[master (root-commit) a14ce2f] Added sub
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 sub
Then we import that submodule in the main project:
~/sub $ cd ../main
~/main $ git submodule add ../sub sub
Cloning into '~/main/sub'...
done.
~/main $ git commit -am "Added submodule sub"
[master (root-commit) bd37219] Added submodule sub
2 files changed, 4 insertions(+)
create mode 100644 .gitmodules
create mode 160000 sub
Now the very question: the monkey patch where I want to modify the sub-module locally.
~/main $ cd sub
~/main/sub $ echo "Monkey patched"" >> sub
> echo "Monkey patched"^C>> sub
~/main/sub $ echo "Monkey patched" >> sub
~/main/sub $ git commit -am "Local hotfix"
[master 0b37958] Local hotfix
1 file changed, 1 insertion(+)
~/main/sub $ ..
~/main $ git commit -am "Hijacked sub-module"
[master 1b3a4af] Hijacked sub-module
1 file changed, 1 insertion(+), 1 deletion(-)
Everything looks beautiful because it seems so, but the evil is there.
Alice wants to work on that project so she clone the main repository (let's imagine instead that the main repository was pushed somewhere on the hub by Bob)
~/main $ ..
~/test $ git clone main alice
Cloning into 'alice'...
done.
~/test $ cd alice
~/alice $ git submodule init
Submodule 'sub' (~/sub) registered for path 'sub'
So far Alice is happy until this moment:
~/alice $ git submodule update
Cloning into '~/sub'...
done.
error: Server does not allow request for unadvertised object 0b3795831f31cf8e9c4444a021936c12210e24c6
Fetched in submodule path 'sub', but it did not contain 0b3795831f31cf8e9c4444a021936c12210e24c6. Direct fetching of that commit failed.
If is clear that Git didn't keep track of the monkey patch on the main repository, but on the local history of the sub-module instead.
This looks to me like a design failure of Git sub-modules, or I just misunderstood something that I am asking for today.
The main question
Is there a way to either
- allow to hijack a Git sub-module locally or,
- prevent users that are new to Git to do it so?
Why do I want to modify a sub-module locally?
I am working on embedded firmware development where each new project is composed of:
- A development framework
- A SDK related to the MCU I am using
- Sub-modules which are the drivers for each physical components (bluetooth IC, io expander, led driver, ...) I am using on my board
It sometime happens that I need to monkey patch the code-base of a physical component. For example I want to extend the native range of the bluetooth IC by boosting the radio power (which is not a feature normally allowed by the driver).