MQL5 Algo Forgeへの移行(第4回):バージョンとリリースの操作
はじめに
MQL5 Algo Forgeへの移行を続けます。すでに個人リポジトリを用いたワークフローを整備し、この移行の主な目的のひとつである「コミュニティが提供するコードを容易に活用できる」という利点に注目しています。第3回では、他のリポジトリにある公開ライブラリを自分のプロジェクトに追加する方法について検証しました。
SimpleCandlesエキスパートアドバイザー(EA)にSmartATRライブラリを接続する実験を通じて、単純なクローン操作では不便な場合があることが明確になりました。特にコードに修正を加える必要がある場合には、その不便さが顕著です。そこで私たちは適切な手順に従い、他者のリポジトリをフォークして自分専用のコピーを作成しました。これにより、バグ修正や改良を自由に行い、後にプルリクエストを通じて作者に変更を提案することが可能になります。
MetaEditorのインターフェースにはいくつかの制約があるものの、MQL5 Algo ForgeのWebインターフェースと組み合わせることで、クローンの作成から編集のコミット、外部ライブラリとのリンクに至るまで、すべての工程を無事に完了させることができました。こうして、特定の課題を解決すると同時に、任意のサードパーティ製コンポーネントを統合するための汎用的なテンプレートも確認することができました。
本記事では、リポジトリに加えた編集内容を公開する段階について詳しく見ていきます。これは、プロジェクトに新しい機能を追加したり、既知の問題を修正したりといった、一連の変更をひとつの「完全な解決策」としてまとめるプロセスです。すなわち、コミットまたは新しい製品バージョンをリリースする工程にあたります。この記事では、このプロセスをどのように整理し、MQL5 Algo Forgeがそれをどのように支援するのかを確認していきます。
ブランチを探す
前回までは、特定の作業タスクに対応する編集内容をまとめる際には、専用のリポジトリブランチを使用することを推奨してきました。しかし、そのブランチでの作業が完了した後は、メインブランチなどにマージした上で削除するのが望ましい方法です。そうしないと、リポジトリ全体が複雑に枝分かれした「茂み」のような状態となり、所有者自身でさえ管理が困難になるおそれがあります。したがって、不要になったブランチは削除すべきです。ただし、場合によっては、あるブランチを削除する直前の状態にコードを戻す必要が生じることがあります。そのような場合、どのようにすればよいのでしょうか。
まず確認しておきたいのは、ブランチとは単に時系列に並んだコミットの連なりであるという点です。技術的には、ブランチとは一連の連続したコミットのうち「最新のコミット」を指し示すポインタにすぎません。したがって、ブランチを削除しても、コミットそのものが削除されるわけではありません。最悪の場合でも、それらのコミットが別のブランチに再割り当てされたり、1つの統合コミットにまとめられたりするだけで、基本的にはリポジトリ内に残り続けます(例外的なケースを除きます)。つまり「ブランチ削除前の状態」に戻すとは、実質的に、既存のブランチに含まれている特定のコミットへ戻すことを意味します。では、そのコミットをどのようにして見つければよいのでしょうか。
次に、第3回におこなった変更後のSimpleCandlesリポジトリの状態を見てみましょう。

左側にはコミット履歴と、ブランチ間の関係を示すカラー表示のビジュアルがあります。各コミットはハッシュ(正確にはその一部)によって識別されます。ハッシュとは他のすべてのコミットと区別するための一意な大きな数値であり、表記を短縮するために16進数(例:b04ebd1257)で表示されます。
このようなコミットツリーは、MQL5 Algo ForgeのWebインターフェースにある専用ページで、どのリポジトリについても確認できます。掲載されているスクリーンショットは過去に取得されたものであり、現在同じページを開くと、新しいコミットが追加され、マージによるブランチの交錯も変化しているはずです。
また、いくつかのコミットの横にはブランチ名も表示されています。これは各ブランチにおける最新のコミットを示すものです。掲載された例ではmain、develop、convert-to-utf8、article-17608-close-manager、article-17607、article-19436-forge3の6つのブランチが確認できます。最後のブランチは第3回執筆時の変更作業に使用されたものです。なお、第2回の作業時にも別の専用ブランチ(article-17698-forge2)を作成していましたが、すでに削除済みのため、現在そのブランチ名を持つコミットは存在しません。では、このブランチをどこで見つければよいのでしょうか。
コミット58beccf233の完全なメッセージを見ると、このブランチ名が記載されており、developブランチにマージされたことがわかります。

