Windows
Git
SourceTree
LabVIEW
LabVIEWDay 5

SourceTree から LabVIEW コードの比較/統合をする

More than 1 year has passed since last update.

LabVIEW Advent Calendar 2016 の5日目です。

バージョン管理の GUI ソフト「SourceTree」から、LabVIEW のソースコード VI の比較/統合をする方法をまとめました。Windows が対象です。

雑な説明

インストールと設定

  1. LabVIEW プロフェッショナル開発システムと SourceTree をインストールしておく。SourceTree のインストール時、デフォルトで組み込まれる Git Bash を選択することを想定。
  2. https://github.com/torufurukawa/sourcetree-lv/releases/download/v0.0.1/lvdiffmerge-0.0.1.zip をダウンロード、解凍、適当なフォルダに保存する
  3. SourceTree の、ツール → オプション → Diff で...
    1. 外部 Diff ツール: カスタム
    2. Diff コマンド: <2のフォルダ>/diff.sh
    3. 引数: $REMOTE $LOCAL
    4. Merge コマンド: <2のフォルダ>/merge.sh
    5. 引数: $BASE $REMOTE $LOCAL $MERGED

bc8a5af4-a86e-4e51-8cbe-025cfe1704f8.png
3. リポジトリの lvdiffmerge.txt に LabVIEW と比較/統合ツールのパスを書いておく。64-bit 版 LabVIEW 2015 をデフォルトでインストールした場合は以下のようになる。

lvdiffmerge.txt
SHARED_DIR="C:\Program Files (x86)\National Instruments\Shared"
LABVIEW_EXE="C:\Program Files (x86)\National Instruments\LabVIEW 2015\LabVIEW.exe"

Diff (比較)

SourceTree で、コミット前の VI を右クリック → 外部 Diff を起動

ext diff.png

diff.png

Merge (統合)

SourceTree でマージ後、コンフリクトした VI を右クリック → コンフリクトを解消 → 外部 Merge を起動

resolve.png

lv merge.png

能書き

今年の秋頃、LabVIEW を使ったアプリケーションを、2人で作る仕事をしました。モジュールで分担しましたが、モジュール間でやりとりが発生する箇所では、どうしても同じ VI を触ることになります。また、2人は普段は離れたところで仕事をしているので、ときどきお互いの変更を取り入れる必要がありました。

分散バージョン管理が役に立つ状況です。Git と SourceTree を使うことにしたのですが、比較と統合に工夫が必要でしたので、ちょっとしたスクリプトを書きました。

「フォルダ名に日付やバージョン名をつけて、まとめて渡すからいいよ」と言われることが多々ありますが、ソフトウェアに任せたほうが、人間をしょうもない作業から開放できると思います。

ワタナベくんと永沢さん

ここで架空の人物、ワタナベくんと永沢さんに登場してもらいます。ふたりとも同じ職場で働く、LabVIEW プログラマーです。ワタナベくんはまだまだこれからです。永沢さんは頭が切れると評判の先輩ということにしましょう。

ワタナベくんと永沢さんは、同じプロジェクトの仕事をすることになりました。顧客の要件がはっきりしないところがあるので、最初の段階で、要件を確認しながら開発することにします。顧客とのやりとりは永沢さんがやってくれます。

Git リポジトリにコミット

永沢 「そういうわけだから、まずは電圧を測定して、グラフに表示するだけの簡単なサンプルを作って欲しいんだよ。」
ワタナベ 「分かりました。カチカチ...」
永沢 「おいおい、プログラムはバージョン管理システムに入れてくれよ。SourceTree っていうのがあるからさ。」
ワタナベ 「余計な作業に見えますけれど。履歴がそんなに重要なんですか?」
永沢 「俺は時の洗礼を受けてないものを読んで貴重な時間を無駄に費やしたくないんだ。人生は短い。この Qiita ページの『雑な説明』の設定をしておいてくれ。とくに lvdiffmerge をダウンロードして、SourceTree を設定するところな。」

ワタナベくんは面倒とは思いながらも、 SourceTree をインストールします。lvdiffmerge をダウンロードして、SourceTree の設定もしておきました。

永沢 「じゃあ、まずは空っぽのリポジトリを作ろう。」
ワタナベ 「リポジトリってなんですか?」
永沢 「バージョン管理対象のフォルダーみたいなもんだ。」

blank.png

git-init.png

永沢 「オーケー。lvdiffmerge.txt って名前のテキストファイルを作って、そこに LabVIEW のパスを書いておこう。このページの上に書いてあるやつのコピペでいい。」
ワタナベ 「こうですか?」

lvdiffmerge.txt
SHARED_DIR="C:\Program Files (x86)\National Instruments\Shared"
LABVIEW_EXE="C:\Program Files (x86)\National Instruments\LabVIEW 2015\LabVIEW.exe"

