<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
	<id>http://wiki.mipt.ru/index.php?action=history&amp;feed=atom&amp;title=Moodle_development_environment_with_Git_submodules</id>
	<title>Moodle development environment with Git submodules - История изменений</title>
	<link rel="self" type="application/atom+xml" href="http://wiki.mipt.ru/index.php?action=history&amp;feed=atom&amp;title=Moodle_development_environment_with_Git_submodules"/>
	<link rel="alternate" type="text/html" href="http://wiki.mipt.ru/index.php?title=Moodle_development_environment_with_Git_submodules&amp;action=history"/>
	<updated>2026-05-06T18:38:12Z</updated>
	<subtitle>История изменений этой страницы в вики</subtitle>
	<generator>MediaWiki 1.42.1</generator>
	<entry>
		<id>http://wiki.mipt.ru/index.php?title=Moodle_development_environment_with_Git_submodules&amp;diff=4217&amp;oldid=prev</id>
		<title>Олег Давидович: 1 версия импортирована</title>
		<link rel="alternate" type="text/html" href="http://wiki.mipt.ru/index.php?title=Moodle_development_environment_with_Git_submodules&amp;diff=4217&amp;oldid=prev"/>
		<updated>2024-10-18T06:42:57Z</updated>

		<summary type="html">&lt;p&gt;1 версия импортирована&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;ru&quot;&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Предыдущая версия&lt;/td&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Версия от 06:42, 18 октября 2024&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-notice&quot; lang=&quot;ru&quot;&gt;&lt;div class=&quot;mw-diff-empty&quot;&gt;(нет различий)&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;</summary>
		<author><name>Олег Давидович</name></author>
	</entry>
	<entry>
		<id>http://wiki.mipt.ru/index.php?title=Moodle_development_environment_with_Git_submodules&amp;diff=4216&amp;oldid=prev</id>
		<title>1&gt;Tim@horizoneducationnetwork.org: clean up, typos fixed: Therefore → Therefore,, so called → so-called, commited → committed, intialization → initialization, seperate → separate, it&#039;s → its, contributer → contributor</title>
		<link rel="alternate" type="text/html" href="http://wiki.mipt.ru/index.php?title=Moodle_development_environment_with_Git_submodules&amp;diff=4216&amp;oldid=prev"/>
		<updated>2023-01-05T16:27:47Z</updated>

		<summary type="html">&lt;p&gt;clean up, typos fixed: Therefore → Therefore,, so called → so-called, commited → committed, intialization → initialization, seperate → separate, it&amp;#039;s → its, contributer → contributor&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Новая страница&lt;/b&gt;&lt;/p&gt;&lt;div&gt;This page describes how to set up a development environment for a Moodle instance with external plugins.&lt;br /&gt;
