DBFluteでgitコンフリクト (Conflict)

概要

DBFluteでgitコンフリクトが起きた場合、起きないようにする方法など。

DBFluteのファイルは大きく四つ

自動生成ファイル (by DBFlute)
BehaviorやEntity, SchemaHTMLなど
元ファイル (by 人間)
dfpropファイルやDDLやTSVなど
蓄積ファイル (by DBFlute)
履歴のdiffmap, decomment-pickup, (SchemaXML)
一時ファイル (by DBFlute)
playsqlのdfmarkなど

DB変更から自動生成までの関連ファイル

e.g. DB変更から自動生成までの関連ファイル @Java

  o                       +---------------------+
 /|\ -------------------> | ERD tool (ERFlute)  | --(save)--> .erm file
 /\                      +---------------------+
 |                                |
  |                                +--(export)-----------------+
  |                                                            |
  |          +--- DBFlute Client -----------------------------/T\-------+
  |          |                                                 |
  |          |     +---- dfprop ------------------------------/T\---+
  |          |     |                                           |
  +-(mod)---/T\--> |   additioinalForeignKey.dfprop            |
  |          |     |   basicInfoMap.dfprop                     |
  |          |     |   ...                                     |
  |          |     +------------------------------------------/T\
  |          |                                                 |
  |          |                                                 |
  |          |     +---- playsql -----------------------------/T\----+
  |          |     |                                           |
  |          |     |            NextDDL  <--(export)-----------+
  |          |     |
  |          |     |                            <--(ref)---+
  +-(mod)---/T\---------------> TSV (test data)            |
  |          |     |                                       |
  |          |     |                                    ReplaceSchema
  |          |     |
  +-(mod)---/T\---------------> AlterDDL        <--(ref)---+
  |          |     |                                       |
  |          |     |                                    AlterCheck
  |          |     |
  |          |     +-------------------------------------------------+
(Replace     |
  Schema)    |
  |          |
  |          |     +---- schema -------------------------------------+
  |          |     |
(JDBC)------/T\--> |   SchemaXML (project-schema-...xml)
  |          |     |   HistoryDiffmap (project-history-...diffmap)
  |          |     |                             ^
  |          |     |                             | (make)
  |          |     |                             +- JDBC
  |          |     |   CraftDiffMeta (previous|next.tsv)
  |          |     |
  |      +--/T\---/T\--> DecommentPickup (decomment-pickup.dfmap)
  |      |   |     |                             ^
  |      |   |     |                             | (make from pieces)
  |      |   |     |                             +- Doc
  |      |   |     |
  |      |   |     +-------------------------------------------------+
  |      |   |
  |      |   |
  |      |   |     +---- output/doc ---------------------------------+
  |      |   |     |
(Doc)----+--/T\--> |   SchemaHTML (schema-...html)
  |          |     |   HistoryHTML (history-...html)
  |          |     |   PropertiesHTML (properties-...html)
  |          |     |                             ^
  |          |     |                             | (make)
  |          |     |                             +- Doc
  |          |     |
  |          |     +-------------------------------------------------+
  |          |
  |          +----------------------------------------------------------+
  |
  |            +---- src/main/java or resources --------------------+
  |            |
  |            |    +-- base world ------------------------------+
(Generate)---> |    |  allcommon
  |            |    |  bsbhv
(Sql2Entity)-> |    |  bsentity
  |            |    |  cbean.bs
  |            |    |  cbean.cq.bs
  |            |    |  cbean.cq.ciq
  |            |    |  cbean.cq.nss
  |            |    +--------------------------------------------+
  |            |
  |            |    +-- extended world --------------------------+
  |            |    |  cbean
  +--(mod)----/T\-> |  cbean.cq
  |            |    |  exbhv
  |            |    |  exentity
  |            |    +--------------------------------------------+
  |            |
  |            |    +-- resouces --------------------------------+
  |            |    |  Di xml (if Lasta)
  |            |    +--------------------------------------------+
  |            |
  |            |                             ^
  |            |                             | (make)
  |            |                             +- Generate
  |            |                                Sql2Entity
  |            |
  |            +----------------------------------------------------+

コンフリクトが発生した場合

ひとまず今コンフリクトが発生してしまった場合のアプローチを紹介します。

自動生成されたファイルは自動生成し直し

自動生成されたファイルは丁寧にマージする必要はありません。

  • dbfluteパッケージのbase系クラスたち (allcommon, bsbhvなど)
  • output/docのHTMLファイルたち (SchemaHTMLなど)

自動生成の元になっているファイルたち (dfpropなど) がコンフリクトしていたら、それらを先にマージして自動生成し直せばOKです。

  1. 元ファイル、蓄積ファイルのコンフリクトを丁寧にマージ
  2. もういちど自動生成を実行して上書き

dfpropファイルは丁寧にマージ

その元ファイルの代表です。dfpropファイルは人が修正していますから、他人の修正と自分の修正をマージしましょう。

schema配下のSchemaXMLは丁寧にマージ

schema配下は基本的に蓄積ファイルと言えます。丁寧にマージしないとデータをロスしてしまいます。

SchemaXMLはDDLから導出されるものなので、一瞬マージしなくてもいいように思えますがHistoryDiffmapの導出に利用されるので、できるだけ手動でマージしましょう。

(どうしても難しければ、playsqlのマージを先にやってReplaceSchemaだけを実行して導出しても良いとは思います)

schema配下のHistoryDiffmapは丁寧にマージ

HistoryDiffmap (project-history...diffmap) は、DBFluteクライアント/output/doc配下に作成されるHistoryHTMLの元データです。 DBFluteによって出力されますが、これは自動生成ファイルではなく蓄積ファイルなので丁寧にマージしましょう。 (@until 1.2.5)