永沢 「そうそう」
ワタナベ 「あれ? SourceTree に何か表示されました。」

new.png

永沢 「新しいファイルが追加されたからね。『作業ツリーのファイル』のリストに、いま追加した lvdiffmerge.txt が表示されている。」
ワタナベ 「そうみたいですね。」
永沢 「ここに表示されているファイルは、変更されたことが分かっているけれど、まだ管理されていない。そこで『Stage All』ボタンをクリックするんだ。」

staged.png

ワタナベ 「やりました。なんか上のほうに移動しましたよ。」
永沢 「オーケー。これで lvdiffmerge.txt がステージされた状態だ」
ワタナベ 「なんですか、それ?」
永沢 「今からこの変更を登録しますよ、っていう意思表示みたいなもんだ。」
ワタナベ 「いきなり変更したらいいじゃないですか?」
永沢 「おいおい本気で言っているのか? 今回はひとつのファイルだが、ファイル数が増えたらどうするんだよ。とくに LabVIEW は VI ごとにファイルが作られるんだぜ? 作業途中の壊れまくってるVIの面倒をみるのは、俺がごめんだよ。」
ワタナベ 「あなたらしいですね。」
永沢 「分かればいい。じゃあこんどは、ほんとうに変更を登録しよう。下のコミットメッセージ欄に変更内容を書いて、コミットをクリックだ。」

initial commit.png

ワタナベ 「何も表示されなくなりましたよ」
永沢 「それでいい。あ、しまった」
ワタナベ 「どうしました?」
永沢 「今回は、LabVIEW 2014 を使うんだった。悪いけど lvdiffmerge.txtの内容を書き直してもらえないかな」

lvdiffmerge.txt
SHARED_DIR="C:\Program Files (x86)\National Instruments\Shared"
LABVIEW_EXE="C:\Program Files (x86)\National Instruments\LabVIEW 2014\LabVIEW.exe"


modified.png

ワタナベ 「書き直したら、また SourceTree の画面が変わりましたね」
永沢 「そうなんだ。変更した箇所が表示される。」
ワタナベ 「またステージして、コミットすればいいですか?」
永沢 「そのとおり。飲み込みがいいな」
ワタナベ 「おかげさまで。ステージ....、コミット...と。やりましたよ。」
永沢 「左のペーンの master ってところをクリックしてみろよ」

second commit tree.png

ワタナベ 「へぇ。これまでの変更履歴が表示されますね」
永沢 「ああ。これでいつ、どんな変更をしたか分かる。それにさ、好きなリビジョンをダブルクリックしたら、そのバージョンでのファイルが戻ってくるんだ。便利だろ?」
ワタナベ 「そんなに便利だとは思えませんがね」
永沢 「そんなに便利なんだよ。じゃ、そこに VI を追加しておいてくれ。」
ワタナベ 「分かりました。」

first vi.png

ワタナベ 「こんな感じでいいですか?」
永沢 「いいね。コミットしておいてくれ」
ワタナベ 「しておきます」
永沢 「あ、そうだ。俺に確認しなくても、どんどんコミットしておけばいい。元に戻したくなったら、いつでも戻せるんだから。さ、早めの昼飯にしよう」
ワタナベ 「早すぎませんか? 僕はこれから遅めの朝飯だっていうのに」
永沢 「食べるものも同じで、食べる時間も同じで、ただ呼び方がちがうだけだ。」

Diff

永沢 「今日の定食だけどさ。お前のほうがうまそうだったな」
ワタナベ 「同感ですね」
永沢 「明日、顧客に見せてくるんだ。それで頼みがあるんだが、さっきのVIな。周波数を変更できるようにしておいて欲しいんだ。」

changed.png

ワタナベ 「聞いていいですか?」
永沢 「なんだい?」
ワタナベ 「コミットする前に、テキストファイルの変更点は SourceTree で確認できますよね。でも VI は確認できないんですよ。ほら。」

blank diff.png

永沢 「ああ、そうだ。肝心なことを忘れてたな。VIを選択して、右クリック。で、そのメニューから 外部diffを選ぶんだ」

ext diff.png

ワタナベ 「ああ、これで LabVIEW の比較ツールが立ち上がるわけですね。」
永沢 「そういうことだ。比較ツールで何を変更したか確認してから、コミットメッセージを書くといいね。」

diff.png

ワタナベ 「コミットしておきます。」
永沢 「サンキュー」

branch

永沢 「俺はそろそろ、顧客のところに行くんだけどさ。その前に、ブランチを切っておいてくれ」
ワタナベ 「なんですかそれは?」
永沢 「バージョン管理の分岐点を作るんだよ。手順としては、分岐させたいバージョンを選択して、『ブランチ』をクリックする」