これで目的のコミットを見つけることができましたが、この方法では効率的とはいえません。さらに、もしコンソール上でgit mergeコマンドを使って手動でマージしていた場合、任意のコメントを自由に記述できたため、ブランチ名がメッセージ内に含まれないケースも考えられます。その場合、該当するコミットを探すのはさらに困難になります。
目的のコミットを特定できたら、そのコミットに切り替えることで、ローカルリポジトリをその時点の状態に戻すことができます。この操作は、git checkoutコマンドにコミットハッシュを指定して実行します。しかし、ここで注意すべき点があります。MetaEditor上で、プロジェクトのコンテキストメニューから「Git Log」を開き、対象のコミットを選択して切り替えを試みると、エラーメッセージが表示される場合があります。

...エラーメッセージが表示されます。

なぜこのようなことが起きるのでしょうか。その理由を理解するために、ここで新しい概念である「タグ」と「HEADポインタ」について紹介します。
タグ
Gitのバージョン管理システムにおける「タグ」とは、特定のコミットに付与される追加の名称のことです。タグは、リポジトリ内の特定のコミットを直接参照する「ポインタ」あるいは「参照」として捉えることもできます。タグを利用することで、そのタグが付けられたコミット時点のコード状態にいつでも正確に戻ることができます。タグは、プロジェクト開発の重要な節目を示す目印として非常に有用です。たとえば、バージョンリリース、開発フェーズの完了、安定版ビルドなどのタイミングで利用されます。MQL5 Algo ForgeのWebインターフェースでは、対象リポジトリのすべてのタグを専用ページで確認することができます。
Gitには「軽量タグ(lightweight tag)」と「注釈付きタグ(annotated tag)」の2種類があります。軽量タグは名前のみを持ち、単純にコミットを指し示す役割を果たします。一方、注釈付きタグには、作成者、日付、コメント、さらには署名といった追加情報を含めることができます。一般的には、軽量タグが最も多く使用されます。
Webインターフェースからタグを作成するには、任意のコミットページ(たとえばこちら)を開き、[Operation]ボタンをクリックし、[Create tag]を選択します。

タグ作成画面の例は後ほど改めて説明します。
Gitコンソールコマンドを用いてタグを作成する場合は、「git tag」コマンドを使用します。軽量タグを作成するには、タグ名を指定するだけです。
git tag <タグ名>
#例
git tag v1.0
注釈付きタグを作成する場合は、追加のパラメータを指定します。
git tag -a <タグ名> -m "タグの説明"
#例
git tag -a v1.0 -m "バージョン 1.0 リリース"
タグは、公開・配布(リリース)を目的としたコードのバージョンを明示するだけでなく、CI/CDパイプラインにおいて特定のタグ付きコミットが検出された際に自動処理を実行させるトリガーとして利用することもできます。 また、新機能の実装完了や重大な不具合修正といった、開発上の重要な節目を示すためにも使用されます。このように、タグはバージョン管理の中で柔軟かつ強力な管理手段として活用できます。
HEADポインタ
タグについて理解したところで、もう一つ重要な概念であるHEADポインタについて触れておきましょう。HEADポインタの動作は、「HEAD」という固定名を持つタグに似ています。ただし、HEADは手動で付けるタグとは異なり、自動的に「現在チェックアウトしているブランチの最新コミット」を指し示すように動作します。そのため、HEADはしばしば「現在のブランチを示すマーカー」や「アクティブなブランチを指すポインタ」と呼ばれます。つまりHEADは、「今リポジトリのどの位置にいるのか?」という問いに答える存在です。ただし、厳密に言えばHEADはタグではありません。
HEADポインタは、リポジトリ内の「.git/HEAD」というファイルに保存されています。このファイルの内容には、シンボリック参照(タグ名またはブランチ名)または特定のコミットハッシュが記録されます。ブランチを切り替えると、HEADポインタは自動的に更新され、現在のブランチの最新コミットを指すようになります。また、新しいコミットを作成すると、Gitはそのコミットオブジェクトを生成すると同時に、HEADポインタをその新しいコミットへ移動させます。
このように、HEADという名前はGitのコンソールコマンド内で、最新コミットのハッシュや現在のブランチ名の代わりに使用することができます。さらに、「~」や「^」といった特殊記号を組み合わせることで、過去のコミットを相対的に指定することも可能です。たとえば「HEAD~2」は、最新コミットの2つ前を意味します。これらの詳細については、ここでは深く掘り下げません。
次に、リポジトリが取りうる2つの状態についても説明しておきましょう。「attached HEAD」と呼ばれる通常の状態では、新しいコミットは現在のブランチの最新コミットの次に追加されます。この状態では、すべての変更がブランチ上に連続的かつ整合的に追加されていきます。
一方、「detached HEAD」状態とは、HEADポインタがどのブランチの最新コミットでもないコミットを指している場合のことです。この状態は、次のような操作をおこなった際に発生することがあります。- 特定の過去のコミットにリポジトリを切り替えた場合(例:git checkout <commit-hash>)
- タグ名で切り替えた場合(例:git checkout tags/<tag-name>)
- リモートリポジトリには存在するが、ローカルでは削除されたブランチに切り替えた場合(例:git checkout origin/<branch-name>)
この「デタッチ状態」は、できる限り避けることが推奨されます。なぜなら、この状態でおこなった変更はどのブランチにも紐づかないため、別のブランチへ切り替えた際に変更内容が失われてしまう可能性があるためです。ただし、この状態で変更を加えない(閲覧や確認のみを行う)場合には、特に問題はありません。
今のところタグはありません
それでは、削除されたブランチarticle-17698-forge2において、かつて最新コミットであった特定のコミットへローカルリポジトリを切り替えようとした試みについて戻ってみましょう。
リポジトリを特定の過去のコミットへ切り替える操作は、日常的なGitの運用において開発者が頻繁におこなうものではありません。通常の開発フローでは、このような操作をおこなう必要が生じることはほとんどありません。しかし、もしこの操作を実行すると、リポジトリは「detached HEAD」と呼ばれる状態に入ります。今回の場合、その対象のコミットはdevelopブランチに属していますが、すでにその後に新しいコミットが追加されているため、もはやブランチの最新コミットではありません。
それでも、Gitのコマンドラインインターフェース(CLI)を用いてこのコミットへ切り替えをおこなえば、操作自体は正常に完了します。ただし、その際Gitから「現在はdetached HEAD状態にある」という警告メッセージが明確に表示されます。

