<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://docs.moodle.org/500/en/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Jan-eberhardt</id>
	<title>MoodleDocs - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://docs.moodle.org/500/en/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Jan-eberhardt"/>
	<link rel="alternate" type="text/html" href="https://docs.moodle.org/500/en/Special:Contributions/Jan-eberhardt"/>
	<updated>2026-04-13T03:58:49Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.5</generator>
	<entry>
		<id>https://docs.moodle.org/500/en/index.php?title=Moodle_development_environment_with_Git_submodules&amp;diff=122503</id>
		<title>Moodle development environment with Git submodules</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/500/en/index.php?title=Moodle_development_environment_with_Git_submodules&amp;diff=122503"/>
		<updated>2016-03-15T15:37:25Z</updated>

		<summary type="html">&lt;p&gt;Jan-eberhardt: &lt;/p&gt;
&lt;hr /&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&#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&#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;
&#039;&#039;&#039;Note: The extension &#039;&#039;&#039;mod_mylittleextension&#039;&#039;&#039; is a fake plugin, which was created for testing purposes only.&#039;&#039;&#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 &#039;&#039;&#039;superproject&#039;&#039;&#039; repository and the developers&#039; projects will be sometimes referred as &#039;local&#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;
&#039;&#039;&#039;Note: This guide won&#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.&#039;&#039;&#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&#039;t obvious and can be quite surprising.&lt;br /&gt;
&#039;&#039;&#039;Note: Ensure that you&#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.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Assume the plugin &#039;&#039;&#039;mod_mylittleextension&#039;&#039;&#039; (remember: MLE is a fake plugin) was installed in the superproject and these changes have been commited:&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 &#039;mod/mylittleextension&#039; (/local/repositories/mle) registered for path &#039;mod/mylittleextension&#039;&lt;br /&gt;
Cloning into &#039;mod/mylittleextension&#039;...&lt;br /&gt;
done.&lt;br /&gt;
Submodule path &#039;mod/mylittleextension&#039;: checked out &#039;89d9eae3d5142474d8452128e8df5720d89012cd&#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&#039;t be initialized, which means that the submodule&#039;s directory will be empty in the beginning.&lt;br /&gt;
For initializing the submodule, the developer needs to execute &#039;&#039;&#039;git submodule update --init --recursive&#039;&#039;&#039;.&lt;br /&gt;
The &#039;&#039;&#039;--recursive&#039;&#039;&#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 intialization the submodule&#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, &#039;&#039;&#039;git submodule update --init&#039;&#039;&#039; will first do a clone of &#039;&#039;&#039;source url&#039;&#039;&#039; into the &#039;&#039;&#039;path&#039;&#039;&#039; and then check out the &#039;&#039;&#039;reference&#039;&#039;&#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&#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&#039;s hash reference doesn&#039;t change.&lt;br /&gt;
E.g. a checkout of the branch &#039;&#039;&#039;master&#039;&#039;&#039; won&#039;t be noticed by the main repository, but a checkout of &#039;&#039;&#039;dev&#039;&#039;&#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 &#039;dev&#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 &#039;&#039;&#039;git submodule update --init&#039;&#039;&#039; after the clone, you can use &#039;&#039;&#039;git clone&#039;&#039;&#039; with the &#039;&#039;&#039;--recursive&#039;&#039;&#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 &#039;&#039;&#039;git submodule update --init&#039;&#039;&#039; in the case you forget the &#039;&#039;&#039;--recursive&#039;&#039;&#039; option in your &#039;&#039;&#039;git clone&#039;&#039;&#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 it&#039;s 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;
&#039;&#039;&#039;git pull&#039;&#039;&#039; won&#039;t upgrade the submodules at once and an additional command is needed.&lt;br /&gt;
This is what &#039;&#039;&#039;git pull&#039;&#039;&#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, &#039;&#039;&#039;git pull&#039;&#039; triggers &#039;&#039;&#039;git fetch&#039;&#039;&#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 &#039;mod/mylittleextension&#039;: checked out &#039;5e0e66aa787f4ebe9f61a940969a6e94abf01a1e&#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 &#039;&#039;&#039;git submodule upgrade&#039;&#039;&#039; checks out the reference, given by your main repository&#039;s commit, your submodule&#039;s repository will turn into detached HEAD state again.&lt;br /&gt;
The command is equivalent to &#039;&#039;&#039;git checkout&#039;&#039;&#039; of the reference inside each submodule&#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&#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&#039;s reference is not known by the origin.&lt;br /&gt;
Your submodule&#039;s directory would be left blank (since there&#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&#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&#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 &#039;&#039;&#039;want to alter&#039;&#039;&#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&#039;t want to merge your pull requests.&lt;br /&gt;
&lt;br /&gt;
As you know from the previous section &#039;&#039;&#039;git submodule update&#039;&#039;&#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&#039;re not the contributer 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&#039;re setting up your first superproject, it doesn&#039;t have to be connected to the original repositiory at all, since you&#039;ll get all updates from your fork.&lt;br /&gt;
So instead of adding the extension&#039;s original remote, you may add the fork only (after adding you can use &#039;&#039;&#039;git remote rename origin fork&#039;&#039;&#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&#039;t installed the extension yet, you can add and rename the repository afterwards (to avoid misunderstanding).&lt;br /&gt;
On your superproject&#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 &#039;mod/mylittleextension&#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 &#039;MLE&#039; installed&amp;quot;&lt;br /&gt;
[master adecc96] New extension &#039;MLE&#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 &#039;&#039;&#039;git clone&#039;&#039;&#039; or &#039;&#039;&#039;git pull&#039;&#039;&#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 &#039;&#039;&#039;.gitmodules&#039;&#039;&#039; file.&lt;br /&gt;
Since the &#039;&#039;&#039;path&#039;&#039;&#039; and &#039;&#039;&#039;url&#039;&#039;&#039; of your submodule are saved (&#039;&#039;&#039;reference&#039;&#039;&#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&#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;
&#039;&#039;&#039;or&#039;&#039;&#039; edit the file &#039;&#039;&#039;.gitmodules&#039;&#039;&#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 &#039;mod/mylittleextension&#039;&lt;br /&gt;
$ git commit -a -m &amp;quot;Changed source url of &#039;MLE&#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 &#039;&#039;&#039;sync&#039;&#039;&#039; command will alter the remotes of your submodule&#039;s repository to match the settings of your &#039;&#039;&#039;.gitmodules&#039;&#039;&#039;.&lt;br /&gt;
It is to mention, that changes in the remotes (like &#039;&#039;&#039;rename&#039;&#039;&#039; or &#039;&#039;&#039;add&#039;&#039;&#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&#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 &#039;&#039;&#039;sync&#039;&#039;&#039; command will change the remote settings of the submodule to match them with the &#039;&#039;&#039;.gitmodules&#039;&#039;&#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&#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 seperate branch and merge them only, when it is satisfying.&lt;br /&gt;
For now, we assume the developers can push into your &#039;&#039;&#039;master&#039;&#039;&#039; (or, in general, the branch, which is tracked by your superproject).&lt;br /&gt;
Your developer&#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;
&#039;&#039;&#039;Do not commit the changes.&#039;&#039;&#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;
&#039;&#039;&#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.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Update the superproject with the following commands on the superproject&#039;s machine:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(On the superproject&#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&#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&#039;t need to commit the changed status of the submodule.&lt;br /&gt;
Your developer&#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 (&#039;&#039;&#039;git submodule update [--init]&#039;&#039;&#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>Jan-eberhardt</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/500/en/index.php?title=Moodle_development_environment_with_Git_submodules&amp;diff=122502</id>
		<title>Moodle development environment with Git submodules</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/500/en/index.php?title=Moodle_development_environment_with_Git_submodules&amp;diff=122502"/>
		<updated>2016-03-15T15:32:13Z</updated>

		<summary type="html">&lt;p&gt;Jan-eberhardt: &lt;/p&gt;
&lt;hr /&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&#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&#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|thumbs|center|Scheme of a development environment]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note: The extension &#039;&#039;&#039;mod_mylittleextension&#039;&#039;&#039; is a fake plugin, which was created for testing purposes only.&#039;&#039;&#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 &#039;&#039;&#039;superproject&#039;&#039;&#039; repository and the developers&#039; projects will be sometimes referred as &#039;local&#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;
&#039;&#039;&#039;Note: This guide won&#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.&#039;&#039;&#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&#039;t obvious and can be quite surprising.&lt;br /&gt;
&#039;&#039;&#039;Note: Ensure that you&#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.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Assume the plugin &#039;&#039;&#039;mod_mylittleextension&#039;&#039;&#039; (remember: MLE is a fake plugin) was installed in the superproject and these changes have been commited:&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 &#039;mod/mylittleextension&#039; (/local/repositories/mle) registered for path &#039;mod/mylittleextension&#039;&lt;br /&gt;
Cloning into &#039;mod/mylittleextension&#039;...&lt;br /&gt;
done.&lt;br /&gt;
Submodule path &#039;mod/mylittleextension&#039;: checked out &#039;89d9eae3d5142474d8452128e8df5720d89012cd&#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&#039;t be initialized, which means that the submodule&#039;s directory will be empty in the beginning.&lt;br /&gt;
For initializing the submodule, the developer needs to execute &#039;&#039;&#039;git submodule update --init --recursive&#039;&#039;&#039;.&lt;br /&gt;
The &#039;&#039;&#039;--recursive&#039;&#039;&#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 intialization the submodule&#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| Dotted line: information obtained from the superproject, but already saved locally (by pull)]]&lt;br /&gt;
&lt;br /&gt;
This means, &#039;&#039;&#039;git submodule update --init&#039;&#039;&#039; will first do a clone of &#039;&#039;&#039;source url&#039;&#039;&#039; into the &#039;&#039;&#039;path&#039;&#039;&#039; and then check out the &#039;&#039;&#039;reference&#039;&#039;&#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&#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&#039;s hash reference doesn&#039;t change.&lt;br /&gt;
E.g. a checkout of the branch &#039;&#039;&#039;master&#039;&#039;&#039; won&#039;t be noticed by the main repository, but a checkout of &#039;&#039;&#039;dev&#039;&#039;&#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 &#039;dev&#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 &#039;&#039;&#039;git submodule update --init&#039;&#039;&#039; after the clone, you can use &#039;&#039;&#039;git clone&#039;&#039;&#039; with the &#039;&#039;&#039;--recursive&#039;&#039;&#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 &#039;&#039;&#039;git submodule update --init&#039;&#039;&#039; in the case you forget the &#039;&#039;&#039;--recursive&#039;&#039;&#039; option in your &#039;&#039;&#039;git clone&#039;&#039;&#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 it&#039;s 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;
&#039;&#039;&#039;git pull&#039;&#039;&#039; won&#039;t upgrade the submodules at once and an additional command is needed.&lt;br /&gt;
This is what &#039;&#039;&#039;git pull&#039;&#039;&#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, &#039;&#039;&#039;git pull&#039;&#039; triggers &#039;&#039;&#039;git fetch&#039;&#039;&#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 &#039;mod/mylittleextension&#039;: checked out &#039;5e0e66aa787f4ebe9f61a940969a6e94abf01a1e&#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|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 &#039;&#039;&#039;git submodule upgrade&#039;&#039;&#039; checks out the reference, given by your main repository&#039;s commit, your submodule&#039;s repository will turn into detached HEAD state again.&lt;br /&gt;
The command is equivalent to &#039;&#039;&#039;git checkout&#039;&#039;&#039; of the reference inside each submodule&#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&#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&#039;s reference is not known by the origin.&lt;br /&gt;
Your submodule&#039;s directory would be left blank (since there&#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&#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&#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 &#039;&#039;&#039;want to alter&#039;&#039;&#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&#039;t want to merge your pull requests.&lt;br /&gt;
&lt;br /&gt;
As you know from the previous section &#039;&#039;&#039;git submodule update&#039;&#039;&#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&#039;re not the contributer 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|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&#039;re setting up your first superproject, it doesn&#039;t have to be connected to the original repositiory at all, since you&#039;ll get all updates from your fork.&lt;br /&gt;
So instead of adding the extension&#039;s original remote, you may add the fork only (after adding you can use &#039;&#039;&#039;git remote rename origin fork&#039;&#039;&#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&#039;t installed the extension yet, you can add and rename the repository afterwards (to avoid misunderstanding).&lt;br /&gt;
On your superproject&#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 &#039;mod/mylittleextension&#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 &#039;MLE&#039; installed&amp;quot;&lt;br /&gt;
[master adecc96] New extension &#039;MLE&#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 &#039;&#039;&#039;git clone&#039;&#039;&#039; or &#039;&#039;&#039;git pull&#039;&#039;&#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 &#039;&#039;&#039;.gitmodules&#039;&#039;&#039; file.&lt;br /&gt;
Since the &#039;&#039;&#039;path&#039;&#039;&#039; and &#039;&#039;&#039;url&#039;&#039;&#039; of your submodule are saved (&#039;&#039;&#039;reference&#039;&#039;&#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&#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;
&#039;&#039;&#039;or&#039;&#039;&#039; edit the file &#039;&#039;&#039;.gitmodules&#039;&#039;&#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 &#039;mod/mylittleextension&#039;&lt;br /&gt;
$ git commit -a -m &amp;quot;Changed source url of &#039;MLE&#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 &#039;&#039;&#039;sync&#039;&#039;&#039; command will alter the remotes of your submodule&#039;s repository to match the settings of your &#039;&#039;&#039;.gitmodules&#039;&#039;&#039;.&lt;br /&gt;
It is to mention, that changes in the remotes (like &#039;&#039;&#039;rename&#039;&#039;&#039; or &#039;&#039;&#039;add&#039;&#039;&#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&#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 &#039;&#039;&#039;sync&#039;&#039;&#039; command will change the remote settings of the submodule to match them with the &#039;&#039;&#039;.gitmodules&#039;&#039;&#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&#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 seperate branch and merge them only, when it is satisfying.&lt;br /&gt;
For now, we assume the developers can push into your &#039;&#039;&#039;master&#039;&#039;&#039; (or, in general, the branch, which is tracked by your superproject).&lt;br /&gt;
Your developer&#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;
&#039;&#039;&#039;Do not commit the changes.&#039;&#039;&#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;
&#039;&#039;&#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.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Update the superproject with the following commands on the superproject&#039;s machine:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(On the superproject&#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&#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&#039;t need to commit the changed status of the submodule.&lt;br /&gt;
Your developer&#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|The 5th command (&#039;&#039;&#039;git submodule update [--init]&#039;&#039;&#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>Jan-eberhardt</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/500/en/index.php?title=Moodle_development_environment_with_Git_submodules&amp;diff=122501</id>
		<title>Moodle development environment with Git submodules</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/500/en/index.php?title=Moodle_development_environment_with_Git_submodules&amp;diff=122501"/>
		<updated>2016-03-15T15:31:07Z</updated>

		<summary type="html">&lt;p&gt;Jan-eberhardt: &lt;/p&gt;
&lt;hr /&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&#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&#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|thumbs|center|Scheme of a development environment]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note: The extension &#039;&#039;&#039;mod_mylittleextension&#039;&#039;&#039; is a fake plugin, which was created for testing purposes only.&#039;&#039;&#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 &#039;&#039;&#039;superproject&#039;&#039;&#039; repository and the developers&#039; projects will be sometimes referred as &#039;local&#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;
&#039;&#039;&#039;Note: This guide won&#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.&#039;&#039;&#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&#039;t obvious and can be quite surprising.&lt;br /&gt;
&#039;&#039;&#039;Note: Ensure that you&#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.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Assume the plugin &#039;&#039;&#039;mod_mylittleextension&#039;&#039;&#039; (remember: MLE is a fake plugin) was installed in the superproject and these changes have been commited:&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 &#039;mod/mylittleextension&#039; (/local/repositories/mle) registered for path &#039;mod/mylittleextension&#039;&lt;br /&gt;
Cloning into &#039;mod/mylittleextension&#039;...&lt;br /&gt;
done.&lt;br /&gt;
Submodule path &#039;mod/mylittleextension&#039;: checked out &#039;89d9eae3d5142474d8452128e8df5720d89012cd&#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&#039;t be initialized, which means that the submodule&#039;s directory will be empty in the beginning.&lt;br /&gt;
For initializing the submodule, the developer needs to execute &#039;&#039;&#039;git submodule update --init --recursive&#039;&#039;&#039;.&lt;br /&gt;
The &#039;&#039;&#039;--recursive&#039;&#039;&#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 intialization the submodule&#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| Dotted line: information obtained from the superproject, but already saved locally (by pull)]]&lt;br /&gt;
&lt;br /&gt;
This means, &#039;&#039;&#039;git submodule update --init&#039;&#039;&#039; will first do a clone of &#039;&#039;&#039;source url&#039;&#039;&#039; into the &#039;&#039;&#039;path&#039;&#039;&#039; and then check out the &#039;&#039;&#039;reference&#039;&#039;&#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&#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&#039;s hash reference doesn&#039;t change.&lt;br /&gt;
E.g. a checkout of the branch &#039;&#039;&#039;master&#039;&#039;&#039; won&#039;t be noticed by the main repository, but a checkout of &#039;&#039;&#039;dev&#039;&#039;&#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 &#039;dev&#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 &#039;&#039;&#039;git submodule update --init&#039;&#039;&#039; after the clone, you can use &#039;&#039;&#039;git clone&#039;&#039;&#039; with the &#039;&#039;&#039;--recursive&#039;&#039;&#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 &#039;&#039;&#039;git submodule update --init&#039;&#039;&#039; in the case you forget the &#039;&#039;&#039;--recursive&#039;&#039;&#039; option in your &#039;&#039;&#039;git clone&#039;&#039;&#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 it&#039;s 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;
&#039;&#039;&#039;git pull&#039;&#039;&#039; won&#039;t upgrade the submodules at once and an additional command is needed.&lt;br /&gt;
This is what &#039;&#039;&#039;git pull&#039;&#039;&#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, &#039;&#039;&#039;git pull&#039;&#039; triggers &#039;&#039;&#039;git fetch&#039;&#039;&#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 &#039;mod/mylittleextension&#039;: checked out &#039;5e0e66aa787f4ebe9f61a940969a6e94abf01a1e&#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|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 &#039;&#039;&#039;git submodule upgrade&#039;&#039;&#039; checks out the reference, given by your main repository&#039;s commit, your submodule&#039;s repository will turn into detached HEAD state again.&lt;br /&gt;
The command is equivalent to &#039;&#039;&#039;git checkout&#039;&#039;&#039; of the reference inside each submodule&#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&#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&#039;s reference is not known by the origin.&lt;br /&gt;
Your submodule&#039;s directory would be left blank (since there&#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&#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&#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 &#039;&#039;&#039;want to alter&#039;&#039;&#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&#039;t want to merge your pull requests.&lt;br /&gt;
&lt;br /&gt;
As you know from the previous section &#039;&#039;&#039;git submodule update&#039;&#039;&#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&#039;re not the contributer 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|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&#039;re setting up your first superproject, it doesn&#039;t have to be connected to the original repositiory at all, since you&#039;ll get all updates from your fork.&lt;br /&gt;
So instead of adding the extension&#039;s original remote, you may add the fork only (after adding you can use &#039;&#039;&#039;git remote rename origin fork&#039;&#039;&#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&#039;t installed the extension yet, you can add and rename the repository afterwards (to avoid misunderstanding).&lt;br /&gt;
On your superproject&#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 &#039;mod/mylittleextension&#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 &#039;MLE&#039; installed&amp;quot;&lt;br /&gt;
[master adecc96] New extension &#039;MLE&#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 &#039;&#039;&#039;git clone&#039;&#039;&#039; or &#039;&#039;&#039;git pull&#039;&#039;&#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 &#039;&#039;&#039;.gitmodules&#039;&#039;&#039; file.&lt;br /&gt;
Since the &#039;&#039;&#039;path&#039;&#039;&#039; and &#039;&#039;&#039;url&#039;&#039;&#039; of your submodule are saved (&#039;&#039;&#039;reference&#039;&#039;&#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&#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;
&#039;&#039;&#039;or&#039;&#039;&#039; edit the file &#039;&#039;&#039;.gitmodules&#039;&#039;&#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 &#039;mod/mylittleextension&#039;&lt;br /&gt;
$ git commit -a -m &amp;quot;Changed source url of &#039;MLE&#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 &#039;&#039;&#039;sync&#039;&#039;&#039; command will alter the remotes of your submodule&#039;s repository to match the settings of your &#039;&#039;&#039;.gitmodules&#039;&#039;&#039;.&lt;br /&gt;
It is to mention, that changes in the remotes (like &#039;&#039;&#039;rename&#039;&#039;&#039; or &#039;&#039;&#039;add&#039;&#039;&#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&#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 &#039;&#039;&#039;sync&#039;&#039;&#039; command will change the remote settings of the submodule to match them with the &#039;&#039;&#039;.gitmodules&#039;&#039;&#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&#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 seperate branch and merge them only, when it is satisfying.&lt;br /&gt;
For now, we assume the developers can push into your &#039;&#039;&#039;master&#039;&#039;&#039; (or, in general, the branch, which is tracked by your superproject).&lt;br /&gt;
Your developer&#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;
&#039;&#039;&#039;Do not commit the changes.&#039;&#039;&#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;
&#039;&#039;&#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.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Update the superproject with the following commands on the superproject&#039;s machine:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(On the superproject&#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&#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&#039;t need to commit the changed status of the submodule.&lt;br /&gt;
Your developer&#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|The 5th command (&#039;&#039;&#039;git submodule update [--init]&#039;&#039;&#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>Jan-eberhardt</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/500/en/index.php?title=Moodle_development_environment_with_Git_submodules&amp;diff=122500</id>
		<title>Moodle development environment with Git submodules</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/500/en/index.php?title=Moodle_development_environment_with_Git_submodules&amp;diff=122500"/>
		<updated>2016-03-15T15:30:47Z</updated>

		<summary type="html">&lt;p&gt;Jan-eberhardt: &lt;/p&gt;
&lt;hr /&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&#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&#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|thumbs|center|Scheme of a development environment]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note: The extension &#039;&#039;&#039;mod_mylittleextension&#039;&#039;&#039; is a fake plugin, which was created for testing purposes only.&#039;&#039;&#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 &#039;&#039;&#039;superproject&#039;&#039;&#039; repository and the developers&#039; projects will be sometimes referred as &#039;local&#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;
&#039;&#039;&#039;Note: This guide won&#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.&#039;&#039;&#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&#039;t obvious and can be quite surprising.&lt;br /&gt;
&#039;&#039;&#039;Note: Ensure that you&#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.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Assume the plugin &#039;&#039;&#039;mod_mylittleextension&#039;&#039;&#039; (remember: MLE is a fake plugin) was installed in the superproject and these changes have been commited:&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 &#039;mod/mylittleextension&#039; (/local/repositories/mle) registered for path &#039;mod/mylittleextension&#039;&lt;br /&gt;
Cloning into &#039;mod/mylittleextension&#039;...&lt;br /&gt;
done.&lt;br /&gt;
Submodule path &#039;mod/mylittleextension&#039;: checked out &#039;89d9eae3d5142474d8452128e8df5720d89012cd&#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&#039;t be initialized, which means that the submodule&#039;s directory will be empty in the beginning.&lt;br /&gt;
For initializing the submodule, the developer needs to execute &#039;&#039;&#039;git submodule update --init --recursive&#039;&#039;&#039;.&lt;br /&gt;
The &#039;&#039;&#039;--recursive&#039;&#039;&#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 intialization the submodule&#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| Dotted line: information obtained from the superproject, but already saved locally (by pull)]]&lt;br /&gt;
&lt;br /&gt;
This means, &#039;&#039;&#039;git submodule update --init&#039;&#039;&#039; will first do a clone of &#039;&#039;&#039;source url&#039;&#039;&#039; into the &#039;&#039;&#039;path&#039;&#039;&#039; and then check out the &#039;&#039;&#039;reference&#039;&#039;&#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&#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&#039;s hash reference doesn&#039;t change.&lt;br /&gt;
E.g. a checkout of the branch &#039;&#039;&#039;master&#039;&#039;&#039; won&#039;t be noticed by the main repository, but a checkout of &#039;&#039;&#039;dev&#039;&#039;&#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 &#039;dev&#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 &#039;&#039;&#039;git submodule update --init&#039;&#039;&#039; after the clone, you can use &#039;&#039;&#039;git clone&#039;&#039;&#039; with the &#039;&#039;&#039;--recursive&#039;&#039;&#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 &#039;&#039;&#039;git submodule update --init&#039;&#039;&#039; in the case you forget the &#039;&#039;&#039;--recursive&#039;&#039;&#039; option in your &#039;&#039;&#039;git clone&#039;&#039;&#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 it&#039;s 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;
&#039;&#039;&#039;git pull&#039;&#039;&#039; won&#039;t upgrade the submodules at once and an additional command is needed.&lt;br /&gt;
This is what &#039;&#039;&#039;git pull&#039;&#039;&#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, &#039;&#039;&#039;git pull&#039;&#039; triggers &#039;&#039;&#039;git fetch&#039;&#039;&#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 &#039;mod/mylittleextension&#039;: checked out &#039;5e0e66aa787f4ebe9f61a940969a6e94abf01a1e&#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|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 &#039;&#039;&#039;git submodule upgrade&#039;&#039;&#039; checks out the reference, given by your main repository&#039;s commit, your submodule&#039;s repository will turn into detached HEAD state again.&lt;br /&gt;
The command is equivalent to &#039;&#039;&#039;git checkout&#039;&#039;&#039; of the reference inside each submodule&#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&#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&#039;s reference is not known by the origin.&lt;br /&gt;
Your submodule&#039;s directory would be left blank (since there&#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&#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&#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 &#039;&#039;&#039;want to alter&#039;&#039;&#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&#039;t want to merge your pull requests.&lt;br /&gt;
&lt;br /&gt;
As you know from the previous section &#039;&#039;&#039;git submodule update&#039;&#039;&#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&#039;re not the contributer 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|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&#039;re setting up your first superproject, it doesn&#039;t have to be connected to the original repositiory at all, since you&#039;ll get all updates from your fork.&lt;br /&gt;
So instead of adding the extension&#039;s original remote, you may add the fork only (after adding you can use &#039;&#039;&#039;git remote rename origin fork&#039;&#039;&#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&#039;t installed the extension yet, you can add and rename the repository afterwards (to avoid misunderstanding).&lt;br /&gt;
On your superproject&#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 &#039;mod/mylittleextension&#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 &#039;MLE&#039; installed&amp;quot;&lt;br /&gt;
[master adecc96] New extension &#039;MLE&#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 &#039;&#039;&#039;git clone&#039;&#039;&#039; or &#039;&#039;&#039;git pull&#039;&#039;&#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 &#039;&#039;&#039;.gitmodules&#039;&#039;&#039; file.&lt;br /&gt;
Since the &#039;&#039;&#039;path&#039;&#039;&#039; and &#039;&#039;&#039;url&#039;&#039;&#039; of your submodule are saved (&#039;&#039;&#039;reference&#039;&#039;&#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&#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;
&#039;&#039;&#039;or&#039;&#039;&#039; edit the file &#039;&#039;&#039;.gitmodules&#039;&#039;&#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 &#039;mod/mylittleextension&#039;&lt;br /&gt;
$ git commit -a -m &amp;quot;Changed source url of &#039;MLE&#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 &#039;&#039;&#039;sync&#039;&#039;&#039; command will alter the remotes of your submodule&#039;s repository to match the settings of your &#039;&#039;&#039;.gitmodules&#039;&#039;&#039;.&lt;br /&gt;
It is to mention, that changes in the remotes (like &#039;&#039;&#039;rename&#039;&#039;&#039; or &#039;&#039;&#039;add&#039;&#039;&#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&#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 &#039;&#039;&#039;sync&#039;&#039;&#039; command will change the remote settings of the submodule to match them with the &#039;&#039;&#039;.gitmodules&#039;&#039;&#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&#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 seperate branch and merge them only, when it is satisfying.&lt;br /&gt;
For now, we assume the developers can push into your &#039;&#039;&#039;master&#039;&#039;&#039; (or, in general, the branch, which is tracked by your superproject).&lt;br /&gt;
Your developer&#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;
&#039;&#039;&#039;Do not commit the changes.&#039;&#039;&#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;
&#039;&#039;&#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.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Update the superproject with the following commands on the superproject&#039;s machine:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(On the superproject&#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&#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&#039;t need to commit the changed status of the submodule.&lt;br /&gt;
Your developer&#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|The 5th command (&#039;&#039;&#039;git submodule update [--init]&#039;&#039;&#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>Jan-eberhardt</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/500/en/index.php?title=Moodle_development_environment_with_Git_submodules&amp;diff=122499</id>
		<title>Moodle development environment with Git submodules</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/500/en/index.php?title=Moodle_development_environment_with_Git_submodules&amp;diff=122499"/>
		<updated>2016-03-15T15:28:34Z</updated>

		<summary type="html">&lt;p&gt;Jan-eberhardt: /* See also */&lt;/p&gt;
&lt;hr /&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&#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&#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|center|Scheme of a development environment]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note: The extension &#039;&#039;&#039;mod_mylittleextension&#039;&#039;&#039; is a fake plugin, which was created for testing purposes only.&#039;&#039;&#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 &#039;&#039;&#039;superproject&#039;&#039;&#039; repository and the developers&#039; projects will be sometimes referred as &#039;local&#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;
&#039;&#039;&#039;Note: This guide won&#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.&#039;&#039;&#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&#039;t obvious and can be quite surprising.&lt;br /&gt;
&#039;&#039;&#039;Note: Ensure that you&#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.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Assume the plugin &#039;&#039;&#039;mod_mylittleextension&#039;&#039;&#039; (remember: MLE is a fake plugin) was installed in the superproject and these changes have been commited:&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 &#039;mod/mylittleextension&#039; (/local/repositories/mle) registered for path &#039;mod/mylittleextension&#039;&lt;br /&gt;
Cloning into &#039;mod/mylittleextension&#039;...&lt;br /&gt;
done.&lt;br /&gt;
Submodule path &#039;mod/mylittleextension&#039;: checked out &#039;89d9eae3d5142474d8452128e8df5720d89012cd&#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&#039;t be initialized, which means that the submodule&#039;s directory will be empty in the beginning.&lt;br /&gt;
For initializing the submodule, the developer needs to execute &#039;&#039;&#039;git submodule update --init --recursive&#039;&#039;&#039;.&lt;br /&gt;
The &#039;&#039;&#039;--recursive&#039;&#039;&#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 intialization the submodule&#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| Dotted line: information obtained from the superproject, but already saved locally (by pull)]]&lt;br /&gt;
&lt;br /&gt;
This means, &#039;&#039;&#039;git submodule update --init&#039;&#039;&#039; will first do a clone of &#039;&#039;&#039;source url&#039;&#039;&#039; into the &#039;&#039;&#039;path&#039;&#039;&#039; and then check out the &#039;&#039;&#039;reference&#039;&#039;&#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&#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&#039;s hash reference doesn&#039;t change.&lt;br /&gt;
E.g. a checkout of the branch &#039;&#039;&#039;master&#039;&#039;&#039; won&#039;t be noticed by the main repository, but a checkout of &#039;&#039;&#039;dev&#039;&#039;&#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 &#039;dev&#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 &#039;&#039;&#039;git submodule update --init&#039;&#039;&#039; after the clone, you can use &#039;&#039;&#039;git clone&#039;&#039;&#039; with the &#039;&#039;&#039;--recursive&#039;&#039;&#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 &#039;&#039;&#039;git submodule update --init&#039;&#039;&#039; in the case you forget the &#039;&#039;&#039;--recursive&#039;&#039;&#039; option in your &#039;&#039;&#039;git clone&#039;&#039;&#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 it&#039;s 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;
&#039;&#039;&#039;git pull&#039;&#039;&#039; won&#039;t upgrade the submodules at once and an additional command is needed.&lt;br /&gt;
This is what &#039;&#039;&#039;git pull&#039;&#039;&#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, &#039;&#039;&#039;git pull&#039;&#039; triggers &#039;&#039;&#039;git fetch&#039;&#039;&#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 &#039;mod/mylittleextension&#039;: checked out &#039;5e0e66aa787f4ebe9f61a940969a6e94abf01a1e&#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|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 &#039;&#039;&#039;git submodule upgrade&#039;&#039;&#039; checks out the reference, given by your main repository&#039;s commit, your submodule&#039;s repository will turn into detached HEAD state again.&lt;br /&gt;
The command is equivalent to &#039;&#039;&#039;git checkout&#039;&#039;&#039; of the reference inside each submodule&#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&#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&#039;s reference is not known by the origin.&lt;br /&gt;
Your submodule&#039;s directory would be left blank (since there&#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&#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&#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 &#039;&#039;&#039;want to alter&#039;&#039;&#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&#039;t want to merge your pull requests.&lt;br /&gt;
&lt;br /&gt;
As you know from the previous section &#039;&#039;&#039;git submodule update&#039;&#039;&#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&#039;re not the contributer 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|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&#039;re setting up your first superproject, it doesn&#039;t have to be connected to the original repositiory at all, since you&#039;ll get all updates from your fork.&lt;br /&gt;
So instead of adding the extension&#039;s original remote, you may add the fork only (after adding you can use &#039;&#039;&#039;git remote rename origin fork&#039;&#039;&#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&#039;t installed the extension yet, you can add and rename the repository afterwards (to avoid misunderstanding).&lt;br /&gt;
On your superproject&#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 &#039;mod/mylittleextension&#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 &#039;MLE&#039; installed&amp;quot;&lt;br /&gt;
[master adecc96] New extension &#039;MLE&#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 &#039;&#039;&#039;git clone&#039;&#039;&#039; or &#039;&#039;&#039;git pull&#039;&#039;&#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 &#039;&#039;&#039;.gitmodules&#039;&#039;&#039; file.&lt;br /&gt;
Since the &#039;&#039;&#039;path&#039;&#039;&#039; and &#039;&#039;&#039;url&#039;&#039;&#039; of your submodule are saved (&#039;&#039;&#039;reference&#039;&#039;&#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&#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;
&#039;&#039;&#039;or&#039;&#039;&#039; edit the file &#039;&#039;&#039;.gitmodules&#039;&#039;&#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 &#039;mod/mylittleextension&#039;&lt;br /&gt;
$ git commit -a -m &amp;quot;Changed source url of &#039;MLE&#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 &#039;&#039;&#039;sync&#039;&#039;&#039; command will alter the remotes of your submodule&#039;s repository to match the settings of your &#039;&#039;&#039;.gitmodules&#039;&#039;&#039;.&lt;br /&gt;
It is to mention, that changes in the remotes (like &#039;&#039;&#039;rename&#039;&#039;&#039; or &#039;&#039;&#039;add&#039;&#039;&#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&#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 &#039;&#039;&#039;sync&#039;&#039;&#039; command will change the remote settings of the submodule to match them with the &#039;&#039;&#039;.gitmodules&#039;&#039;&#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&#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 seperate branch and merge them only, when it is satisfying.&lt;br /&gt;
For now, we assume the developers can push into your &#039;&#039;&#039;master&#039;&#039;&#039; (or, in general, the branch, which is tracked by your superproject).&lt;br /&gt;
Your developer&#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;
&#039;&#039;&#039;Do not commit the changes.&#039;&#039;&#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;
&#039;&#039;&#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.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Update the superproject with the following commands on the superproject&#039;s machine:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(On the superproject&#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&#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&#039;t need to commit the changed status of the submodule.&lt;br /&gt;
Your developer&#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|The 5th command (&#039;&#039;&#039;git submodule update [--init]&#039;&#039;&#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>Jan-eberhardt</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/500/en/index.php?title=File:superprojects5.png&amp;diff=122498</id>
		<title>File:superprojects5.png</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/500/en/index.php?title=File:superprojects5.png&amp;diff=122498"/>
		<updated>2016-03-15T15:26:09Z</updated>

		<summary type="html">&lt;p&gt;Jan-eberhardt: 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;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The 5th command (&#039;&#039;&#039;git submodule update [--init]&#039;&#039;&#039;) is only necessary, when other submodules are added or updated.&lt;/div&gt;</summary>
		<author><name>Jan-eberhardt</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/500/en/index.php?title=Moodle_development_environment_with_Git_submodules&amp;diff=122497</id>
		<title>Moodle development environment with Git submodules</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/500/en/index.php?title=Moodle_development_environment_with_Git_submodules&amp;diff=122497"/>
		<updated>2016-03-15T15:25:32Z</updated>

		<summary type="html">&lt;p&gt;Jan-eberhardt: /* Figure: Suggested workflow */&lt;/p&gt;
&lt;hr /&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&#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&#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|center|Scheme of a development environment]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note: The extension &#039;&#039;&#039;mod_mylittleextension&#039;&#039;&#039; is a fake plugin, which was created for testing purposes only.&#039;&#039;&#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 &#039;&#039;&#039;superproject&#039;&#039;&#039; repository and the developers&#039; projects will be sometimes referred as &#039;local&#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;
&#039;&#039;&#039;Note: This guide won&#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.&#039;&#039;&#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&#039;t obvious and can be quite surprising.&lt;br /&gt;
&#039;&#039;&#039;Note: Ensure that you&#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.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Assume the plugin &#039;&#039;&#039;mod_mylittleextension&#039;&#039;&#039; (remember: MLE is a fake plugin) was installed in the superproject and these changes have been commited:&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 &#039;mod/mylittleextension&#039; (/local/repositories/mle) registered for path &#039;mod/mylittleextension&#039;&lt;br /&gt;
Cloning into &#039;mod/mylittleextension&#039;...&lt;br /&gt;
done.&lt;br /&gt;
Submodule path &#039;mod/mylittleextension&#039;: checked out &#039;89d9eae3d5142474d8452128e8df5720d89012cd&#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&#039;t be initialized, which means that the submodule&#039;s directory will be empty in the beginning.&lt;br /&gt;
For initializing the submodule, the developer needs to execute &#039;&#039;&#039;git submodule update --init --recursive&#039;&#039;&#039;.&lt;br /&gt;
The &#039;&#039;&#039;--recursive&#039;&#039;&#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 intialization the submodule&#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| Dotted line: information obtained from the superproject, but already saved locally (by pull)]]&lt;br /&gt;
&lt;br /&gt;
This means, &#039;&#039;&#039;git submodule update --init&#039;&#039;&#039; will first do a clone of &#039;&#039;&#039;source url&#039;&#039;&#039; into the &#039;&#039;&#039;path&#039;&#039;&#039; and then check out the &#039;&#039;&#039;reference&#039;&#039;&#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&#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&#039;s hash reference doesn&#039;t change.&lt;br /&gt;
E.g. a checkout of the branch &#039;&#039;&#039;master&#039;&#039;&#039; won&#039;t be noticed by the main repository, but a checkout of &#039;&#039;&#039;dev&#039;&#039;&#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 &#039;dev&#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 &#039;&#039;&#039;git submodule update --init&#039;&#039;&#039; after the clone, you can use &#039;&#039;&#039;git clone&#039;&#039;&#039; with the &#039;&#039;&#039;--recursive&#039;&#039;&#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 &#039;&#039;&#039;git submodule update --init&#039;&#039;&#039; in the case you forget the &#039;&#039;&#039;--recursive&#039;&#039;&#039; option in your &#039;&#039;&#039;git clone&#039;&#039;&#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 it&#039;s 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;
&#039;&#039;&#039;git pull&#039;&#039;&#039; won&#039;t upgrade the submodules at once and an additional command is needed.&lt;br /&gt;
This is what &#039;&#039;&#039;git pull&#039;&#039;&#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, &#039;&#039;&#039;git pull&#039;&#039; triggers &#039;&#039;&#039;git fetch&#039;&#039;&#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 &#039;mod/mylittleextension&#039;: checked out &#039;5e0e66aa787f4ebe9f61a940969a6e94abf01a1e&#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|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 &#039;&#039;&#039;git submodule upgrade&#039;&#039;&#039; checks out the reference, given by your main repository&#039;s commit, your submodule&#039;s repository will turn into detached HEAD state again.&lt;br /&gt;
The command is equivalent to &#039;&#039;&#039;git checkout&#039;&#039;&#039; of the reference inside each submodule&#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&#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&#039;s reference is not known by the origin.&lt;br /&gt;
Your submodule&#039;s directory would be left blank (since there&#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&#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&#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 &#039;&#039;&#039;want to alter&#039;&#039;&#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&#039;t want to merge your pull requests.&lt;br /&gt;
&lt;br /&gt;
As you know from the previous section &#039;&#039;&#039;git submodule update&#039;&#039;&#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&#039;re not the contributer 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|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&#039;re setting up your first superproject, it doesn&#039;t have to be connected to the original repositiory at all, since you&#039;ll get all updates from your fork.&lt;br /&gt;
So instead of adding the extension&#039;s original remote, you may add the fork only (after adding you can use &#039;&#039;&#039;git remote rename origin fork&#039;&#039;&#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&#039;t installed the extension yet, you can add and rename the repository afterwards (to avoid misunderstanding).&lt;br /&gt;
On your superproject&#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 &#039;mod/mylittleextension&#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 &#039;MLE&#039; installed&amp;quot;&lt;br /&gt;
[master adecc96] New extension &#039;MLE&#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 &#039;&#039;&#039;git clone&#039;&#039;&#039; or &#039;&#039;&#039;git pull&#039;&#039;&#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 &#039;&#039;&#039;.gitmodules&#039;&#039;&#039; file.&lt;br /&gt;
Since the &#039;&#039;&#039;path&#039;&#039;&#039; and &#039;&#039;&#039;url&#039;&#039;&#039; of your submodule are saved (&#039;&#039;&#039;reference&#039;&#039;&#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&#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;
&#039;&#039;&#039;or&#039;&#039;&#039; edit the file &#039;&#039;&#039;.gitmodules&#039;&#039;&#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 &#039;mod/mylittleextension&#039;&lt;br /&gt;
$ git commit -a -m &amp;quot;Changed source url of &#039;MLE&#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 &#039;&#039;&#039;sync&#039;&#039;&#039; command will alter the remotes of your submodule&#039;s repository to match the settings of your &#039;&#039;&#039;.gitmodules&#039;&#039;&#039;.&lt;br /&gt;
It is to mention, that changes in the remotes (like &#039;&#039;&#039;rename&#039;&#039;&#039; or &#039;&#039;&#039;add&#039;&#039;&#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&#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 &#039;&#039;&#039;sync&#039;&#039;&#039; command will change the remote settings of the submodule to match them with the &#039;&#039;&#039;.gitmodules&#039;&#039;&#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&#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 seperate branch and merge them only, when it is satisfying.&lt;br /&gt;
For now, we assume the developers can push into your &#039;&#039;&#039;master&#039;&#039;&#039; (or, in general, the branch, which is tracked by your superproject).&lt;br /&gt;
Your developer&#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;
&#039;&#039;&#039;Do not commit the changes.&#039;&#039;&#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;
&#039;&#039;&#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.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Update the superproject with the following commands on the superproject&#039;s machine:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(On the superproject&#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&#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&#039;t need to commit the changed status of the submodule.&lt;br /&gt;
Your developer&#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|The 5th command (&#039;&#039;&#039;git submodule update [--init]&#039;&#039;&#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;
* [[Git for developers guide]]&lt;br /&gt;
* [[Git FAQ]]&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>Jan-eberhardt</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/500/en/index.php?title=File:superprojects4.png&amp;diff=122496</id>
		<title>File:superprojects4.png</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/500/en/index.php?title=File:superprojects4.png&amp;diff=122496"/>
		<updated>2016-03-15T15:24:14Z</updated>

		<summary type="html">&lt;p&gt;Jan-eberhardt: Suggested workflow with customized plugins&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Suggested workflow with customized plugins&lt;/div&gt;</summary>
		<author><name>Jan-eberhardt</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/500/en/index.php?title=Moodle_development_environment_with_Git_submodules&amp;diff=122494</id>
		<title>Moodle development environment with Git submodules</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/500/en/index.php?title=Moodle_development_environment_with_Git_submodules&amp;diff=122494"/>
		<updated>2016-03-15T15:23:48Z</updated>

		<summary type="html">&lt;p&gt;Jan-eberhardt: /* Figure: Updates without customization */&lt;/p&gt;
&lt;hr /&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&#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&#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|center|Scheme of a development environment]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note: The extension &#039;&#039;&#039;mod_mylittleextension&#039;&#039;&#039; is a fake plugin, which was created for testing purposes only.&#039;&#039;&#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 &#039;&#039;&#039;superproject&#039;&#039;&#039; repository and the developers&#039; projects will be sometimes referred as &#039;local&#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;
&#039;&#039;&#039;Note: This guide won&#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.&#039;&#039;&#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&#039;t obvious and can be quite surprising.&lt;br /&gt;
&#039;&#039;&#039;Note: Ensure that you&#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.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Assume the plugin &#039;&#039;&#039;mod_mylittleextension&#039;&#039;&#039; (remember: MLE is a fake plugin) was installed in the superproject and these changes have been commited:&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 &#039;mod/mylittleextension&#039; (/local/repositories/mle) registered for path &#039;mod/mylittleextension&#039;&lt;br /&gt;
Cloning into &#039;mod/mylittleextension&#039;...&lt;br /&gt;
done.&lt;br /&gt;
Submodule path &#039;mod/mylittleextension&#039;: checked out &#039;89d9eae3d5142474d8452128e8df5720d89012cd&#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&#039;t be initialized, which means that the submodule&#039;s directory will be empty in the beginning.&lt;br /&gt;
For initializing the submodule, the developer needs to execute &#039;&#039;&#039;git submodule update --init --recursive&#039;&#039;&#039;.&lt;br /&gt;
The &#039;&#039;&#039;--recursive&#039;&#039;&#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 intialization the submodule&#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| Dotted line: information obtained from the superproject, but already saved locally (by pull)]]&lt;br /&gt;
&lt;br /&gt;
This means, &#039;&#039;&#039;git submodule update --init&#039;&#039;&#039; will first do a clone of &#039;&#039;&#039;source url&#039;&#039;&#039; into the &#039;&#039;&#039;path&#039;&#039;&#039; and then check out the &#039;&#039;&#039;reference&#039;&#039;&#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&#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&#039;s hash reference doesn&#039;t change.&lt;br /&gt;
E.g. a checkout of the branch &#039;&#039;&#039;master&#039;&#039;&#039; won&#039;t be noticed by the main repository, but a checkout of &#039;&#039;&#039;dev&#039;&#039;&#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 &#039;dev&#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 &#039;&#039;&#039;git submodule update --init&#039;&#039;&#039; after the clone, you can use &#039;&#039;&#039;git clone&#039;&#039;&#039; with the &#039;&#039;&#039;--recursive&#039;&#039;&#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 &#039;&#039;&#039;git submodule update --init&#039;&#039;&#039; in the case you forget the &#039;&#039;&#039;--recursive&#039;&#039;&#039; option in your &#039;&#039;&#039;git clone&#039;&#039;&#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 it&#039;s 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;
&#039;&#039;&#039;git pull&#039;&#039;&#039; won&#039;t upgrade the submodules at once and an additional command is needed.&lt;br /&gt;
This is what &#039;&#039;&#039;git pull&#039;&#039;&#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, &#039;&#039;&#039;git pull&#039;&#039; triggers &#039;&#039;&#039;git fetch&#039;&#039;&#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 &#039;mod/mylittleextension&#039;: checked out &#039;5e0e66aa787f4ebe9f61a940969a6e94abf01a1e&#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|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 &#039;&#039;&#039;git submodule upgrade&#039;&#039;&#039; checks out the reference, given by your main repository&#039;s commit, your submodule&#039;s repository will turn into detached HEAD state again.&lt;br /&gt;
The command is equivalent to &#039;&#039;&#039;git checkout&#039;&#039;&#039; of the reference inside each submodule&#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&#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&#039;s reference is not known by the origin.&lt;br /&gt;
Your submodule&#039;s directory would be left blank (since there&#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&#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&#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 &#039;&#039;&#039;want to alter&#039;&#039;&#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&#039;t want to merge your pull requests.&lt;br /&gt;
&lt;br /&gt;
As you know from the previous section &#039;&#039;&#039;git submodule update&#039;&#039;&#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&#039;re not the contributer 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;
[[Image:superprojects4.png|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&#039;re setting up your first superproject, it doesn&#039;t have to be connected to the original repositiory at all, since you&#039;ll get all updates from your fork.&lt;br /&gt;
So instead of adding the extension&#039;s original remote, you may add the fork only (after adding you can use &#039;&#039;&#039;git remote rename origin fork&#039;&#039;&#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&#039;t installed the extension yet, you can add and rename the repository afterwards (to avoid misunderstanding).&lt;br /&gt;
On your superproject&#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 &#039;mod/mylittleextension&#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 &#039;MLE&#039; installed&amp;quot;&lt;br /&gt;
[master adecc96] New extension &#039;MLE&#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 &#039;&#039;&#039;git clone&#039;&#039;&#039; or &#039;&#039;&#039;git pull&#039;&#039;&#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 &#039;&#039;&#039;.gitmodules&#039;&#039;&#039; file.&lt;br /&gt;
Since the &#039;&#039;&#039;path&#039;&#039;&#039; and &#039;&#039;&#039;url&#039;&#039;&#039; of your submodule are saved (&#039;&#039;&#039;reference&#039;&#039;&#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&#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;
&#039;&#039;&#039;or&#039;&#039;&#039; edit the file &#039;&#039;&#039;.gitmodules&#039;&#039;&#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 &#039;mod/mylittleextension&#039;&lt;br /&gt;
$ git commit -a -m &amp;quot;Changed source url of &#039;MLE&#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 &#039;&#039;&#039;sync&#039;&#039;&#039; command will alter the remotes of your submodule&#039;s repository to match the settings of your &#039;&#039;&#039;.gitmodules&#039;&#039;&#039;.&lt;br /&gt;
It is to mention, that changes in the remotes (like &#039;&#039;&#039;rename&#039;&#039;&#039; or &#039;&#039;&#039;add&#039;&#039;&#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&#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 &#039;&#039;&#039;sync&#039;&#039;&#039; command will change the remote settings of the submodule to match them with the &#039;&#039;&#039;.gitmodules&#039;&#039;&#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&#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 seperate branch and merge them only, when it is satisfying.&lt;br /&gt;
For now, we assume the developers can push into your &#039;&#039;&#039;master&#039;&#039;&#039; (or, in general, the branch, which is tracked by your superproject).&lt;br /&gt;
Your developer&#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;
&#039;&#039;&#039;Do not commit the changes.&#039;&#039;&#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;
&#039;&#039;&#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.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Update the superproject with the following commands on the superproject&#039;s machine:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(On the superproject&#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&#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&#039;t need to commit the changed status of the submodule.&lt;br /&gt;
Your developer&#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|The 5th command (&#039;&#039;&#039;git submodule update [--init]&#039;&#039;&#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;
* [[Git for developers guide]]&lt;br /&gt;
* [[Git FAQ]]&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>Jan-eberhardt</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/500/en/index.php?title=File:superprojects3.png&amp;diff=122493</id>
		<title>File:superprojects3.png</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/500/en/index.php?title=File:superprojects3.png&amp;diff=122493"/>
		<updated>2016-03-15T15:23:18Z</updated>

		<summary type="html">&lt;p&gt;Jan-eberhardt: A workflow for an upgrade from the source repository&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;A workflow for an upgrade from the source repository&lt;/div&gt;</summary>
		<author><name>Jan-eberhardt</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/500/en/index.php?title=Moodle_development_environment_with_Git_submodules&amp;diff=122492</id>
		<title>Moodle development environment with Git submodules</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/500/en/index.php?title=Moodle_development_environment_with_Git_submodules&amp;diff=122492"/>
		<updated>2016-03-15T15:22:42Z</updated>

		<summary type="html">&lt;p&gt;Jan-eberhardt: &lt;/p&gt;
&lt;hr /&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&#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&#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|center|Scheme of a development environment]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note: The extension &#039;&#039;&#039;mod_mylittleextension&#039;&#039;&#039; is a fake plugin, which was created for testing purposes only.&#039;&#039;&#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 &#039;&#039;&#039;superproject&#039;&#039;&#039; repository and the developers&#039; projects will be sometimes referred as &#039;local&#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;
&#039;&#039;&#039;Note: This guide won&#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.&#039;&#039;&#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&#039;t obvious and can be quite surprising.&lt;br /&gt;
&#039;&#039;&#039;Note: Ensure that you&#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.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Assume the plugin &#039;&#039;&#039;mod_mylittleextension&#039;&#039;&#039; (remember: MLE is a fake plugin) was installed in the superproject and these changes have been commited:&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 &#039;mod/mylittleextension&#039; (/local/repositories/mle) registered for path &#039;mod/mylittleextension&#039;&lt;br /&gt;
Cloning into &#039;mod/mylittleextension&#039;...&lt;br /&gt;
done.&lt;br /&gt;
Submodule path &#039;mod/mylittleextension&#039;: checked out &#039;89d9eae3d5142474d8452128e8df5720d89012cd&#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&#039;t be initialized, which means that the submodule&#039;s directory will be empty in the beginning.&lt;br /&gt;
For initializing the submodule, the developer needs to execute &#039;&#039;&#039;git submodule update --init --recursive&#039;&#039;&#039;.&lt;br /&gt;
The &#039;&#039;&#039;--recursive&#039;&#039;&#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 intialization the submodule&#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| Dotted line: information obtained from the superproject, but already saved locally (by pull)]]&lt;br /&gt;
&lt;br /&gt;
This means, &#039;&#039;&#039;git submodule update --init&#039;&#039;&#039; will first do a clone of &#039;&#039;&#039;source url&#039;&#039;&#039; into the &#039;&#039;&#039;path&#039;&#039;&#039; and then check out the &#039;&#039;&#039;reference&#039;&#039;&#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&#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&#039;s hash reference doesn&#039;t change.&lt;br /&gt;
E.g. a checkout of the branch &#039;&#039;&#039;master&#039;&#039;&#039; won&#039;t be noticed by the main repository, but a checkout of &#039;&#039;&#039;dev&#039;&#039;&#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 &#039;dev&#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 &#039;&#039;&#039;git submodule update --init&#039;&#039;&#039; after the clone, you can use &#039;&#039;&#039;git clone&#039;&#039;&#039; with the &#039;&#039;&#039;--recursive&#039;&#039;&#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 &#039;&#039;&#039;git submodule update --init&#039;&#039;&#039; in the case you forget the &#039;&#039;&#039;--recursive&#039;&#039;&#039; option in your &#039;&#039;&#039;git clone&#039;&#039;&#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 it&#039;s 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;
&#039;&#039;&#039;git pull&#039;&#039;&#039; won&#039;t upgrade the submodules at once and an additional command is needed.&lt;br /&gt;
This is what &#039;&#039;&#039;git pull&#039;&#039;&#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, &#039;&#039;&#039;git pull&#039;&#039; triggers &#039;&#039;&#039;git fetch&#039;&#039;&#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 &#039;mod/mylittleextension&#039;: checked out &#039;5e0e66aa787f4ebe9f61a940969a6e94abf01a1e&#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;
[[Image:superprojects3.png|A workflow for an upgrade from the source repository]]&lt;br /&gt;
&lt;br /&gt;
=== Known issues ===&lt;br /&gt;
&lt;br /&gt;
Since &#039;&#039;&#039;git submodule upgrade&#039;&#039;&#039; checks out the reference, given by your main repository&#039;s commit, your submodule&#039;s repository will turn into detached HEAD state again.&lt;br /&gt;
The command is equivalent to &#039;&#039;&#039;git checkout&#039;&#039;&#039; of the reference inside each submodule&#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&#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&#039;s reference is not known by the origin.&lt;br /&gt;
Your submodule&#039;s directory would be left blank (since there&#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&#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&#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 &#039;&#039;&#039;want to alter&#039;&#039;&#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&#039;t want to merge your pull requests.&lt;br /&gt;
&lt;br /&gt;
As you know from the previous section &#039;&#039;&#039;git submodule update&#039;&#039;&#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&#039;re not the contributer 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;
[[Image:superprojects4.png|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&#039;re setting up your first superproject, it doesn&#039;t have to be connected to the original repositiory at all, since you&#039;ll get all updates from your fork.&lt;br /&gt;
So instead of adding the extension&#039;s original remote, you may add the fork only (after adding you can use &#039;&#039;&#039;git remote rename origin fork&#039;&#039;&#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&#039;t installed the extension yet, you can add and rename the repository afterwards (to avoid misunderstanding).&lt;br /&gt;
On your superproject&#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 &#039;mod/mylittleextension&#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 &#039;MLE&#039; installed&amp;quot;&lt;br /&gt;
[master adecc96] New extension &#039;MLE&#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 &#039;&#039;&#039;git clone&#039;&#039;&#039; or &#039;&#039;&#039;git pull&#039;&#039;&#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 &#039;&#039;&#039;.gitmodules&#039;&#039;&#039; file.&lt;br /&gt;
Since the &#039;&#039;&#039;path&#039;&#039;&#039; and &#039;&#039;&#039;url&#039;&#039;&#039; of your submodule are saved (&#039;&#039;&#039;reference&#039;&#039;&#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&#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;
&#039;&#039;&#039;or&#039;&#039;&#039; edit the file &#039;&#039;&#039;.gitmodules&#039;&#039;&#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 &#039;mod/mylittleextension&#039;&lt;br /&gt;
$ git commit -a -m &amp;quot;Changed source url of &#039;MLE&#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 &#039;&#039;&#039;sync&#039;&#039;&#039; command will alter the remotes of your submodule&#039;s repository to match the settings of your &#039;&#039;&#039;.gitmodules&#039;&#039;&#039;.&lt;br /&gt;
It is to mention, that changes in the remotes (like &#039;&#039;&#039;rename&#039;&#039;&#039; or &#039;&#039;&#039;add&#039;&#039;&#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&#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 &#039;&#039;&#039;sync&#039;&#039;&#039; command will change the remote settings of the submodule to match them with the &#039;&#039;&#039;.gitmodules&#039;&#039;&#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&#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 seperate branch and merge them only, when it is satisfying.&lt;br /&gt;
For now, we assume the developers can push into your &#039;&#039;&#039;master&#039;&#039;&#039; (or, in general, the branch, which is tracked by your superproject).&lt;br /&gt;
Your developer&#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;
&#039;&#039;&#039;Do not commit the changes.&#039;&#039;&#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;
&#039;&#039;&#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.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Update the superproject with the following commands on the superproject&#039;s machine:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(On the superproject&#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&#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&#039;t need to commit the changed status of the submodule.&lt;br /&gt;
Your developer&#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|The 5th command (&#039;&#039;&#039;git submodule update [--init]&#039;&#039;&#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;
* [[Git for developers guide]]&lt;br /&gt;
* [[Git FAQ]]&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>Jan-eberhardt</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/500/en/index.php?title=File:superprojects2.png&amp;diff=122491</id>
		<title>File:superprojects2.png</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/500/en/index.php?title=File:superprojects2.png&amp;diff=122491"/>
		<updated>2016-03-15T15:21:27Z</updated>

		<summary type="html">&lt;p&gt;Jan-eberhardt: Dotted line: information obtained from the superproject, but already saved locally (by pull)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Dotted line: information obtained from the superproject, but already saved locally (by pull)&lt;/div&gt;</summary>
		<author><name>Jan-eberhardt</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/500/en/index.php?title=Moodle_development_environment_with_Git_submodules&amp;diff=122490</id>
		<title>Moodle development environment with Git submodules</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/500/en/index.php?title=Moodle_development_environment_with_Git_submodules&amp;diff=122490"/>
		<updated>2016-03-15T15:18:53Z</updated>

		<summary type="html">&lt;p&gt;Jan-eberhardt: &lt;/p&gt;
&lt;hr /&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&#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&#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|center|Scheme of a development environment]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note: The extension &#039;&#039;&#039;mod_mylittleextension&#039;&#039;&#039; is a fake plugin, which was created for testing purposes only.&#039;&#039;&#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 &#039;&#039;&#039;superproject&#039;&#039;&#039; repository and the developers&#039; projects will be sometimes referred as &#039;local&#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;
&#039;&#039;&#039;Note: This guide won&#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.&#039;&#039;&#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&#039;t obvious and can be quite surprising.&lt;br /&gt;
&#039;&#039;&#039;Note: Ensure that you&#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.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Assume the plugin &#039;&#039;&#039;mod_mylittleextension&#039;&#039;&#039; (remember: MLE is a fake plugin) was installed in the superproject and these changes have been commited:&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 &#039;mod/mylittleextension&#039; (/local/repositories/mle) registered for path &#039;mod/mylittleextension&#039;&lt;br /&gt;
Cloning into &#039;mod/mylittleextension&#039;...&lt;br /&gt;
done.&lt;br /&gt;
Submodule path &#039;mod/mylittleextension&#039;: checked out &#039;89d9eae3d5142474d8452128e8df5720d89012cd&#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&#039;t be initialized, which means that the submodule&#039;s directory will be empty in the beginning.&lt;br /&gt;
For initializing the submodule, the developer needs to execute &#039;&#039;&#039;git submodule update --init --recursive&#039;&#039;&#039;.&lt;br /&gt;
The &#039;&#039;&#039;--recursive&#039;&#039;&#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 intialization the submodule&#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;
[[File:superprojects2.png| Dotted line: information obtained from the superproject, but already saved locally (by pull)]]&lt;br /&gt;
&lt;br /&gt;
This means, &#039;&#039;&#039;git submodule update --init&#039;&#039;&#039; will first do a clone of &#039;&#039;&#039;source url&#039;&#039;&#039; into the &#039;&#039;&#039;path&#039;&#039;&#039; and then check out the &#039;&#039;&#039;reference&#039;&#039;&#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&#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&#039;s hash reference doesn&#039;t change.&lt;br /&gt;
E.g. a checkout of the branch &#039;&#039;&#039;master&#039;&#039;&#039; won&#039;t be noticed by the main repository, but a checkout of &#039;&#039;&#039;dev&#039;&#039;&#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 &#039;dev&#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 &#039;&#039;&#039;git submodule update --init&#039;&#039;&#039; after the clone, you can use &#039;&#039;&#039;git clone&#039;&#039;&#039; with the &#039;&#039;&#039;--recursive&#039;&#039;&#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 &#039;&#039;&#039;git submodule update --init&#039;&#039;&#039; in the case you forget the &#039;&#039;&#039;--recursive&#039;&#039;&#039; option in your &#039;&#039;&#039;git clone&#039;&#039;&#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 it&#039;s 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;
&#039;&#039;&#039;git pull&#039;&#039;&#039; won&#039;t upgrade the submodules at once and an additional command is needed.&lt;br /&gt;
This is what &#039;&#039;&#039;git pull&#039;&#039;&#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, &#039;&#039;&#039;git pull&#039;&#039; triggers &#039;&#039;&#039;git fetch&#039;&#039;&#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 &#039;mod/mylittleextension&#039;: checked out &#039;5e0e66aa787f4ebe9f61a940969a6e94abf01a1e&#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|A workflow for an upgrade from the source repository]]&lt;br /&gt;
&lt;br /&gt;
=== Known issues ===&lt;br /&gt;
&lt;br /&gt;
Since &#039;&#039;&#039;git submodule upgrade&#039;&#039;&#039; checks out the reference, given by your main repository&#039;s commit, your submodule&#039;s repository will turn into detached HEAD state again.&lt;br /&gt;
The command is equivalent to &#039;&#039;&#039;git checkout&#039;&#039;&#039; of the reference inside each submodule&#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&#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&#039;s reference is not known by the origin.&lt;br /&gt;
Your submodule&#039;s directory would be left blank (since there&#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&#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&#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 &#039;&#039;&#039;want to alter&#039;&#039;&#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&#039;t want to merge your pull requests.&lt;br /&gt;
&lt;br /&gt;
As you know from the previous section &#039;&#039;&#039;git submodule update&#039;&#039;&#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&#039;re not the contributer 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|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&#039;re setting up your first superproject, it doesn&#039;t have to be connected to the original repositiory at all, since you&#039;ll get all updates from your fork.&lt;br /&gt;
So instead of adding the extension&#039;s original remote, you may add the fork only (after adding you can use &#039;&#039;&#039;git remote rename origin fork&#039;&#039;&#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&#039;t installed the extension yet, you can add and rename the repository afterwards (to avoid misunderstanding).&lt;br /&gt;
On your superproject&#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 &#039;mod/mylittleextension&#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 &#039;MLE&#039; installed&amp;quot;&lt;br /&gt;
[master adecc96] New extension &#039;MLE&#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 &#039;&#039;&#039;git clone&#039;&#039;&#039; or &#039;&#039;&#039;git pull&#039;&#039;&#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 &#039;&#039;&#039;.gitmodules&#039;&#039;&#039; file.&lt;br /&gt;
Since the &#039;&#039;&#039;path&#039;&#039;&#039; and &#039;&#039;&#039;url&#039;&#039;&#039; of your submodule are saved (&#039;&#039;&#039;reference&#039;&#039;&#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&#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;
&#039;&#039;&#039;or&#039;&#039;&#039; edit the file &#039;&#039;&#039;.gitmodules&#039;&#039;&#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 &#039;mod/mylittleextension&#039;&lt;br /&gt;
$ git commit -a -m &amp;quot;Changed source url of &#039;MLE&#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 &#039;&#039;&#039;sync&#039;&#039;&#039; command will alter the remotes of your submodule&#039;s repository to match the settings of your &#039;&#039;&#039;.gitmodules&#039;&#039;&#039;.&lt;br /&gt;
It is to mention, that changes in the remotes (like &#039;&#039;&#039;rename&#039;&#039;&#039; or &#039;&#039;&#039;add&#039;&#039;&#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&#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 &#039;&#039;&#039;sync&#039;&#039;&#039; command will change the remote settings of the submodule to match them with the &#039;&#039;&#039;.gitmodules&#039;&#039;&#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&#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 seperate branch and merge them only, when it is satisfying.&lt;br /&gt;
For now, we assume the developers can push into your &#039;&#039;&#039;master&#039;&#039;&#039; (or, in general, the branch, which is tracked by your superproject).&lt;br /&gt;
Your developer&#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;
&#039;&#039;&#039;Do not commit the changes.&#039;&#039;&#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;
&#039;&#039;&#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.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Update the superproject with the following commands on the superproject&#039;s machine:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(On the superproject&#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&#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&#039;t need to commit the changed status of the submodule.&lt;br /&gt;
Your developer&#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;
[[File:superprojects5.png|The 5th command (&#039;&#039;&#039;git submodule update [--init]&#039;&#039;&#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;
* [[Git for developers guide]]&lt;br /&gt;
* [[Git FAQ]]&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>Jan-eberhardt</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/500/en/index.php?title=File:superprojects1.png&amp;diff=122489</id>
		<title>File:superprojects1.png</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/500/en/index.php?title=File:superprojects1.png&amp;diff=122489"/>
		<updated>2016-03-15T15:17:13Z</updated>

		<summary type="html">&lt;p&gt;Jan-eberhardt: Scheme of a development environment&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Scheme of a development environment&lt;/div&gt;</summary>
		<author><name>Jan-eberhardt</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/500/en/index.php?title=Moodle_development_environment_with_Git_submodules&amp;diff=122488</id>
		<title>Moodle development environment with Git submodules</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/500/en/index.php?title=Moodle_development_environment_with_Git_submodules&amp;diff=122488"/>
		<updated>2016-03-15T15:15:00Z</updated>

		<summary type="html">&lt;p&gt;Jan-eberhardt: Created page with &amp;quot;This page describes how to set up a development environment for a Moodle instance with external plugins. Over time the number of plugins may increase in such a way, that they...&amp;quot;&lt;/p&gt;
&lt;hr /&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&#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&#039;ll learn in this guide how to use Git submodules in order to achieve the following setup:&lt;br /&gt;
&lt;br /&gt;
[[File:superprojects1.png|center|Scheme of a development environment]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note: The extension &#039;&#039;&#039;mod_mylittleextension&#039;&#039;&#039; is a fake plugin, which was created for testing purposes only.&#039;&#039;&#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 &#039;&#039;&#039;superproject&#039;&#039;&#039; repository and the developers&#039; projects will be sometimes referred as &#039;local&#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;
&#039;&#039;&#039;Note: This guide won&#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.&#039;&#039;&#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&#039;t obvious and can be quite surprising.&lt;br /&gt;
&#039;&#039;&#039;Note: Ensure that you&#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.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Assume the plugin &#039;&#039;&#039;mod_mylittleextension&#039;&#039;&#039; (remember: MLE is a fake plugin) was installed in the superproject and these changes have been commited:&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 &#039;mod/mylittleextension&#039; (/local/repositories/mle) registered for path &#039;mod/mylittleextension&#039;&lt;br /&gt;
Cloning into &#039;mod/mylittleextension&#039;...&lt;br /&gt;
done.&lt;br /&gt;
Submodule path &#039;mod/mylittleextension&#039;: checked out &#039;89d9eae3d5142474d8452128e8df5720d89012cd&#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&#039;t be initialized, which means that the submodule&#039;s directory will be empty in the beginning.&lt;br /&gt;
For initializing the submodule, the developer needs to execute &#039;&#039;&#039;git submodule update --init --recursive&#039;&#039;&#039;.&lt;br /&gt;
The &#039;&#039;&#039;--recursive&#039;&#039;&#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 intialization the submodule&#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;
[[File:superprojects2.png| Dotted line: information obtained from the superproject, but already saved locally (by pull)]]&lt;br /&gt;
&lt;br /&gt;
This means, &#039;&#039;&#039;git submodule update --init&#039;&#039;&#039; will first do a clone of &#039;&#039;&#039;source url&#039;&#039;&#039; into the &#039;&#039;&#039;path&#039;&#039;&#039; and then check out the &#039;&#039;&#039;reference&#039;&#039;&#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&#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&#039;s hash reference doesn&#039;t change.&lt;br /&gt;
E.g. a checkout of the branch &#039;&#039;&#039;master&#039;&#039;&#039; won&#039;t be noticed by the main repository, but a checkout of &#039;&#039;&#039;dev&#039;&#039;&#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 &#039;dev&#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 &#039;&#039;&#039;git submodule update --init&#039;&#039;&#039; after the clone, you can use &#039;&#039;&#039;git clone&#039;&#039;&#039; with the &#039;&#039;&#039;--recursive&#039;&#039;&#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 &#039;&#039;&#039;git submodule update --init&#039;&#039;&#039; in the case you forget the &#039;&#039;&#039;--recursive&#039;&#039;&#039; option in your &#039;&#039;&#039;git clone&#039;&#039;&#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 it&#039;s 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;
&#039;&#039;&#039;git pull&#039;&#039;&#039; won&#039;t upgrade the submodules at once and an additional command is needed.&lt;br /&gt;
This is what &#039;&#039;&#039;git pull&#039;&#039;&#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, &#039;&#039;&#039;git pull&#039;&#039; triggers &#039;&#039;&#039;git fetch&#039;&#039;&#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 &#039;mod/mylittleextension&#039;: checked out &#039;5e0e66aa787f4ebe9f61a940969a6e94abf01a1e&#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|A workflow for an upgrade from the source repository]]&lt;br /&gt;
&lt;br /&gt;
=== Known issues ===&lt;br /&gt;
&lt;br /&gt;
Since &#039;&#039;&#039;git submodule upgrade&#039;&#039;&#039; checks out the reference, given by your main repository&#039;s commit, your submodule&#039;s repository will turn into detached HEAD state again.&lt;br /&gt;
The command is equivalent to &#039;&#039;&#039;git checkout&#039;&#039;&#039; of the reference inside each submodule&#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&#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&#039;s reference is not known by the origin.&lt;br /&gt;
Your submodule&#039;s directory would be left blank (since there&#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&#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&#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 &#039;&#039;&#039;want to alter&#039;&#039;&#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&#039;t want to merge your pull requests.&lt;br /&gt;
&lt;br /&gt;
As you know from the previous section &#039;&#039;&#039;git submodule update&#039;&#039;&#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&#039;re not the contributer 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|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&#039;re setting up your first superproject, it doesn&#039;t have to be connected to the original repositiory at all, since you&#039;ll get all updates from your fork.&lt;br /&gt;
So instead of adding the extension&#039;s original remote, you may add the fork only (after adding you can use &#039;&#039;&#039;git remote rename origin fork&#039;&#039;&#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&#039;t installed the extension yet, you can add and rename the repository afterwards (to avoid misunderstanding).&lt;br /&gt;
On your superproject&#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 &#039;mod/mylittleextension&#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 &#039;MLE&#039; installed&amp;quot;&lt;br /&gt;
[master adecc96] New extension &#039;MLE&#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 &#039;&#039;&#039;git clone&#039;&#039;&#039; or &#039;&#039;&#039;git pull&#039;&#039;&#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 &#039;&#039;&#039;.gitmodules&#039;&#039;&#039; file.&lt;br /&gt;
Since the &#039;&#039;&#039;path&#039;&#039;&#039; and &#039;&#039;&#039;url&#039;&#039;&#039; of your submodule are saved (&#039;&#039;&#039;reference&#039;&#039;&#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&#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;
&#039;&#039;&#039;or&#039;&#039;&#039; edit the file &#039;&#039;&#039;.gitmodules&#039;&#039;&#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 &#039;mod/mylittleextension&#039;&lt;br /&gt;
$ git commit -a -m &amp;quot;Changed source url of &#039;MLE&#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 &#039;&#039;&#039;sync&#039;&#039;&#039; command will alter the remotes of your submodule&#039;s repository to match the settings of your &#039;&#039;&#039;.gitmodules&#039;&#039;&#039;.&lt;br /&gt;
It is to mention, that changes in the remotes (like &#039;&#039;&#039;rename&#039;&#039;&#039; or &#039;&#039;&#039;add&#039;&#039;&#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&#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 &#039;&#039;&#039;sync&#039;&#039;&#039; command will change the remote settings of the submodule to match them with the &#039;&#039;&#039;.gitmodules&#039;&#039;&#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&#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 seperate branch and merge them only, when it is satisfying.&lt;br /&gt;
For now, we assume the developers can push into your &#039;&#039;&#039;master&#039;&#039;&#039; (or, in general, the branch, which is tracked by your superproject).&lt;br /&gt;
Your developer&#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;
&#039;&#039;&#039;Do not commit the changes.&#039;&#039;&#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;
&#039;&#039;&#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.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Update the superproject with the following commands on the superproject&#039;s machine:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(On the superproject&#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&#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&#039;t need to commit the changed status of the submodule.&lt;br /&gt;
Your developer&#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;
[[File:superprojects5.png|The 5th command (&#039;&#039;&#039;git submodule update [--init]&#039;&#039;&#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;
* [[Git for developers guide]]&lt;br /&gt;
* [[Git FAQ]]&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>Jan-eberhardt</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/500/en/index.php?title=Git_for_Administrators&amp;diff=122487</id>
		<title>Git for Administrators</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/500/en/index.php?title=Git_for_Administrators&amp;diff=122487"/>
		<updated>2016-03-15T15:11:56Z</updated>

		<summary type="html">&lt;p&gt;Jan-eberhardt: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Installing Moodle}}&lt;br /&gt;
This page describes how to maintain a copy of Moodle on your production server which can easily be upgraded using Git. If you have customisations of Moodle core code, you are advised to follow the instructions in the [[:dev:Git for developers|Git for developers guide]].&lt;br /&gt;
&lt;br /&gt;
To get the most of Git it is worth making the effort to understand its basic concepts - see the section below. It can be a bit of a steep learning curve, especially if you are used to CVS or Subversion. &lt;br /&gt;
&lt;br /&gt;
== Getting hold of Git (Windows, OSX, Linux and others) ==&lt;br /&gt;
&lt;br /&gt;
Support for Git was, up until recently, mostly confined to Linux but builds are now available for most popular operating systems:&lt;br /&gt;
&lt;br /&gt;
* List of downloads from Git site - http://git-scm.com/download&lt;br /&gt;
&lt;br /&gt;
Once you have downloaded and installed your OS relevant git installation, the git commands in this document should work with your operating system.&lt;br /&gt;
&lt;br /&gt;
== Obtaining the code from Git ==&lt;br /&gt;
&lt;br /&gt;
The command line version of Git is discussed here. Graphical clients are little more than wrappers around the command line version, so you should be able to deduce the correct parameters quite easily. &lt;br /&gt;
&lt;br /&gt;
You can find the official Moodle git repository at git://git.moodle.org/moodle.git (with an official clone at git://github.com/moodle/moodle.git). To initialize your local checkout, use&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cd /path/to/your/webroot&lt;br /&gt;
$ git clone git://git.moodle.org/moodle.git                       (1)&lt;br /&gt;
$ cd moodle&lt;br /&gt;
$ git branch -a                                                   (2)&lt;br /&gt;
$ git branch --track MOODLE_30_STABLE origin/MOODLE_30_STABLE     (3)&lt;br /&gt;
$ git checkout MOODLE_30_STABLE                                   (4)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* The command (1) initializes the new local repository as a clone of the &#039;upstream&#039; (i.e. the remote server based) moodle.git repository. The upstream repository is called &#039;origin&#039; by default. It creates a new directory named &#039;&#039;moodle&#039;&#039;, where it downloads all the files. This operation can take a while as it is actually getting the entire history of all Moodle versions&lt;br /&gt;
* The command (2) lists all available branches.&lt;br /&gt;
* Use the command (3) to create a new local branch called MOODLE_30_STABLE and set it to track the remote branch MOODLE_30_STABLE from the upstream repository.&lt;br /&gt;
* The command (4) actually switches to the newly created local branch. &lt;br /&gt;
&lt;br /&gt;
Note that Git has a huge number of options for each command and it&#039;s actually possible to do the above process with a single command (left as an exercise!!).&lt;br /&gt;
&lt;br /&gt;
==Git from behind a firewall==&lt;br /&gt;
&lt;br /&gt;
Git uses a read-only protocol that may be blocked by your firewall (port 9418). If this is a problem, you can use Github&#039;s http version &amp;lt;nowiki&amp;gt;https://github.com/moodle/moodle.git&amp;lt;/nowiki&amp;gt;. It&#039;s a bit slower, so use the Git protocol if you can.&lt;br /&gt;
&lt;br /&gt;
== Updating your installation ==&lt;br /&gt;
&lt;br /&gt;
The Moodle development team performs integration and testing of fixed bugs every Monday and Tuesday. On Wednesday you can install all patches by updating your code. Check the [http://git.moodle.org/gw?p=moodle.git;a=summary shortlog] to see if the official repository has been already updated or not.&lt;br /&gt;
&lt;br /&gt;
To update your code to the latest version (on the MOODLE_30_STABLE branch) &#039;&#039;&#039;all&#039;&#039;&#039; you have to do is:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cd /path/to/your/moodle/&lt;br /&gt;
$ git pull&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If this is a production site you should still consider the [[Upgrade]] instructions (e.g. take backups).&lt;br /&gt;
&lt;br /&gt;
== Installing a contributed extension from its Git repository ==&lt;br /&gt;
&lt;br /&gt;
This is one way to handle adding plugins from other Git repositories into your Moodle repository. Another way is to use Git Submodules. However, at the time of writing, this is one of Git&#039;s rougher features and should be regarded as an advanced option. &lt;br /&gt;
&lt;br /&gt;
For example, let us say we want to install the [[Certificate module]] from its Git repository into our Moodle 3.0.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cd /path/to/your/moodle/&lt;br /&gt;
$ cd mod                                                          (1)&lt;br /&gt;
$ git clone https://github.com/markn86/moodle-mod_certificate.git certificate     (2)&lt;br /&gt;
$ cd certificate&lt;br /&gt;
$ git checkout -b MOODLE_30_STABLE origin/MOODLE_30_STABLE        (3)&lt;br /&gt;
$ git branch -d master                                            (4)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The command (1) changes the current directory into the &#039;&#039;mod&#039;&#039; folder of your local Moodle clone. The command (2) creates a new subdirectory &#039;&#039;certificate&#039;&#039; and makes a local clone of vanilla Certificate repository. The command (3) creates a new local branch that will track the remote branch with a Certificate version for Moodle 3.0. The command (4) deletes the &#039;&#039;master&#039;&#039; that was created automatically by git-clone in (2) as we do not want it in this production checkout.&lt;br /&gt;
&lt;br /&gt;
Note: you should check first the compatibility of a module with your Moodle branch by asking directly to the Maintainer before cloning the repo or - if you want to guess it - by issuing the command below before running the command (3), in order to verify what is available among the branches:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ git branch -a&lt;br /&gt;
* master&lt;br /&gt;
  remotes/origin/HEAD -&amp;gt; origin/master&lt;br /&gt;
  remotes/origin/MOODLE_20_STABLE&lt;br /&gt;
  remotes/origin/MOODLE_21_STABLE&lt;br /&gt;
  remotes/origin/MOODLE_22_STABLE&lt;br /&gt;
  remotes/origin/MOODLE_23_STABLE&lt;br /&gt;
  remotes/origin/MOODLE_24_STABLE&lt;br /&gt;
  remotes/origin/MOODLE_25_STABLE&lt;br /&gt;
  remotes/origin/MOODLE_26_STABLE&lt;br /&gt;
  remotes/origin/MOODLE_27_STABLE&lt;br /&gt;
  remotes/origin/MOODLE_28_STABLE&lt;br /&gt;
  remotes/origin/MOODLE_29_STABLE&lt;br /&gt;
  remotes/origin/MOODLE_30_STABLE&lt;br /&gt;
  remotes/origin/master&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This will avoid an error message when you issue the command (3) against a nonexistent branch, e.g.:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
§ git checkout -b MOODLE_30_STABLE origin/MOODLE_30_STABLE&lt;br /&gt;
fatal: git checkout: updating paths is incompatible with switching branches.&lt;br /&gt;
Did you intend to checkout &#039;origin/MOODLE_30_STABLE&#039; which can not be resolved as commit?&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now it is wise to add the new directory mod/certificate/ to the list of ignored files of the main Moodle clone, otherwise a status of the main clone will keep reminding you that the new code has not been checked in.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cd /path/to/your/moodle/&lt;br /&gt;
$ echo /mod/certificate/ &amp;gt;&amp;gt; .git/info/exclude&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
To update your Moodle installation now, you must visit both Git repositories and pull changes from upstream.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cd /path/to/your/moodle/&lt;br /&gt;
$ git pull&lt;br /&gt;
$ cd mod/certificate&lt;br /&gt;
$ git pull&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Writing a shell script with these lines in the root of Moodle installation is a very good idea. Otherwise it is easy to forget what Git repositories are there within the main Moodle repository.&lt;br /&gt;
&lt;br /&gt;
== Installing and maintaining contributed extensions using Git submodules ==&lt;br /&gt;
&lt;br /&gt;
As it was said in the previous section, this is for advanced users only.&lt;br /&gt;
Therefore it is necessary, that you have some experience with Git and its commands.&lt;br /&gt;
A step-by-step explanation will be provided, but in order to follow these steps it is helpful to understand, what these commands do.&lt;br /&gt;
&lt;br /&gt;
Advanced options and commands can be found at [[https://git-scm.com/book/en/v2/Git-Tools-Submodules|the Git book]].&lt;br /&gt;
If you have any questions about Git submodules, please visit the site above first.&lt;br /&gt;
&lt;br /&gt;
=== Installing a new extension into an existing Moodle ===&lt;br /&gt;
&lt;br /&gt;
As an example we use the [[Certificate module]] from the previous section.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cd /path/to/your/moodle&lt;br /&gt;
$ git submodule add https://github.com/markn86/moodle-mod_certificate.git mod/certificate&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note, that Git is reporting two new files in the repository:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ git status&lt;br /&gt;
# On branch MOODLE_29_STABLE&lt;br /&gt;
# Changes to be committed:&lt;br /&gt;
#   (use &amp;quot;git reset HEAD &amp;lt;file&amp;gt;...&amp;quot; to unstage)&lt;br /&gt;
#&lt;br /&gt;
#	new file:   .gitmodules&lt;br /&gt;
#	new file:   mod/certificate&lt;br /&gt;
#&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The file &#039;&#039;&#039;.gitmodules&#039;&#039;&#039; contains the local path and url of all your submodules.&lt;br /&gt;
It has to be commited, if you intend to clone the repository later (see the page [[Moodle development environment with Git submodules]]).&lt;br /&gt;
Before commiting, make sure to check the configuration of the plugin&#039;s Git repository, since the automatically generated settings may be not sufficient.&lt;br /&gt;
For future updates it is helpful, to track the remote branch, which corresponds to the Moodle version of your repository.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cd mod/certificate&lt;br /&gt;
$ git branch -avv&lt;br /&gt;
* master                          345f5b1 [origin/master] Replaced deprecated function&lt;br /&gt;
  remotes/origin/HEAD             -&amp;gt; origin/master&lt;br /&gt;
  remotes/origin/MOODLE_20_STABLE 1aa1040 Added option to print &#039;grade category&#039; grade&lt;br /&gt;
  remotes/origin/MOODLE_21_STABLE 1aa1040 Added option to print &#039;grade category&#039; grade&lt;br /&gt;
  remotes/origin/MOODLE_22_STABLE 1aa1040 Added option to print &#039;grade category&#039; grade&lt;br /&gt;
  remotes/origin/MOODLE_23_STABLE fe047de Check that the function exists rather than relying on the Moodle version&lt;br /&gt;
  remotes/origin/MOODLE_24_STABLE 1051f7d CONTRIB-4892 Fixed the email to others functionality&lt;br /&gt;
  remotes/origin/MOODLE_25_STABLE cdb221a CONTRIB-4946: Removed character from language file breaking AMOS&lt;br /&gt;
  remotes/origin/MOODLE_26_STABLE 696802a Increased version&lt;br /&gt;
  remotes/origin/MOODLE_27_STABLE d3c0379 Increased version&lt;br /&gt;
  remotes/origin/MOODLE_28_STABLE fa8df83 Increased version&lt;br /&gt;
  remotes/origin/MOODLE_29_STABLE 3f03740 Replaced deprecated function&lt;br /&gt;
  remotes/origin/master           345f5b1 Replaced deprecated function&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Git created the branch &#039;&#039;&#039;master&#039;&#039;&#039; which tracks &#039;&#039;&#039;origin/master&#039;&#039;&#039; automatically, because the remote repository has checked out &#039;&#039;&#039;master&#039;&#039;&#039;.&lt;br /&gt;
Therefore, create a new branch, which tracks the appropriate remote branch.&lt;br /&gt;
Of course, this is only possible, if the remote repository offers those branches. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ git checkout -b MOODLE_29_STABLE origin/MOODLE_29_STABLE&lt;br /&gt;
Branch MOODLE_29_STABLE set up to track remote branch MOODLE_29_STABLE from origin.&lt;br /&gt;
Switched to a new branch &#039;MOODLE_29_STABLE&#039;&lt;br /&gt;
$ git branch -D master&lt;br /&gt;
Deleted branch master (was 345f5b1).&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
It is not necessary to delete the &#039;&#039;&#039;master&#039;&#039;&#039; branch, but it&#039;s useless to keep it.&lt;br /&gt;
In fact, these settings don&#039;t need to be touched afterwards.&lt;br /&gt;
&lt;br /&gt;
The final step is to commit the changes to the main repository.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cd /path/to/your/moodle&lt;br /&gt;
$ git commit -a -m &amp;quot;New extension mod_certificate installed&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It has to be ensured, that the commit includes only the changes for the new Git submodule (since &#039;&#039;&#039;-a&#039;&#039;&#039; commits all non-staged changes).&lt;br /&gt;
&lt;br /&gt;
=== Maintaining Git submodules ===&lt;br /&gt;
&lt;br /&gt;
Maintaining a set of submodules is extremly easy.&lt;br /&gt;
Consider a Moodle repository with several submodules installed.&lt;br /&gt;
Keep in mind, that the extension &#039;&#039;&#039;mod_mylittleextension&#039;&#039;&#039; is a fake plugin, created for a test scenario in this example.&lt;br /&gt;
It is not an official Moodle module. For updating all your submodules at once, type in:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cd /path/to/your/moodle&lt;br /&gt;
$ git submodule foreach git pull&lt;br /&gt;
Entering &#039;block/coursefeedback&#039;&lt;br /&gt;
Already up-to-date.&lt;br /&gt;
Entering &#039;mod/certificate&#039;&lt;br /&gt;
Already up-to-date.&lt;br /&gt;
Entering &#039;mod/mylittleextension&#039;&lt;br /&gt;
remote: Counting objects: 6, done.&lt;br /&gt;
remote: Compressing objects: 100% (4/4), done.&lt;br /&gt;
remote: Total 4 (delta 0), reused 0 (delta 0)&lt;br /&gt;
Unpacking objects: 100% (4/4), done.&lt;br /&gt;
From /local/repositories/mle&lt;br /&gt;
   89d9eae..64c122d  master     -&amp;gt; origin/master&lt;br /&gt;
Updating 89d9eae..64c122d&lt;br /&gt;
Fast-forward&lt;br /&gt;
 index.html  |    9 +++++++++&lt;br /&gt;
 version.php |    6 +++---&lt;br /&gt;
 2 files changed, 12 insertions(+), 3 deletions(-)&lt;br /&gt;
 create mode 100644 index.html&lt;br /&gt;
$ git status&lt;br /&gt;
# On branch MOODLE_29_STABLE&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;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The command &#039;&#039;&#039;git submodule foreach [another command]&#039;&#039;&#039; walks through all submodule repositiories and executes what is specified by &#039;&#039;&#039;[another command]&#039;&#039;&#039;.&lt;br /&gt;
In this case it is &#039;&#039;&#039;git pull&#039;&#039;&#039;.&lt;br /&gt;
Therefore the module mylittleextension was updated and the main repository isn&#039;t clean anymore until changes are committed:&lt;br /&gt;
&amp;lt;pre&amp;gt;&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;
Maintaining plugins with Git submodules has also another application than simplyfying the update process.&lt;br /&gt;
In a greater scale it can be used to maintain a Moodle project, where multiple developers need to have an exact copy of your moodle without organizing external plugins manually.&lt;br /&gt;
You can read more about this topic at the page [[Moodle development environment with Git submodules]].&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
&lt;br /&gt;
* [[Windows installation using Git]]&lt;br /&gt;
* [[Git for Mac]]&lt;br /&gt;
* [[:dev:Moodle versions]]&lt;br /&gt;
* For fixing a Tracker Issue (MDL) / Forking Moodle / CONTRIButing code [[:dev:User:Sam_Hemelryk/My_Moodle_Git_workflow|User:Sam_Hemelryk/My_Moodle_Git_workflow]]&lt;br /&gt;
* [[Moodle_Production_Server_with_GIT|Case study Git + Moodle from Technical University Berlin]]&lt;br /&gt;
&lt;br /&gt;
; Moodle forum discussions&lt;br /&gt;
* [https://moodle.org/mod/forum/discuss.php?d=255175 Github and Moodle deployment for production]&lt;br /&gt;
* [http://moodle.org/mod/forum/discuss.php?d=168094 GIT help needed]&lt;br /&gt;
* [https://moodle.org/mod/forum/discuss.php?d=231046 Clear git guide for Admins (not developers)]&lt;br /&gt;
&lt;br /&gt;
; External resources &lt;br /&gt;
* [http://thamblings.blogspot.com.au/2013/07/upgrading-moodle-from-git.html Deploying Moodle from git - Blog post from a production experience]&lt;br /&gt;
* [http://gitref.org/ Git Reference]&lt;br /&gt;
* [http://progit.org/book/ Pro Git book]&lt;br /&gt;
&lt;br /&gt;
[[ja:管理者用Git]]&lt;br /&gt;
[[fr:Git_pour_administrateurs]]&lt;br /&gt;
[[es:Git para Administradores]]&lt;/div&gt;</summary>
		<author><name>Jan-eberhardt</name></author>
	</entry>
</feed>