MySQL Workbench 个文件的 hg diff

hg diff on MySQL Workbench files

posting this as a Q&A 记录一个似乎经常出现的问题的解决方法——如何将 MySQL Workbench 文件置于版本控制之下——但我一直无法找到任何解决方案。欢迎反馈!

如何让 Mercurial diff 压缩存档的内容并忽略对这些内容的某些更改?具体来说,我如何使用 hg 来区分 MySQL Workbench (.mwb) 文件的内容,忽略 MySQL [=49] 的许多不重要的更改=] 使每次文件被打开?我可以使用忽略某些不相关更改的自定义脚本吗?

背景

我正在尝试 diff hg 存储库中的文件。文件 document.mwb.xml 是从 .mwb 文件(MySQL Workbench 模型文件)中提取的 XML 文档。基本上,我希望将模型的内容——table 结构、可视化模型等——置于版本控制之下,但不提交 .mwb 文件本身,它是一个 zip 存档,因此是一个二进制文件文件。

每当我保存 .mwb 文件时,我都会解压缩它。我将解压缩的内容保存在我的存储库中,当我需要使用 MySQL.

中的 .mwb 时,只需再次压缩它们

有问题的 XML 看起来像这样:

<?xml version="1.0"?>
<data grt_format="2.0" document_type="MySQL Workbench Model" version="1.4.4">
  <value type="object" struct-name="workbench.Document" id="8551CCFA-3AD0-4207-BC76-15ED589CF22C" struct-checksum="0x7131bf99">
    <value type="object" struct-name="workbench.logical.Model" id="B48E1CD2-3386-40B7-8E59-AA191598F667" struct-checksum="0xf4220370" key="logicalModel">
      <value _ptr_="0x7fbcd1cc3270" type="list" content-type="object" content-struct-name="workbench.logical.Diagram" key="diagrams"/>
      <value _ptr_="0x7fbcd1cc3210" type="dict" key="customData"/>
      <value _ptr_="0x7fbcd1cc32d0" type="list" content-type="object" content-struct-name="model.Marker" key="markers"/>
      <value _ptr_="0x7fbcd1cc3330" type="dict" key="options"/>
      <value type="string" key="name"></value>
      <link type="object" struct-name="GrtObject" key="owner">8551CCFA-3AD0-4207-BC76-15ED589CF22C</link>
    </value>
    <value _ptr_="0x7fbcd1cc2b70" type="list" content-type="object" content-struct-name="workbench.OverviewPanel" key="overviewPanels"/>
    <value _ptr_="0x7fbcd1cc2c00" type="list" content-type="object" content-struct-name="workbench.physical.Model" key="physicalModels">
      <value type="object" struct-name="workbench.physical.Model" id="34B9E967-5C9B-4D1B-8759-C417F6C33AA3" struct-checksum="0x5f896d18">
...

问题在于所有这些 _ptr_ 属性:此文件中实际上有数千个属性,并且每次保存文件时每个属性都会发生变化,即使没有任何修改也是如此。结果,存储库可能会迅速变得杂乱无章,因为对此文件进行了完全无意义的“更改”。

有没有办法使用自定义 diff 例程来忽略这些不相关的更改?

我还没有找到真正的解决方案,但受此 mwb-diff gist 启发,我开发了一个令人满意的解决方法。这允许我解压和区分 .mwb 文件的内容,将这些内容及其更改提交到存储库,并在必要时正常使用 .mwb

项目结构

我的项目是这样设置的:

project_root
    /dist
    /schema
    /src
    /test

我保存 .mwb 文件 - 将其命名为 MyModel.mwb - 在 project_root/schema 中。显然,您可以使用不同的结构,但您需要相应地修改下面的说明。

剧本

我创建了以下脚本并将它们保存在 project_root/schema:

unpack.sh

#!/bin/bash

# Unzip the model (MyModel.mwb) into a particular directory (project_root/schema/MyModel)
unzip -o MyModel.mwb -d MyModel/

# Replace all _ptr_="...." attributes with _ptr_="xxx"
sed -i presed -E 's/_ptr_="0x[0-9a-f]+"/_ptr_="xxx"/g' MyModel/document.mwb.xml

pack.sh

#!/bin/bash

# This file goes into the directory containing the model contents, zips them up, and saves them as a .mwb model

cd MyModel/
zip -r ../MyModel.mwb ./* -x lock
cd ..

让 Mercurial 准备好摇滚

我们需要告诉 hg 忽略模型(以及所有其他 .mwb 文件)。此外,当 MySQL Workbench 打开时,它会在 .mwb 存档中添加一个 lock 文件,我们需要忽略它。因此,将这些行添加到您的 .hgignore 文件中:

*.mwb
*.mwb.bak
schema/MyModel/lock

An Aside About the data.db File

Optionally, also ignore the data.db file (a SQLite database) in the .mwb file. It is a binary file that contains any INSERTs or other non-create SQL statements that are part of your model. As a rule, I don't use MySQL Workbench for this stuff; I use it only to create and edit tables, views, etc. So, I added this line to .hgignore:

schema/MyModel/data.db

If you want to track changes to the data.db file, you may need to modify this workaround.

如何使用脚本

当您要修改 .mwb 文件时,请通过上面的 运行ning pack.sh 从其组件重建它。这可以作为 hook 添加,以便在您 hg pull、更新等时自动发生,但我还没有探索过这一点。

当您完成 .mwb 文件的编辑并想要提交您的更改时,运行 unpack.sh 脚本。如果需要,您可以在系统上设置一个文件监视实用程序,以便在文件更改时自动执行此操作,但这超出了本答案的范围。

结果

Mercurial 现在非常乐意跟踪对 .mwb 文件内容的更改,而无需跟踪数以千计显然无用的 _ptr_ 属性。此外,当我将其与 Mercurial 一起使用时,基本逻辑(和 shell 脚本)将适用于 git、SVN 等

重要警告: 据我所知,_ptr_ 属性是无关紧要的。我上面发布的脚本实际上替换了那些属性的内容。 _ptr_="0x98a7b3e4"(或其他)变为 _ptr_"xxx"。根据我的测试,这无关紧要,MySQL Workbench 将愉快地使用重构文件,显然无视 _ptr_ 值。 我可能错了,这些值可能很重要!强烈建议您在依赖我的解决方案之前亲自测试一下。