注意深い読者の方は、直近のスクリーンショットで私たちがハッシュ値58beccf233のコミットに切り替えたにもかかわらず、GitのメッセージではHEADポインタが58beccfを指していることにお気づきかもしれません。末尾の3桁はどこへ消えたのでしょうか。実際には何も問題はありません。ハッシュ値が消えたわけではなく、Gitはリポジトリ内で一意に識別できる範囲であれば、短縮されたコミットハッシュを使用できるようになっているのです。インターフェースやツールによって、表示されるハッシュの長さはおおむね4~10文字程度に省略されることがあります。
もし完全なハッシュ値(フルハッシュ)を確認したい場合は、「git log」コマンドを実行することで確認できます。各コミットの完全なハッシュは40桁の16進数で構成されています。

各ハッシュはランダムかつ一意に生成されるため、最初の数桁だけでもリポジトリ内で重複する可能性はほとんどありません。このため、コマンド内でコミットを指定する際には、ハッシュの短縮形を使うだけでGitが正確に対象のコミットを特定できる場合がほとんどです。
UTF-8エンコーディングの使用
ここにもう一つ興味深い側面があります。以前のバージョンのMetaEditorでは、ソースコードファイルを保存する際にUTF-16LEエンコーディングが使用されていました。しかし、このエンコーディングで保存されたファイルは、Git上ではテキストファイルではなくバイナリファイルとして扱われてしまいました。そのため、コミット内でどの行が実際に変更されたのかを正確に確認することができませんでした(Visual Studio Codeでは正常に確認できましたが、Git上では不可能でした)。コミットで確認できる情報は、変更前後のファイルサイズのみでした。
MQL5 Algo Forge Webインターフェースでは次のようになります。

現在では、MetaEditorで新規作成されるファイルはUTF-8エンコーディングで保存されるようになっています。また、日本語などを使用しても、自動的にUTF-16LEに切り替わることはありません。そのため、古いプロジェクトから新しいリポジトリに持ち込んだ既存ファイルについては、UTF-8に変換することが推奨されます。UTF-8に変換した後は、次回以降のコミットから、どの行やどの文字が変更されたのかを正確に確認できるようになります。たとえば、MQL5 Algo ForgeのWebインターフェースでは、変更された行や文字が明確に表示されるようになります。