Over time the number of plugins may increase in such a way, that they can&amp;#039;t be managed manually by developers anymore.&lt;br /&gt;
Without any precautions this can lead to various problems, for instance:&lt;br /&gt;
* Missing plugins in cloned repositories&lt;br /&gt;
* Diverged versions in existing repositories (can lead to fatal errors when trying to update the site)&lt;br /&gt;
* Messed up Git excludes&lt;br /&gt;
&lt;br /&gt;
You&amp;#039;ll learn in this guide how to use Git submodules in order to achieve the following setup:&lt;br /&gt;
&lt;br /&gt;
[[Image:superprojects1.png|frame|center|Scheme of a development environment]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Note: The extension &amp;#039;&amp;#039;&amp;#039;mod_mylittleextension&amp;#039;&amp;#039;&amp;#039; is a fake plugin, which was created for testing purposes only.&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
By using Git submodules all extensions of a repository can be simply synchronized with other projects.&lt;br /&gt;
All repositories are based on the so-called &amp;#039;&amp;#039;&amp;#039;superproject&amp;#039;&amp;#039;&amp;#039; repository and the developers&amp;#039; projects will be sometimes referred as &amp;#039;local&amp;#039; repository.&lt;br /&gt;
Anyone who is interested in maintaining the superproject and core changes by Git can visit [[Moodle Production Server with GIT]].&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Note: This guide won&amp;#039;t cover basic Git commands and how to install/maintain Git submodules.&lt;br /&gt;
It is assumed, that you have read [[Git for Administrators]] where these topics are covered.&lt;br /&gt;
The superproject will be seen as a Moodle repository where several plugins have been already installed via Git submodules.&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
== Cloning a superproject ==&lt;br /&gt;
&lt;br /&gt;
First a short explanation of events which are triggered, when a superproject is cloned.&lt;br /&gt;
There are some things in Git submodules, which aren&amp;#039;t obvious and can be quite surprising.&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Note: Ensure that you&amp;#039;ve understood the how-to at [[Git for Administrators#Installing and maintaining contributed extensions using Git submodules|Installing and maintaining contributed extensions using Git submodules]] before continuing.&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Assume the plugin &amp;#039;&amp;#039;&amp;#039;mod_mylittleextension&amp;#039;&amp;#039;&amp;#039; (remember: MLE is a fake plugin) was installed in the superproject and these changes have been committed:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cd /path/to/your/superproject&lt;br /&gt;
$ git submodule add /local/repositories/mle/ mod/mylittleextension&lt;br /&gt;
$ git commit -a -m &amp;quot;New module MLE installed&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now a developer has to type in the following commands, in order to clone the superproject (maybe from a remote device).&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cd /path/to/local/directory&lt;br /&gt;
$ git clone &amp;lt;source&amp;gt; moodle&lt;br /&gt;
$ cd moodle&lt;br /&gt;
$ git submodule update --init --recursive&lt;br /&gt;
Submodule &amp;#039;mod/mylittleextension&amp;#039; (/local/repositories/mle) registered for path &amp;#039;mod/mylittleextension&amp;#039;&lt;br /&gt;
Cloning into &amp;#039;mod/mylittleextension&amp;#039;...&lt;br /&gt;
done.&lt;br /&gt;
Submodule path &amp;#039;mod/mylittleextension&amp;#039;: checked out &amp;#039;89d9eae3d5142474d8452128e8df5720d89012cd&amp;#039;&lt;br /&gt;
$ cd mod/mylittleextension&lt;br /&gt;
mod/mylittleextension $ git branch -av&lt;br /&gt;
* (no branch)           89d9eae Initial commit&lt;br /&gt;
  master                89d9eae Initial commit&lt;br /&gt;
  remotes/origin/HEAD   -&amp;gt; origin/master&lt;br /&gt;
  remotes/origin/dev    3a2d487 First commit&lt;br /&gt;
  remotes/origin/master 89d9eae Initial commit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The new main repositories will automatically know about the new extension, but it won&amp;#039;t be initialized, which means that the submodule&amp;#039;s directory will be empty in the beginning.&lt;br /&gt;
For initializing the submodule, the developer needs to execute &amp;#039;&amp;#039;&amp;#039;git submodule update --init --recursive&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
The &amp;#039;&amp;#039;&amp;#039;--recursive&amp;#039;&amp;#039;&amp;#039; option means, that Git will walk through nested submodules as well (not obligatory in this example).&lt;br /&gt;
&lt;br /&gt;
After the initialization the submodule&amp;#039;s repository will be in detached HEAD state.&lt;br /&gt;
This is due the fact, that Git receives following data from the superproject:&lt;br /&gt;
  * source url&lt;br /&gt;
  * local path&lt;br /&gt;
  * HEAD reference (hash)&lt;br /&gt;
See this figure, for a better understanding:&lt;br /&gt;
&lt;br /&gt;
[[Image:superprojects2.png|frame|center|Dotted line: information obtained from the superproject, but already saved locally (by pull)]]&lt;br /&gt;
&lt;br /&gt;
This means, &amp;#039;&amp;#039;&amp;#039;git submodule update --init&amp;#039;&amp;#039;&amp;#039; will first do a clone of &amp;#039;&amp;#039;&amp;#039;source url&amp;#039;&amp;#039;&amp;#039; into the &amp;#039;&amp;#039;&amp;#039;path&amp;#039;&amp;#039;&amp;#039; and then check out the &amp;#039;&amp;#039;&amp;#039;reference&amp;#039;&amp;#039;&amp;#039;, leaving the submodule in detached HEAD state.&lt;br /&gt;
You and your developers need to keep in mind, that any change of the HEAD&amp;#039;s reference of your submodule will be noticed by the main repository.&lt;br /&gt;
This means also, that everyone can switch branches unnoticedly as long as the HEAD&amp;#039;s hash reference doesn&amp;#039;t change.&lt;br /&gt;
E.g. a checkout of the branch &amp;#039;&amp;#039;&amp;#039;master&amp;#039;&amp;#039;&amp;#039; won&amp;#039;t be noticed by the main repository, but a checkout of &amp;#039;&amp;#039;&amp;#039;dev&amp;#039;&amp;#039;&amp;#039; will:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mod/mylittleextension $ git checkout master&lt;br /&gt;
mod/mylittleextension $ git branch -av&lt;br /&gt;
* master                89d9eae Initial commit&lt;br /&gt;
  remotes/origin/HEAD   -&amp;gt; origin/master&lt;br /&gt;
  remotes/origin/dev    3a2d487 First commit&lt;br /&gt;
  remotes/origin/master 89d9eae Initial commit&lt;br /&gt;
$ cd ../..&lt;br /&gt;
$ git status&lt;br /&gt;
# On branch master&lt;br /&gt;
nothing to commit (working directory clean)&lt;br /&gt;
$ cd mod/mylittleextension&lt;br /&gt;
mod/mylittleextension $ git checkout dev&lt;br /&gt;
Branch dev set up to track remote branch dev from origin.&lt;br /&gt;
Switched to a new branch &amp;#039;dev&amp;#039;&lt;br /&gt;
mod/mylittleextension $ cd ../..&lt;br /&gt;
$ git status&lt;br /&gt;
# On branch master&lt;br /&gt;
# Changes not staged for commit:&lt;br /&gt;
#   (use &amp;quot;git add &amp;lt;file&amp;gt;...&amp;quot; to update what will be committed)&lt;br /&gt;
#   (use &amp;quot;git checkout -- &amp;lt;file&amp;gt;...&amp;quot; to discard changes in working directory)&lt;br /&gt;
#&lt;br /&gt;
#	modified:   mod/mylittleextension (new commits)&lt;br /&gt;
#&lt;br /&gt;
no changes added to commit (use &amp;quot;git add&amp;quot; and/or &amp;quot;git commit -a&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There is a shorter command to initialize the submodules, but the outcome will be the same as above.&lt;br /&gt;
Instead of changing the moodle directory and use &amp;#039;&amp;#039;&amp;#039;git submodule update --init&amp;#039;&amp;#039;&amp;#039; after the clone, you can use &amp;#039;&amp;#039;&amp;#039;git clone&amp;#039;&amp;#039;&amp;#039; with the &amp;#039;&amp;#039;&amp;#039;--recursive&amp;#039;&amp;#039;&amp;#039; option as well.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cd /path/to/new/location&lt;br /&gt;
$ git clone --recursive &amp;lt;source&amp;gt; moodle&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In other words, you may use &amp;#039;&amp;#039;&amp;#039;git submodule update --init&amp;#039;&amp;#039;&amp;#039; in the case you forget the &amp;#039;&amp;#039;&amp;#039;--recursive&amp;#039;&amp;#039;&amp;#039; option in your &amp;#039;&amp;#039;&amp;#039;git clone&amp;#039;&amp;#039;&amp;#039; command.&lt;br /&gt;
&lt;br /&gt;
== Upgrading your submodules via the superproject ==&lt;br /&gt;
&lt;br /&gt;
We now assume, that the external plugin is updated by its own repository only and no customization is needed.&lt;br /&gt;
See [[Git for Administrators#Installing_and_maintaining_contributed_extensions_using_Git_submodules|Installing and maintaining contributed extensions using Git submodules]] for further information on the topic of maintaining submodules of your superproject.&lt;br /&gt;
&lt;br /&gt;
=== Pull and upgrade ===&lt;br /&gt;
&lt;br /&gt;
In case a submodule was updated inside the superproject, your developers have to be careful.&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;git pull&amp;#039;&amp;#039;&amp;#039; won&amp;#039;t upgrade the submodules at once and an additional command is needed.&lt;br /&gt;
This is what &amp;#039;&amp;#039;&amp;#039;git pull&amp;#039;&amp;#039;&amp;#039; would look like:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cd /path/to/local/repository&lt;br /&gt;
$ git pull&lt;br /&gt;
remote: Counting objects: 5, done.&lt;br /&gt;
remote: Compressing objects: 100% (3/3), done.&lt;br /&gt;
remote: Total 3 (delta 2), reused 0 (delta 0)&lt;br /&gt;
Unpacking objects: 100% (3/3), done.&lt;br /&gt;
From /local/repositories/super/&lt;br /&gt;
   b547f6c..7f0c348  master     -&amp;gt; origin/master&lt;br /&gt;
Fetching submodule mod/mylittleextension&lt;br /&gt;
remote: Counting objects: 7, done.&lt;br /&gt;
remote: Compressing objects: 100% (5/5), done.&lt;br /&gt;
remote: Total 6 (delta 0), reused 0 (delta 0)&lt;br /&gt;
Unpacking objects: 100% (6/6), done.&lt;br /&gt;
From /local/repositories/mle&lt;br /&gt;
   3a2d487..5e0e66a  dev        -&amp;gt; origin/dev&lt;br /&gt;
   89d9eae..5e0e66a  master     -&amp;gt; origin/master&lt;br /&gt;
Updating b547f6c..7f0c348&lt;br /&gt;
Fast-forward&lt;br /&gt;
 mod/mylittleextension |    2 +-&lt;br /&gt;
 1 file changed, 1 insertion(+), 1 deletion(-)&lt;br /&gt;
$ cd mod/mylittleextension&lt;br /&gt;
mod/mylittleextension $ git branch -av&lt;br /&gt;
* (no branch)           89d9eae Initial commit&lt;br /&gt;
  dev                   3a2d487 [behind 1] First commit&lt;br /&gt;
  master                89d9eae [behind 2] Initial commit&lt;br /&gt;
  remotes/origin/master 5e0e66a Second commit&lt;br /&gt;
  remotes/origin/dev    5e0e66a Second commit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you see, &amp;#039;&amp;#039;&amp;#039;git pull&amp;#039;&amp;#039; triggers &amp;#039;&amp;#039;&amp;#039;git fetch&amp;#039;&amp;#039;&amp;#039; inside the submodules repository, but nothing else.&lt;br /&gt;
Therefore, your developers have to update the submodules afterwards:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cd /path/to/local/repository&lt;br /&gt;
$ git submodule update&lt;br /&gt;
Submodule path &amp;#039;mod/mylittleextension&amp;#039;: checked out &amp;#039;5e0e66aa787f4ebe9f61a940969a6e94abf01a1e&amp;#039;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Figure: Updates without customization ===&lt;br /&gt;
&lt;br /&gt;
[[File:superprojects3.png|frame|center|A workflow for an upgrade from the source repository]]&lt;br /&gt;
&lt;br /&gt;
=== Known issues ===&lt;br /&gt;
&lt;br /&gt;
Since &amp;#039;&amp;#039;&amp;#039;git submodule upgrade&amp;#039;&amp;#039;&amp;#039; checks out the reference, given by your main repository&amp;#039;s commit, your submodule&amp;#039;s repository will turn into detached HEAD state again.&lt;br /&gt;
The command is equivalent to &amp;#039;&amp;#039;&amp;#039;git checkout&amp;#039;&amp;#039;&amp;#039; of the reference inside each submodule&amp;#039;s path.&lt;br /&gt;
That means, that conflicts will abort the checkout, like entering the directory and trying to do the checkout manually.&lt;br /&gt;
So the submodule&amp;#039;s repository should be clean in order to prevent problems with the submodule update.&lt;br /&gt;
&lt;br /&gt;
A special case of this problem happens, if you try to clone a superproject, whose submodule&amp;#039;s reference is not known by the origin.&lt;br /&gt;
Your submodule&amp;#039;s directory would be left blank (since there&amp;#039;s nothing to check out) and you would have to resolve this issue manually (e.g. add your superprojects submodule repository as a remote).&lt;br /&gt;
A situation, you don&amp;#039;t want to get, for sure.&lt;br /&gt;
&lt;br /&gt;
== Upgrading customized plugins ==&lt;br /&gt;
&lt;br /&gt;
=== Figure: Suggested workflow ===&lt;br /&gt;
&lt;br /&gt;
In a normal workflow you don&amp;#039;t touch external plugins and therefore there is no need to alter the submodules in any way.&lt;br /&gt;
But what, if you &amp;#039;&amp;#039;&amp;#039;want to alter&amp;#039;&amp;#039;&amp;#039; them.&lt;br /&gt;
In some cases the submodule is your own plugin or the extension is somehow insufficient but the original contributor doesn&amp;#039;t want to merge your pull requests.&lt;br /&gt;
&lt;br /&gt;
As you know from the previous section &amp;#039;&amp;#039;&amp;#039;git submodule update&amp;#039;&amp;#039;&amp;#039; tries to checkout a specific reference.&lt;br /&gt;
Therefore, this reference must exist in the origin or you will get a problem while updating them.&lt;br /&gt;
If you&amp;#039;re not the contributor of the extension it is necessary to fork these repositiories.&lt;br /&gt;
A suggested workflow would be like this:&lt;br /&gt;
&lt;br /&gt;
[[File:superprojects4.png|frame|center|Suggested workflow with customized plugins]]&lt;br /&gt;
&lt;br /&gt;
Your developers are responsible for updating your forked plugin.&lt;br /&gt;
Therefore, they must merge the original changes into your forked code and resolve conflicts, if necessary.&lt;br /&gt;
Your superproject pulls from the fork only.&lt;br /&gt;
If you&amp;#039;re setting up your first superproject, it doesn&amp;#039;t have to be connected to the original repositiory at all, since you&amp;#039;ll get all updates from your fork.&lt;br /&gt;
So instead of adding the extension&amp;#039;s original remote, you may add the fork only (after adding you can use &amp;#039;&amp;#039;&amp;#039;git remote rename origin fork&amp;#039;&amp;#039;&amp;#039; before your initial commit of the plugin).&lt;br /&gt;
&lt;br /&gt;
=== Setting up a new submodule ===&lt;br /&gt;
&lt;br /&gt;
In case you haven&amp;#039;t installed the extension yet, you can add and rename the repository afterwards (to avoid misunderstanding).&lt;br /&gt;
On your superproject&amp;#039;s machine do the following commands:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cd /path/to/moodle&lt;br /&gt;
$ git submodule add &amp;lt;source:fork&amp;gt; mod/mylittleextension&lt;br /&gt;
Cloning into &amp;#039;mod/mylittleextension&amp;#039;...&lt;br /&gt;
done.&lt;br /&gt;
$ cd mod/mylittleextension&lt;br /&gt;
mod/mylittleextension $ git remote rename origin fork&lt;br /&gt;
mod/mylittleextension $ git branch -avv&lt;br /&gt;
* master              5e0e66a [fork/master] Second commit&lt;br /&gt;
  remotes/fork/HEAD   -&amp;gt; fork/master&lt;br /&gt;
  remotes/fork/dev    5e0e66a Second commit&lt;br /&gt;
  remotes/fork/master 5e0e66a Second commit&lt;br /&gt;
mod/mylittleextension $ cd ../..&lt;br /&gt;
$ git commit -a -m &amp;quot;New extension &amp;#039;MLE&amp;#039; installed&amp;quot;&lt;br /&gt;
[master adecc96] New extension &amp;#039;MLE&amp;#039; installed&lt;br /&gt;
 2 files changed, 4 insertions(+)&lt;br /&gt;
 create mode 100644 .gitmodules&lt;br /&gt;
 create mode 160000 mod/mylittleextension&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Your developers will get your new submodule using &amp;#039;&amp;#039;&amp;#039;git clone&amp;#039;&amp;#039;&amp;#039; or &amp;#039;&amp;#039;&amp;#039;git pull&amp;#039;&amp;#039;&amp;#039; and can rename the remote likewise.&lt;br /&gt;
In addition, they have to fetch updates from the original remote and have to add a remote repository manually.&lt;br /&gt;
On your developers machine type in (output messages from Git are omitted):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /path/to/local/repository&lt;br /&gt;
$ git pull&lt;br /&gt;
$ git submodule update --init&lt;br /&gt;
$ cd mod/mylittleextension&lt;br /&gt;
mod/mylittleextension $ git remote rename origin fork&lt;br /&gt;
mod/mylittleextension $ git remote add origin &amp;lt;source:origin&amp;gt;&lt;br /&gt;
mod/mylittleextension $ git fetch origin&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now your developers can add branches, edit code, do commits and contribute to your fork.&lt;br /&gt;
Details about that topic will follow after the next section.&lt;br /&gt;
&lt;br /&gt;
=== Changes for an existing submodule ===&lt;br /&gt;
&lt;br /&gt;
If the submodule is already installed and your superproject cloned, you must edit the &amp;#039;&amp;#039;&amp;#039;.gitmodules&amp;#039;&amp;#039;&amp;#039; file.&lt;br /&gt;
Since the &amp;#039;&amp;#039;&amp;#039;path&amp;#039;&amp;#039;&amp;#039; and &amp;#039;&amp;#039;&amp;#039;url&amp;#039;&amp;#039;&amp;#039; of your submodule are saved (&amp;#039;&amp;#039;&amp;#039;reference&amp;#039;&amp;#039;&amp;#039; is saved in your commit), you may edit the file manually.&lt;br /&gt;
But you can also use a Git command for that purpose.&lt;br /&gt;
On the superproject&amp;#039;s machine type in (output messages from Git are omitted):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /path/to/moodle/&lt;br /&gt;
$ git config --file=.gitmodules submodule.&amp;quot;mod/mylittleextension&amp;quot;.url &amp;quot;&amp;lt;source:fork&amp;gt;&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;or&amp;#039;&amp;#039;&amp;#039; edit the file &amp;#039;&amp;#039;&amp;#039;.gitmodules&amp;#039;&amp;#039;&amp;#039; respectively.&lt;br /&gt;
&lt;br /&gt;
Afterwards type in:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ git submodule sync&lt;br /&gt;
Synchronizing submodule url for &amp;#039;mod/mylittleextension&amp;#039;&lt;br /&gt;
$ git commit -a -m &amp;quot;Changed source url of &amp;#039;MLE&amp;#039;&amp;quot;&lt;br /&gt;
$ cd mod/mylittleextension&lt;br /&gt;
mod/mylittleextension $ git remote rename origin fork&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;#039;&amp;#039;&amp;#039;sync&amp;#039;&amp;#039;&amp;#039; command will alter the remotes of your submodule&amp;#039;s repository to match the settings of your &amp;#039;&amp;#039;&amp;#039;.gitmodules&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
It is to mention, that changes in the remotes (like &amp;#039;&amp;#039;&amp;#039;rename&amp;#039;&amp;#039;&amp;#039; or &amp;#039;&amp;#039;&amp;#039;add&amp;#039;&amp;#039;&amp;#039;) of a submodule wont be noticed by the Moodle repository.&lt;br /&gt;
In fact, unless you edit a file or change the submodule&amp;#039;s HEAD reference, you can do whatever you want with your branches.&lt;br /&gt;
&lt;br /&gt;
At last your developer has to update his project as well.&lt;br /&gt;
On the developers machine type in (output messages are omitted again):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cd /path/to/local/repository&lt;br /&gt;
$ git pull&lt;br /&gt;
$ git submodule update&lt;br /&gt;
$ git submodule sync&lt;br /&gt;
$ cd mod/mylittleextension&lt;br /&gt;
mod/mylittleextension $ git remote rename origin fork&lt;br /&gt;
mod/mylittleextension $ git remote add origin &amp;lt;source:origin&amp;gt;&lt;br /&gt;
mod/mylittleextension $ git fetch origin&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Again, the &amp;#039;&amp;#039;&amp;#039;sync&amp;#039;&amp;#039;&amp;#039; command will change the remote settings of the submodule to match them with the &amp;#039;&amp;#039;&amp;#039;.gitmodules&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
=== Contributing to the superproject ===&lt;br /&gt;
&lt;br /&gt;
This section will explain how to contribute patches for your superproject.&lt;br /&gt;
Assume your developer has changed an extension and commit his changes in the submodule&amp;#039;s repository.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cd /path/to/local/repository&lt;br /&gt;
$ cd mod/mylittleextension&lt;br /&gt;
mod/mylittleextension $ git branch -avv&lt;br /&gt;
* dev                 9701a0c [fork/dev: ahead 1] Third commit&lt;br /&gt;
  master              5e0e66a [fork/master] Second commit&lt;br /&gt;
  remotes/fork/HEAD   -&amp;gt; fork/master&lt;br /&gt;
  remotes/fork/dev    5e0e66a Second commit&lt;br /&gt;
  remotes/fork/master 5e0e66a Second commit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Push the changes into the fork.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mod/mylittleextension $ git push fork dev:master&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You may organize your forked repository in another way, e.g. let the developers push into a separate branch and merge them only, when it is satisfying.&lt;br /&gt;
For now, we assume the developers can push into your &amp;#039;&amp;#039;&amp;#039;master&amp;#039;&amp;#039;&amp;#039; (or, in general, the branch, which is tracked by your superproject).&lt;br /&gt;
Your developer&amp;#039;s Moodle repository will notice the changes from their commit:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cd /path/to/moodle&lt;br /&gt;
$ git status&lt;br /&gt;
# On branch master&lt;br /&gt;
# Changes not staged for commit:&lt;br /&gt;
#   (use &amp;quot;git add &amp;lt;file&amp;gt;...&amp;quot; to update what will be committed)&lt;br /&gt;
#   (use &amp;quot;git checkout -- &amp;lt;file&amp;gt;...&amp;quot; to discard changes in working directory)&lt;br /&gt;
#&lt;br /&gt;
#	modified:   mod/mylittleextension (new commits)&lt;br /&gt;
#&lt;br /&gt;
no changes added to commit (use &amp;quot;git add&amp;quot; and/or &amp;quot;git commit -a&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Do not commit the changes.&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
We presume, that every change in your main repository is done through a commit from your superproject.&lt;br /&gt;
The status is just saying, that your submodule is on another state than your superproject.&lt;br /&gt;
But this is not a problem at all. We will fix this later.&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Note: When your developers need to commit changes, which are not related to the submodule, they have to avoid to stage the submodule until the superproject has been updated.&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Update the superproject with the following commands on the superproject&amp;#039;s machine:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(On the superproject&amp;#039;s machine)&lt;br /&gt;
$ cd /path/to/moodle&lt;br /&gt;
$ git submodule foreach git pull&lt;br /&gt;
$ git commit -a -m &amp;quot;Plugin updates&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Your developers can now fetch the updated superproject.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(On the developer&amp;#039;s machine)&lt;br /&gt;
$ cd /path/to/local/repository&lt;br /&gt;
$ git pull&lt;br /&gt;
$ git status&lt;br /&gt;
# On branch master&lt;br /&gt;
nothing to commit (working directory clean)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see, your developer don&amp;#039;t need to commit the changed status of the submodule.&lt;br /&gt;
Your developer&amp;#039;s repository will be clean again after a fetch.&lt;br /&gt;
&lt;br /&gt;
=== Figure: Workflow of an update of your submodules ===&lt;br /&gt;
&lt;br /&gt;
[[Image:superprojects5.png|frame|center|The 5th command (&amp;#039;&amp;#039;&amp;#039;git submodule update [--init]&amp;#039;&amp;#039;&amp;#039;) is only necessary, when other submodules are added or updated.]]&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
&lt;br /&gt;
; Moodle Docs&lt;br /&gt;
* [[Git for Administrators]]&lt;br /&gt;
* [[:dev:Git for developers|Git for developers guide]]&lt;br /&gt;
* [[Windows installation using Git]]&lt;br /&gt;
* [[Git for Mac]]&lt;br /&gt;
* [[Moodle Production Server with GIT|Case study Git + Moodle from Technical University Berlin]]&lt;br /&gt;
&lt;br /&gt;
; External resources&lt;br /&gt;
* [https://git-scm.com/book/en/v2/Git-Tools-Submodules Submodules at the Git book]&lt;/div&gt;</summary>
		<author><name>1&gt;Tim@horizoneducationnetwork.org</name></author>
	</entry>
</feed>