branch.png

ワタナベ 「こうですか?」
永沢 「そうだ。それで適当にブランチ名をつけておけばいい。で、左ペーンのブランチのところで、今作ったブランチをダブルクリックしておくんだ。」

branch name.png

永沢 「俺が出かけている間、他のパラメータ指定を追加しておいて欲しいんだよ。ワタナベの変更はすべて、そのブランチにコミットすることになる。」
ワタナベ 「なんでわざわざ分けるんですか?」
永沢 「おいおい。俺だって客先でVIの変更できるんだぜ。分けておけば、誰が何を変更したか管理しやすくなる。じゃあ、行ってくるよ」

というわけで、ワタナベくんは、追加の作業をしました。

more indicators.png

これをコミットすると、以下のようになります。

commit to branch.png

Merge

ワタナベ 「永沢さん、おはようございます。昨日はどうでした?」
永沢 「大したことないよ。ひとつ変更が出た。」
ワタナベ 「どんな変更ですか?」
永沢 「集録した波形を見る必要なくて、スペクトルだけ見たいそうだ」
ワタナベ 「なるほど。じゃあ変更しますね」
永沢 「いや、その必要はない。客先で変更して、確認をしてもらってある。」

fft.png

ワタナベ 「これを統合するわけですね。手間がかかりますね」
永沢 「ときどき俺は世間を見まわして本当にうんざりするんだ。どうしてこいつらは努力というものをしないんだろう、努力もせずに不平ばかり言うんだろうってね。」
ワタナベ 「そうは言っても、他の人だって手間ひまかけて、あくせく働いているように見えますけどね」
永沢 「あれは努力じゃなくてただの労働だ。俺のいう努力というのはそういうのじゃない。努力というのはもっと主体的に目的的になされるもののことだ。いいか、まず、俺が出かけるまえのバージョンに戻すんだ」

checkout.png

ワタナベ 「ここですね? ここでダブルクリックしたらいいですか?」
永沢 「そうだ。それで、昨日、俺が出かける前のVIが復元される。その状態で、俺のVIを上書き保存して、コミットするんだ。」
ワタナベ 「おやすい御用です。」

premerge.png

永沢 「master が俺の作業履歴、more-works がワタナベの作業履歴だ」
ワタナベ 「なるほど」
永沢 「次に『マージ』ってボタンをクリックすると、ダイアログが出る。そこで、more-works の先頭のバージョンを選択して、マージするんだ」
ワタナベ 「やってみましょう」

merge.png

ワタナベ 「エラーが出ましたよ」

merge error.png

永沢 「構わない。ワタナベと俺が、同じVIを別々に変更したので、単純に更新ができないだけだ。エラーのダイアログを閉じて、元のダイアログも『閉じる』をクリックする」
ワタナベ 「分かりました。でも、どうするんですか?」
永沢 「慌てなくていい。その main.vi を右クリック → 競合を解決 → 外部のマージツールを起動、だ。ちょっと時間がかかるが、統合ツールが開く。」

resolve.png

ワタナベ 「出ましたよ」

lv merge.png

永沢 「それでいい。左側には、上から順にワタナベのVI、昨日までのVI、俺のVIの順に並んでいる。右下のそれぞれの変更リストがある。どれを採用するかを選んでいくと、右上に反映される。」
ワタナベ 「ああなるほど。ちょうどよい感じに変更するわけですね。」
永沢 「そういうことだ」
ワタナベ 「でも、どうしても統合されない箇所がありますよ。」
永沢 「そういうことだってあるさ。そのときは後で自分で修正するんだよ。できるところまでやったら『閉じる』→『保存する』だ。」
ワタナベ 「はい。」
永沢 「統合しきれなかった箇所があれば、VIを開いて手動で調整する」
ワタナベ 「はい、やりました」
永沢 「SouceTree で main.vi を右クリック → 競合を解決 → 解決とマーク、したらオーケーだ。コミットできるようになる。」

mark resolved.png

ワタナベ 「なんとなく分かってきましたよ。これで、コミットしますね。この main.vi.orig ってなんですか?」
永沢 「競合を解決する前の VI さ。もう要らないから消していい。これでワタナベの変更と俺の変更がマージされた」

merged.png

永沢 「さあ、街に出て、女の子を抱きに行こう」
ワタナベ 「やれやれ」

捕捉

  • LabVIEWGitEnv という、同じ目的のツールがあるのですが、どうも手元の環境では動きませんでした。で、自分でツールを作ったら似たような結果になってしまいました。環境に依存しないように Go で書いたほうがよかったかも。
  • llb ファイルには複数の VI を格納できますが、これはなかなか比較が難しいですね。
  • lvproj ファイルは XML なので、テキスト扱いで diff/merge できます。