少々脱線したので、話を元に戻し、リポジトリにおける新しいコードバージョンの公開方法について引き続き説明していきます。
メインタスクに戻る
リポジトリ内のブランチのうち、今回はarticle-17608-close-managerとarticle-17607に注目します。これらのブランチでおこなわれた変更は、対応するタスクがまだ進行中のため、まだdevelopブランチにマージされていません。両ブランチは今後も開発が続くため、現時点でdevelopにマージするのは時期尚早です。ここでは、article-17607を選び、このブランチの作業を一旦論理的に完了させたうえでdevelopにマージします。マージ後のコード状態には、バージョン番号を付けてタグ付けをおこないます。
選択したブランチで作業を続ける前に、最新の状態を取り込む必要があります。なぜなら、article-17607が存在している間に他のブランチでも変更がおこなわれており、これらの変更はすでにdevelopにマージされているためです。したがって、developで更新された内容を選択したブランチに反映させる必要があります。
developの変更をarticle-17607に取り込む方法はいくつかあります。たとえば、WebインターフェースからPull Requestを作成してマージする方法もありますが、この方法は通常「新しい未検証のコードを、安定したブランチにマージしたい場合」に適しています。今回のケースでは状況が逆であり、安定した検証済みの更新内容を、新しい未検証コードを含むブランチに取り込みたいため、Gitのコンソールコマンドを使ってマージする方法が適しています。ここではコンソールで操作をおこない、その過程をVisual Studio Codeで確認します。
まず、リポジトリの現在の状態を確認しましょう。バージョン管理パネルでコミット履歴とブランチ名を確認します。現在のブランチはarticle-19436-forge3で、直近の変更はこのブランチ上でおこなわれました。ターミナル右側には「git status」の出力が表示されており、リポジトリがリモートブランチと同期していることを確認できます。

このコマンドにより、リポジトリが現在article-19436-forge3ブランチ上にあり、その状態がリモートリポジトリの対応ブランチと同期していることが確認できます。
次に、コマンド「git checkout article-17607」を使用してarticle-17607ブランチに切り替えます。

次に、「git merge develop」を使用して、developとマージします。

外部の変更がarticle-17607で作業した箇所には影響していなかったため、マージ時にコンフリクトは発生しませんでした。その結果、Gitは新しいマージコミットを作成しました。
次に、「git push」コマンドを実行して、更新内容をリモートリポジトリに反映させます。

MQL5 Algo Forgeのリポジトリを確認すると、先ほどのマージ操作がリモートリポジトリにも正しく反映されていることが確認できます。

スクリーンショットに表示されている最新のコミットは、developブランチとarticle-17607ブランチのマージコミットです。
また、article-19436-forge3ブランチの末端はまだ他のブランチと接続されていません。このブランチでの変更はまだdevelopにマージされておらず、作業も継続中です。そのため、現時点ではこのブランチはそのまま残しておきます。必要になった時点で再度取り扱います。
これで、article-17607ブランチでの開発を続行する準備が整いました。このブランチに対応するタスクの具体的なコード作業については別の記事で説明されているため、ここでは繰り返しません。代わりに、次はタスク完了後にコードの状態を最終化し記録する方法について説明していきます。
マージの実行
特定のコード状態を公開する前に、まずその変更をメインブランチにマージする必要があります。今回のリポジトリにおける主要ブランチはmainです。developブランチのすべての更新は最終的にメインに反映され、各タスク用ブランチの変更はまずdevelopにマージされます。現時点ではmainに新しいコードをマージする準備ができていないため、ここではdevelopへのマージのみに留めます。デモンストレーションの目的では、どのブランチをmainと見なすかはそれほど重要ではありません。
選択したタスクの作業が終了した時点でのSimpleCandlesリポジトリの状態を確認します。

示されているように、最新のコミットはarticle-17607ブランチ上にあります。前述のように、このブランチをdevelopにマージするため、MQL5 Algo ForgeのWebインターフェースからPull Requestを作成します。

すべてが期待どおりに進んだかどうかを確認しましょう。コミット履歴ページを、ブランチツリー表示で再度確認します。

ハッシュ432d8a0fd7のコミットは、もはやarticle-17607ブランチの最新コミットとしては表示されません。代わりに、ハッシュ001d35b4a7のコミットがdevelopの最新コミットとして表示されます。このコミットは、2つのブランチのマージを記録したものであり、以降「マージコミット」と呼びます。
次に、マージコミットページを開き、新しいタグを作成します。これをどこでおこなうかはこの記事の前半で示しましたが、次は実際におこなう番です。

ポップアップウィンドウでタグ名v0.1を入力します。これはまだ最終バージョンにはほど遠いため、小さめのバージョン番号を設定しています。今後プロジェクトにどれほどの追加作業があるかは未確定ですが、十分に多くの作業が残っていることを示す目安として、このような小さな番号を使用しています。なお、現時点ではWebインターフェースでは注釈付きタグの作成には対応していないようです。
タグは正常に作成され、作成結果は

または、リポジトリの専用タグページで確認できます。