DBFlute-1.2.6よりファイル構成が変わり、コンフリクトしないように調整されました。

schema配下のcraft-metaファイルは丁寧にマージ

これもdiffmapと似たようなもので、DBFluteが集めたDBデータの差分の蓄積データです。丁寧にマージしましょう。

schema配下decommentのpickupファイルは丁寧にマージ

これもdiffmapと似たようなもので、DBFluteが集めたdecommentの蓄積データです。丁寧にマージしましょう。 ただ、pickupDatetimeの日時がコンフリクトしてるだけのケースが多いでしょう。日時は最新の方を優先でOKです。

playsql配下のファイル (DDLやTSVなど) は丁寧にマージ

playsqlも元ファイルと言えます。これらファイルからスキーマが作成されて自動生成につながります。

DDLがERDツールなどから自動生成されている場合は、ERDファイル自体をマージしましょう。 (ERFluteであれば、大抵の場合は自動マージが可能です)

一方で、tsv-data-result.dfmarkなどのReplaceSchemaのデータ登録処理の出力結果などは、一時的な出力情報ということなので、ReplaceSchemaし直して上書きすればOKです。

コンフリクトしないためには?

A. 自動生成タスクは代わりばんこに

例えば、alter_dbブランチというDB変更や自動生成を実施する専用のブランチを作成して、複数の人が同時に自動生成を実行しないようにします。

ただ、人間的な運用が必要です。そのブランチの修正者が同時に必ず一人になるようにチーム内でうまく情報共有しましょう。

(これが一番多いパターンです)

長いスパンの別ブランチ開発があってどうしても並列でDB変更と自動生成を行う場合は、本線とマージするときにコンフリクトが発生し自動生成し直しと丁寧マージが必要にはなるでしょう。 (そこは時々なので許容してマージ頑張るということになるでしょう)

B. 自動生成クラスのBsクラスをgitignoreに

自動生成されるクラスやファイルをgitignoreにすることで、自動生成ファイルのコンフリクトは発生しません。 ただ、各開発者にはブランチを切り替えるたびにつどつど自動生成 (renewal or regenerate) をしてもらう必要があります。

  • allcommonパッケージ
  • bsbhvパッケージ
  • bsentityパッケージ
  • cbean.bsパッケージ
  • cbean.cq.bsパッケージ
  • cbean.cq.ciqパッケージ
  • cbean.nssパッケージ
  • DIコンテナ用の設定ファイル (e.g. dbflute.xml)
  • SchemaHTML: DBFluteクライアント/output/doc/schema-*.html
  • HistoryHTML: DBFluteクライアント/output/doc/history-*.html
  • PropertiesHTML: DBFluteクライアント/output/doc/properties-*.html
  • LastaDoc: DBFluteクライアント/output/doc/lasta-*.html (Lastaのみ)
  • playsql/data配下のdfmark: (e.g. xls-data-result.dfmark, tsv-data-result.dfmark)
e.g. src/main/javaのdbfluteパッケージ配下の.gitignore @Java
# DBFlute GenIgnored
## Base packages
/allcommon
/bsbhv
/bsentity
/cbean/bs
/cbean/cq/bs
/cbean/cq/ciq
/cbean/nss
e.g. src/main/resources配下の.gitignore (LastaFluteの場合のみ) @Java
# DBFlute GenIgnored
## Di xml for LastaFlute
/dbflute*.xml
e.g. DBFluteクライアントのoutput/doc配下の.gitignore @Java
# DBFlute GenIgnored
## output documents
/schema-*.html
/history-*.html
/properties-*.html
/lastadoc-*.html

ただし、HistoryHTMLの履歴データである schema/project-history-*.diffmap は、ignoreにしてはいけません。 これはDDLだけでは再現できない情報なので蓄積させる必要があります。また、decommentやhacommentのpieceファイルやpickupファイルも同様です。 これらは、自動生成ファイルというよりは、DBFluteが保存しているファイルと言えます。

一方で、自動生成ではないファイルのコンフリクトは変わらず丁寧にマージする必要はあります。

また、SavePreviousのファイルは、自動生成とは別のライフサイクルなので一概にignoreにはできないでしょう。 (クラスの自動生成と SavePrevious は別物と考えたほうが良いです)

C. 自動生成し直しと丁寧マージをしっかり

割り切ってみんなで丁寧にマージしていこうというやり方も可能性としてはあります。

本ページのコンフリクトが発生した場合を参考に、各々が自動生成し直しマージを実施します。

中途半端なignoreは非推奨

例えば、SchemaHTMLだけignore、HistoryHTMLだけignore、というような中途半端なignoreはオススメしていません。強く非推奨です。

各開発者がローカルで自動生成を行う義務がなければ、結局それらファイルはローカルに存在しないことになり、それら機能が活用されなくなってしまうからです。

DBFluteの機能は地味なものだらけで、その機能のためにわざわざ狙って何か実行するってことにはなりにくいのですが、目の前にあれば便利だなって感じるような機能が多いです。 ゆえに、開発者としては、中途半端なignoreは避けてもらいたいという気持ちがあります。 (ignoreにするなら、全ての自動生成ファイルをignoreにするようにした方が良いのかなと)

一方で、decommentサーバー方式を採用していて、SchemaHTMLなどは社内サーバー上の DBFlute Intro経由で閲覧するような仕組みになっていればまた話は別です。

一方で一方で、playsql/data配下のdfmarkなどは元々一時的な出力のものなので、これらはピンポイントでignoreしても良いでしょう。