
Moving to MQL5 Algo Forge (Part 2): Working with Multiple Repositories
Introduction
In the first article, we began transitioning from the built-in SVN-based MQL5 Storage in MetaEditor to a more flexible and modern solution based on the Git version control system: MQL5 Algo Forge. The main reason for this step was the need to fully leverage repository branches while working on multiple projects or on different functionalities within a single project.
The transition started with the creation of a new repository in MQL5 Algo Forge and the setup of a local development environment using Visual Studio Code, along with the necessary MQL5 and Git extensions and supporting tools. We then added a .gitignore file to the repository to exclude standard and temporary files from version control. All existing projects were uploaded into a dedicated archive branch, designated as an archival storage of all previously written code. The main branch was left empty and prepared for organizing new project branches. In this way, we laid the foundation for distributing different project codes across separate branches of the repository.
However, since the publication of the first article, MetaEditor has significantly expanded its support for the new repository system. These changes encourage us to reconsider the previously outlined approach. Therefore, in this article, we will deviate slightly from the original plan and explore how to create a public project that integrates other public projects as components. The project we will focus on is the development of a multi-currency Expert Advisor. Several articles have already been published that describe the approaches to the code development and modifications for this project. Now, we will take full advantage of Git version control to organize and streamline the development process.
Mapping out the path
It's hard to believe, but at the time of the previous article, MetaEditor did not yet include the "Git: menu or file context menu commands for working with MQL5 Algo Forge repositories. As a result, considerable effort was required to configure workflows using external tools like Visual Studio Code. Since we didn't know how MetaEditor would eventually implement repository support, we had to use the tools available at that time.
Since then, new MetaEditor releases have introduced built-in support for MQL5 Algo Forge. MetaQuotes has also published a new article, "Getting Started with MQL5 Algo Forge", which explains the basics and demonstrates key features. However, the most important development, in our view, is the implementation of Shared Projects in MetaEditor.
Why is this significant? Previously, we knew that the MQL5 folder would act as a repository hosted on the Git servers of MQL5 Algo Forge. Apparently, this repository would have the fixed name mql5. This meant that each user would have a repository named mql5 in Algo Forge. This repository would then be cloned into the MQL5 folder after installing a new terminal, logging into the Community, and connecting the repository. At the same time, MQL5 Algo Forge has always allowed the creation of additional repositories. More precisely, not additional, but separate ones, not related to the mql5 repository. Naturally, this raised a question: how would MetaEditor handle these other repositories?
Would users be able to select which repository to use in each installation of the terminal? Or not? Would only the mql5 repository be supported, with users forced to separate their work into branches for different projects? We initially prepared for this worst-case scenario. Managing multiple projects across branches in a single repository is not particularly convenient. Fortunately, our concerns proved unfounded.
MetaQuotes introduced a more elegant solution that effectively solves two problems at once. On one hand, we have the main repository named mql5. This works well for those already accustomed to MQL5 Storage. They can now continue using version control without worrying about which version control system lies underneath.
On the other hand, all other user repositories are now available as folders inside Shared Projects. This provides a new standard root folder, alongside existing (ones such as MQL5, MQL5/Experts, MQL5/Include, etc.), intended for storing code from the user's additional repositories.
Let's consider an example. Suppose we have two separate repositories in MQL5 Algo Forge, neither of which is the default mql5. The first repository (Adwizard) contains only library code, i.e. only *.mqh include files, without any *.mq5 files that could be compiled into an Expert Advisor or indicator. The second repository (Simple Candles) contains *.mq5 files that use the include files from the first repository. For simplicity, we'll refer to the first repository as the library repository and the second as the project repository.
Our goal is to determine how to use code from the library repository while developing within the project repository. This scenario could become increasingly common if, for instance, code shared in the mql5.com Code Base is also mirrored by its authors in MQL5 Algo Forge as public repositories. In such cases, linking one or more repositories as external libraries to a project could be handled in the same way we are about to explore in this article.
Getting Started
Let's first look at the situation from the perspective of the developer who owns both repositories. This means we can freely make changes to the code in either repository without waiting for a review and approval via the Pull Request mechanism. We begin by creating a clean terminal folder and copying two files from any previously installed copy of MetaTrader 5:
To avoid searching for the terminal's working folder deep within the file system, we recommend running the terminal in Portable mode. In Windows, one way to do this is to create a shortcut to the terminal's executable file and add the /portable flag to the target field in the shortcut properties.
After launching the terminal, open a new demo account just in case, update to the latest version, sign in to the Community, and then launch MetaEditor by pressing F4. Connect MQL5 Algo Forge, if it hasn't already connected automatically.
In the Navigator, we now see the 'Shared Projects' folder, which lists the repositories we previously created through the web interface. However, if we open this folder in Explorer, it is still empty. This means that the actual repository files have not yet been downloaded to our computer.
To clone them, right-click each of the needed repositories and select "Git Clone" from the context menu. The log confirms successful cloning of both Adwizard and Simple Candles. The folders with the cloned repositories now appear in Explorer:
At this point, the code for both projects is available locally and ready to use.
First Problem
Let's open SimpleCandles.mq5 and try compiling it:
As expected, compilation errors occur. Let's try to understand their reasons. These are not critical, since we know the code compiled successfully before. The only thing that has changed is the relative placement of the library and project files. The first two fundamental errors come from the fact that the compiler cannot find the library files where it expects them. Back in Part 28, we agreed to use the following folder structure to store the library and projects parts:
That is, we store the library repository inside a subfolder of the project repository. This gave us a predictable structure for locating library files. This time, however, we'll change this. Instead of using a mandatory Include subfolder inside the project, we will use the MQL5/Shared Projects folder. Ideally, this folder will remain stable and continue serving the same purpose in future MetaEditor versions.
To fix the issue, we'll update the #include directives in two files. But before making any code changes, let's follow good development practice and create a separate branch for this isolated task. Once the fixes are tested, we can merge the branch back into the main development branch.
Let's see what branches we already have in the project repository. This can be done in several ways:
- Via the repository folder's context menu in MetaEditor:
- Through the web interface on the repository's branches page:
- Using an external Git tool such as Visual Studio Code. Next to the repository name we see main, which is the name of the current branch. A click on it shows a list of available branches (and menu items for creating new branches):
Currently, the repository has four branches:
- main — the primary branch. It is created with the repository. In the simplest case, all work can be done here without creating any additional branches. In more complex cases, this branch is used to store the states of the files that provide stable versions of the code. Any ongoing changes that have not yet been completed and tested are made in other branches.
- develop — the development branch. In simple cases, it can be used as the only branch to add changes and implement new features. This option is sufficient if new features are implemented sequentially. That is, we do not start implementing new functionality until the project is in a fully functional and stable state after we added the previous features. Before starting work on a new feature, branches are merged: edits made in the develop branch are merged into main. If multiple features are being developed simultaneously, it becomes inconvenient to work in one development branch. In such cases, additional feature branches can be created.
- The examples or such branches are article-17608-close-manager and article-17607. The former is a feature branch for position-closing logic based on profit/loss thresholds. This branch is already merged into develop and develop is then merged into main. The second feature branch is used for enhancements to automated optimization. It is still in progress, not yet merged into develop or main.
It's important to stress that Git does not enforce any specific branch usage rules. So, we can choose the option that is most convenient for us. There are certain workflows that some developers have found useful and shared with others. This is how "Best Practices" appear. You're free to adopt or adapt whichever branching model suits your project. As an example, take a look at one of the proposed branching principles described in this article.
Now let's get back to our repository.
One detail that may raise questions is the prefix origin/ (or refs/remotes/origin/ as shown in MetaEditor). This prefix simply indicates that the branch exists in the remote repository, not just locally. Typically, we keep local and remote branches in sync. In MetaEditor, running a Commit command automatically triggers a Push command, and thus the commit is sent to the remote repository.
If commits are made outside MetaEditor, it's possible to commit locally without pushing. In such cases, the local and remote branches with the same name may be different. The origin/ prefix helps distinguish between them. With this prefix, we mean a branch in a remote repository; otherwise, it's a local one.
Creating a New Branch
Since the planned edits only ensure the code compiles correctly after the placement of its library part changed, we'll base a new branch generated from develop. We first switch to origin/develop, after which it appears in the list as a local develop branch.
Then we create a new branch (execute the New command) and enter the desired name. Following our convention, article-related branches begin with article- plus the article's unique identifier. This can optionally be followed by a short suffix describing the topic of the article. That's why the new branch is named "article-17698-forge2".
We could create a branch in other ways too: using the web interface, the Visual Studio Code interface, or the command line interface. From the command line in the repository's root folder, we can run:
git checkout -b article-17698-forge2 develop
This tells Git to switch (checkout) to a new branch (-b) called article-17698-forge2, based on the develop branch.
If a branch is created outside the web interface, it will exist only on our local machine until the first push to the remote repository. The opposite is also true: if a branch is created in the remote repository through the web interface, it will not appear on our local machine until the first pull from the remote repository.
You can push changes like this:
or like this:
The console command for the Push operation, when it includes the creation of a new branch, must contain additional parameters confirming that we truly want the branch to be created in the remote repository:
git push --set-upstream origin article-17698-forge2
After this, the branch exists both in the local copy of the repository and in the remote repository hosted in MQL5 Algo Forge. At this point, we can start making edits without fear of breaking the functionality of other branches.
Making Changes
The required modifications are very simple. In the file SimpleCandles.mq5, we update the line that includes a file from the Adwizard library. Since the root folders of the Simple Candles and Adwizard repositories are now located at the same level inside the Shared Projects folder, the path to Expert.mqh must first move one level up (../) before descending into the subfolders of the library repository:
#include "Include/Adwizard/Experts/Expert.mqh" #include "../Adwizard/Experts/Expert.mqh"
A similar adjustment is needed in the file Strategies/SimpleCandlesStrategy.mqh:
#include "../Include/Adwizard/Virtual/VirtualStrategy.mqh" #include "../../Adwizard/Virtual/VirtualStrategy.mqh"
After these changes, SimpleCandles.mq5 compiles successfully again. We can now commit the changes to the repository:
As mentioned earlier, when committing through the MetaEditor interface, the Push command is executed automatically, sending the changes to the remote repository in MQL5 Algo Forge.
When working with console commands, we can achieve the same result as follows. If, in addition to editing existing files, we also created new ones, we first need to add them to the repository index:
git add .
This command adds all new files found in the repository folder. To add only specific files, replace the dot (.) with their names. After that, we commit the changes with a specified comment and push them to the remote repository:
git commit -m "Fix relative paths to include files from Adwizard"
git push
At this point, the changes in the article-17698-forge2 branch are complete. It can be merged into the develop branch and then closed.
Second Problem
Here we run into an unpleasant surprise. MetaEditor currently lacks tools for merging branches. In other words, we can now create new branches, but we cannot transfer changes from one branch to another! Hopefully, this functionality will be added in the near future. For now, we must once again turn to alternative tools to perform repository operations.
There are two main ways we can merge branches. The first is to use the merge interface in Visual Studio Code or standard console commands. For our case, the following commands can be used:
git checkout develop
git pull
git merge --no-ff article-17698-forge2
First, we switch to the develop branch. Then, as a precaution, we update it (in case changes were made that have not yet reached our local machine). Finally, the last command performs the actual merge. Merge conflicts are possible, but in our scenario, they are unlikely, since we are still considering the case of a single developer working on the project Even when working from multiple locations, as long as we regularly update the repositories to the latest state, conflicts should not arise.
However, let us not dwell on the nuances of this method. Instead, we will take a closer look at the second approach. Here we use the MQL5 Algo Forge web interface.
Using Pull Requests for Merging
Like other Git-based platforms (such as GitHub, GitLab, or Bitbucket), MQL5 Algo Forge also includes a mechanism called a Pull Request (PR).
A Pull Request allows a developer to propose changes made in a branch to be merged into a repository. In other words, creating a PR is a way of notifying the repository owner and other contributors: "I’ve completed work in my branch, please review and merge these changes into the main branch (main/master/develop)."
A PR is not a feature of Git itself but an additional layer built on top of it. It organizes the process of code review and discussion before changes are merged into the main branch.
Pull Requests also solve several other critical tasks in modern development: continuous integration (CI) with automated tests, quality control by other developers, and documentation of changes in the form of PR comments explaining why certain modifications were made. However, these practices are most relevant for team-based projects, while MQL5 projects are usually individual ones. Anyway, the workflow may become more important as collaborative projects emerge in the future.
That said, we have already replicated the start of a typical workflow for adding new functionality or fixes using PRs:
-
Pull the latest changes. Before starting work, we updated the local develop branch.
-
Create a new branch for the task. From the updated develop branch, we created a branch with a clear name article-17698-forge2.
-
Make changes in the new branch. We modified and tested several files, then committed the changes.
-
Create a Pull Request. In the MQL5 Algo Forge web interface, navigate to the Pull Requests tab and click the large red 'New pull request' button.
This opens the branch selection page. At this stage, the PR has not yet been created; first, we must define where the changes will be merged. Once the branches are selected, we can review the list of changes. Then, click 'New pull request' again.
A new page opens where we can provide a detailed description of the changes. Here, we can also assign reviewers. By default, the request is directed to ourselves, which is exactly what we need in this case.
-
Review and discussion. Since we are working alone, we can skip this step. Normally, this stage involves:
-
reviewers examining the code and leaving comments (general or tied to specific lines),
-
the PR author responding to comments and making corrections in the same branch,
-
and all new pushes automatically being added to the existing PR.
-
-
Merging. After reviewers approve (if any) and CI passes (if configured), the PR can be merged. Typically, there are several merge options:
-
Merge commit: Creates a separate merge commit, preserving the branch history.
-
Squash and merge: Combines all PR commits into a single commit added to the target branch. Useful to avoid cluttering the history with minor commits like "fixed typo".
-
Rebase and merge: Reapplies PR commits on top of the target branch (in our case it's develop). This produces a clean, linear history.
Now comes the final page of Pull Request operations. Here we check the option 'Delete branch ...' to close the temporary development branch. The commit history will still reflect that the branch existed. But keeping it open serves no purpose since we've achieved our goal. For future changes that solve other tasks, we will create new branches. This way, the repository's branch list always provides a clear snapshot of currently ongoing parallel work.
Leave the rest of the settings as they are and click 'Create merge commit'.
The process is now complete: the article-17698-forge2 branch has been merged into develop and deleted:
In general, using Pull Requests even in your own repository is a good and recommended practice, even for solo projects. Before merging, you can visually review all changes, often catching things missed during commits: unnecessary comments, stray files, or non-optimal edits. In essence, this is a form of self-discipline. Moreover, adopting this workflow builds good habits (branching, code review, etc.). So if you later join a development team, this process will already be familiar to you.
So yes - submitting PRs to yourself is not only possible but encouraged for any serious project. It improves code quality and enforces discipline. Of course, for quick fixes consisting of one or two commits, nothing prevents you from merging directly with git merge. But for larger changes, a PR is the better approach.
Conclusion
Overall, the workflow with personal repositories is now well established. We have covered the path from cloning repositories to refining a process where changes leave the code functional and ready for further development. The project repository can now meaningfully use code from another repository (or several) as libraries.
However, we have only considered one scenario: when the same user owns both the project and library repositories. The other scenario is when the project owner wants to use someone else's repositories as libraries. This case is not as simple. And yet, this kind of workflow, with active reuse of community code and collaboration, was one of the stated goals behind moving to the new repository system. Nevertheless, the foundation has been laid.
We will stop here for now. See you in the next part!
Translated from Russian by MetaQuotes Ltd.
Original article: https://www.mql5.com/ru/articles/17698
Warning: All rights to these materials are reserved by MetaQuotes Ltd. Copying or reprinting of these materials in whole or in part is prohibited.
This article was written by a user of the site and reflects their personal views. MetaQuotes Ltd is not responsible for the accuracy of the information presented, nor for any consequences resulting from the use of the solutions, strategies or recommendations described.





- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
You agree to website policy and terms of use
The Cyrillic alphabet was hardly there - I gave up using it even in comments a long time ago.
Apparently, I was mistaken. I just added this to the .mq5 file with UTF-8 encoding:
// Cyrillic
and after saving the file encoding changed to "UTF-16 LE BOM".
It seems to be MetaEditor's fault. I added Cyrillic characters and saved the file using Notepad++ and the encoding remained UTF-8.
I also find it strange to argue for the need to be able to remove branches from the local repository. Given that Git's branching model is its killer feature and Git encourages frequent creation, deletion and merging of branches.
So I'm also in favour of deleting branches after they merge with the main branches. It's just the first time I've heard that after deletion, they create a branch for the new fiche with the same name, not a new one.
What is the purpose of watching diff?
Yes, it is a very necessary thing. I actively use it too, but only in VS Code. And there, strangely enough, there are no crashes there, though I look through files with "bad" encoding.
I've never encountered such a thing. It's pretty unexpected, too. Maybe the breakage of normal files was due to simultaneous use of different ME builds to work with the same files? I don't know...
I looked at the commit history, that files added two months ago do indeed already have UTF-8 encoding, and files added three months ago are still UTF-16 LE. Apparently there was a switch to UTF-8 encoding somewhere around that time.
I guess I was wrong. I just added this to the .mq5 file with UTF-8 encoding:
and after saving the file encoding changed to "UTF-16 LE BOM".
It seems to be MetaEditor's fault. I added Cyrillic characters and saved the file using Notepad++ and the encoding remained UTF-8.
I confirm, after adding Russian letters and saving the file the encoding changes from UTF-8 to UTF-16 LE. If all Russian letters are removed and saved, it still remains UTF-16 LE.
It seems to be MetaEditor's fault.
Here is a proof that you can make UTF-8, Cyrillic and Git compatible:
https://forge.mql5.io/junk/utf8-cyrillic-test/commit/e87d37b02e88d44305dea0f7f6630c6173471aea
All you need to do is to ask MetaEditor not to change the file encoding.
I guess I was wrong. I just added this to the .mq5 file with UTF-8 encoding:
and after saving the file encoding changed to "UTF-16 LE BOM".
It seems to be MetaEditor's fault. I added Cyrillic characters and saved the file using Notepad++ and the encoding remained UTF-8.
Most likely, UTF-8 was without BOM, ME doesn't like it. At least it used to leave files in UTF-8 only if BOM was present. Other editors are smarter and work without BOM.