「git pull」コマンドでローカルリポジトリを更新すると、作成したタグもローカルに反映されます。ただし、MetaEditorではリポジトリタグの表示に対応していません。そこで、Visual Studio Codeでタグの状態を確認します。コミットツリー上で対象のコミットにマウスカーソルを合わせると、ツールチップにタグ名が付いたカラーラベルが表示され、どのコミットにタグが付いているかを視覚的に確認できます。

タグの作成が完了したので、ここで作業を終了してタグ名を「git checkout」コマンドで指定し、正確にそのコード状態へ切り替えることもできますし、さらに進めてこのタグを基にリリースを作成することも可能です。
リリースの作成
リリースとは、使用するプログラミング言語に関わらず、特定のソフトウェアバージョンを明示的に示して配布するための仕組みです。コミットやブランチは開発のワークフローを表していますが、リリースはその公式な成果物、すなわち公開したいバージョンを示します。リリースを利用する主な目的は次の通りです。
- バージョン管理:リポジトリ内の特定のコード状態を安定版としてマークします。これは重大なエラーがなく、機能が検証済みであることを意味します。ユーザーはこうした特定のバージョンを利用できます。
- バイナリ配布:リリースにはコンパイル済みやパッケージ化されたファイル(.ex5、.dll、.zipなど)を含めることができ、ユーザーが自分でプロジェクトをコンパイルする必要がなくなります。
- ユーザーへの情報提供:リリースには変更点、新機能、修正済みのバグ、既知の問題などをまとめた説明を添付します。これはユーザーがアップデートすべきか判断するための重要な情報です。
リリースは既存のタグを基に作成することも、新しいタグを生成して作成することもできます。今回はすでにタグがあるため、このタグを利用して新しいリリースを作成します。リポジトリのタグページに移動し、対象のタグの横にある[New release]をクリックします。

- リリース名、ターゲットブランチ、タグ(既存タグまたは新規タグ)
- リリースノート:新機能、修正点、既知の問題点の概要
- 添付ファイル:コンパイル済みプログラムやドキュメント、外部リソースへのリンクなど

作成したリリースはドラフトとして保存し、後から詳細を更新することもできますし、すぐに公開することも可能です。公開後も、リリース説明を後から修正することができます。公開されたリリースはリポジトリのReleasesページに表示され、他のユーザーも閲覧できるようになります。

以上です。新しいバージョンが公開され、使用可能な状態になりました。後ほど、リリース名を更新したり、実装内容を解説した記事へのリンクを追加したりすることも可能です。
結論
ここで少し立ち止まり、これまでの進捗を振り返ってみましょう。私たちは単にバージョン管理の技術的な側面を学んだだけではありません。散発的な修正作業から脱し、コードを体系的かつ一貫した形で管理するためのワークフローを構築するという、完全な変革を成し遂げました。そして何より重要なのは、最終段階――つまり、完成した作業をエンドユーザー向けの正式な製品バージョンとしてリリースするところまで到達したことです。現在のリポジトリはまだ完全な成熟段階にあるとは言えませんが、そのための基盤はすべて整いました。
このアプローチは、プロジェクトの捉え方そのものを根本から変えます。以前は単なるソースファイルの寄せ集めだったものが、今では変更履歴が明確に管理された、いつでも安定した状態に戻すことができる整理されたシステムになりました。これは開発者にとっても、完成品を利用するユーザーにとっても大きな利点です。
これらのツールを使いこなすことで、私たちはMQL5 Algo Forgeリポジトリでの作業を新たな段階へと引き上げ、今後より複雑で大規模なプロジェクトへと発展させるための道を開いたのです。
ご精読ありがとうございました。また次回お会いしましょう。
MetaQuotes Ltdによってロシア語から翻訳されました。
元の記事: https://www.mql5.com/ru/articles/19623
警告: これらの資料についてのすべての権利はMetaQuotes Ltd.が保有しています。これらの資料の全部または一部の複製や再プリントは禁じられています。
この記事はサイトのユーザーによって執筆されたものであり、著者の個人的な見解を反映しています。MetaQuotes Ltdは、提示された情報の正確性や、記載されているソリューション、戦略、または推奨事項の使用によって生じたいかなる結果についても責任を負いません。
初心者からエキスパートへ:MQL5を使用したアニメーションニュースヘッドライン(IV) - ローカルホストAIモデル市場インサイト
知っておくべきMQL5ウィザードのテクニック(第73回):一目均衡表とADX-Wilderのパターンの利用
MQL5入門(第18回):ウォルフ波動パターンの基本
MQL5での取引戦略の自動化(第22回):Envelopes Trend取引のためのZone Recoveryシステムの作成
- 無料取引アプリ
- 8千を超えるシグナルをコピー
- 金融ニュースで金融マーケットを探索