# What's your method for resolving resource.json git conflicts?

**URL:** <https://forum.inductiveautomation.com/t/whats-your-method-for-resolving-resource-json-git-conflicts/60096>\
**Category:** Ignition\
**Created:** [May 26, 2022, 9:01pm UTC](https://forum.inductiveautomation.com/t/whats-your-method-for-resolving-resource-json-git-conflicts/60096 "2022-05-26T21:01:51Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![justin.brzozoski](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/justin.brzozoski/32/13452_2.png) [@justin.brzozoski](https://forum.inductiveautomation.com/u/justin.brzozoski)\
**Post date:** [May 26, 2022, 9:01pm UTC](https://forum.inductiveautomation.com/t/whats-your-method-for-resolving-resource-json-git-conflicts/60096/1 "2022-05-26T21:01:51Z")

</div>

My colleagues and I try to follow a pretty normal git development flow: we implement things on temporary branches and do peer-reviewed pull requests to merge those into a main “develop” branch. And after some period of testing and vetting, the “develop” branch is then pulled into a “production” branch.

We still have to be cautious and avoid more than one of us working on the same binary file at the same time, but we’ve been able to work on the same view or script and git was able to merge changes reasonably well.

The resource.json files are driving me nuts, though.

They always conflict, every time we touch anything in a directory, even if the changes in the code.py or view.json or whatever were merged gracefully by git.

I know we could just jump them to a clean-but-mismatched version by using something like `git checkout --ours`. But then we will have a commit in our history that if checked out will trigger a gateway to regenerate the resource.json and leave uncommitted files sitting around, which makes subsequent git operations propblematic. So the proper thing to do is to let Ignition re-generate them after resolving the conflict and roll that into the commit.

But I usually have Ignition stopped so it doesn’t freak out on conflict markers in files, which means my merge/rebase process now involves starting and stopping Ignition gateway after every conflict just to re-scan files and re-generate resource.json files.

Does anyone else have a better method of dealing with this? I know the IA team has a plan to let users control when Ignition re-scans the projects directories, which would at least let me keep Ignition running, but that feature isn’t here yet.

I’m mostly just venting, but also adding a little more weight to the feature request to control directory scanning manually.

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [May 26, 2022, 9:14pm UTC](https://forum.inductiveautomation.com/t/whats-your-method-for-resolving-resource-json-git-conflicts/60096/2 "2022-05-26T21:14:52Z")

</div>

The issue is that resource.json is composed of both user-supplied metadata and calculated metadata. The former belongs in git, the latter does not. This will not be resolved until IA redesigns how this file works.

IMNSHO.

{ Maybe in v8.2 ? }

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [May 26, 2022, 9:53pm UTC](https://forum.inductiveautomation.com/t/whats-your-method-for-resolving-resource-json-git-conflicts/60096/3 "2022-05-26T21:53:30Z")

</div>

I wonder if a standalone CLI utility could be created to generate valid signatures…

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [May 27, 2022, 12:19am UTC](https://forum.inductiveautomation.com/t/whats-your-method-for-resolving-resource-json-git-conflicts/60096/4 "2022-05-27T00:19:24Z")

</div>

Sigh. /:

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [May 27, 2022, 12:26am UTC](https://forum.inductiveautomation.com/t/whats-your-method-for-resolving-resource-json-git-conflicts/60096/5 "2022-05-27T00:26:21Z")

</div>

As a workaround for 8.1. I do think we’re planning to revamp this in 8.2.

---

<div class="post-metadata">

**Author:** ![justin.brzozoski](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/justin.brzozoski/32/13452_2.png) [@justin.brzozoski](https://forum.inductiveautomation.com/u/justin.brzozoski)\
**Post date:** [May 27, 2022, 5:32pm UTC](https://forum.inductiveautomation.com/t/whats-your-method-for-resolving-resource-json-git-conflicts/60096/6 "2022-05-27T17:32:36Z")

</div>

If a CLI tool existed I would use it. But I also agree that the files should be revamped in the long run to avoid the issue entirely.

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [May 27, 2022, 11:32pm UTC](https://forum.inductiveautomation.com/t/whats-your-method-for-resolving-resource-json-git-conflicts/60096/7 "2022-05-27T23:32:03Z")

</div>

Well, it’s not currently very useful, but in case it helps anyone as a starting point, I made a thing:

> **[GitHub - paul-griffith/modification-updater](https://github.com/paul-griffith/modification-updater)**
>
> Contribute to paul-griffith/modification-updater development by creating an account on GitHub.

Download the latest built jar from here: [Update readme · paul-griffith/modification-updater@137aaac · GitHub](https://github.com/paul-griffith/modification-updater/actions/runs/2399231200)  
Run it with any Java 17 build on the command line:  
 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/f/4/f4846742d02d426a44b060f9c77d4f7aee6de0b5.png)

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/3/0/30fece437c4dde1251feed7b30bf70673da5815e.png)

You could, in theory, hook this in to Git in some way to automatically update the `resource.json` files _before_ overwriting them in the resource directory, and, since the signature will be valid, Ignition won’t overwrite them again later.

---

<div class="post-metadata">

**Author:** ![justin.brzozoski](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/justin.brzozoski/32/13452_2.png) [@justin.brzozoski](https://forum.inductiveautomation.com/u/justin.brzozoski)\
**Post date:** [May 31, 2022, 4:52pm UTC](https://forum.inductiveautomation.com/t/whats-your-method-for-resolving-resource-json-git-conflicts/60096/8 "2022-05-31T16:52:56Z")

</div>

I’ll give it a try. If it saves me from cycling Ignition on/off repeatedly, I’m happy.

Of course, almost immediately I did this:

```auto
$ java -jar ~/bin/modification-updater.jar . > resource.json 
Exception in thread "main" kotlinx.serialization.json.internal.JsonDecodingException: Expected start of the object '{', but had 'EOF' instead at path: $

```

Works fine as `java -jar modification-updater.jar . > r0 && mv r0 resource.json` though, so no biggie. Just made me chuckle that the most obvious usage pattern blows away the input file before it can read it.

---

<div class="post-metadata">

**Author:** ![justin.brzozoski](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/justin.brzozoski/32/13452_2.png) [@justin.brzozoski](https://forum.inductiveautomation.com/u/justin.brzozoski)\
**Post date:** [June 7, 2022, 9:05pm UTC](https://forum.inductiveautomation.com/t/whats-your-method-for-resolving-resource-json-git-conflicts/60096/9 "2022-06-07T21:05:18Z")

</div>

The gateway is fine with the resource.json files that tool makes, but Designer is more finicky about the date format. 🤕

```auto
com.inductiveautomation.ignition.common.gson.JsonParseException: unable to parse utc timestamp: 2022-06-06T18:58:26.091320830Z
	at com.inductiveautomation.ignition.common.project.resource.LastModification$GsonAdapter.deserialize(LastModification.java:161)
	at com.inductiveautomation.ignition.common.project.resource.LastModification$GsonAdapter.deserialize(LastModification.java:129)
	at com.inductiveautomation.ignition.common.gson.internal.bind.TreeTypeAdapter.read(TreeTypeAdapter.java:69)
	at com.inductiveautomation.ignition.common.gson.Gson.fromJson(Gson.java:927)
	at com.inductiveautomation.ignition.common.gson.Gson.fromJson(Gson.java:994)
	at com.inductiveautomation.ignition.common.gson.Gson.fromJson(Gson.java:967)
	at com.inductiveautomation.ignition.common.project.resource.LastModification.fromJson(LastModification.java:61)
	at com.inductiveautomation.ignition.common.util.ResourceUtil.lambda$static$0(ResourceUtil.java:57)
	at java.base/java.util.TimSort.binarySort(Unknown Source)
	at java.base/java.util.TimSort.sort(Unknown Source)
	at java.base/java.util.Arrays.sort(Unknown Source)
	at java.base/java.util.ArrayList.sort(Unknown Source)
	at java.base/java.util.stream.SortedOps$RefSortingSink.end(Unknown Source)
	at java.base/java.util.stream.Sink$ChainedReference.end(Unknown Source)
	at java.base/java.util.stream.AbstractPipeline.copyIntoWithCancel(Unknown Source)
	at java.base/java.util.stream.AbstractPipeline.copyInto(Unknown Source)
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(Unknown Source)
	at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(Unknown Source)
	at java.base/java.util.stream.AbstractPipeline.evaluate(Unknown Source)
	at java.base/java.util.stream.ReferencePipeline.collect(Unknown Source)
	at com.inductiveautomation.ignition.designer.workspacewelcome.RecentlyModifiedTablePanel$RecentlyModifiedModel.lambda$new$1(RecentlyModifiedTablePanel.java:140)
	at com.inductiveautomation.ignition.designer.workspacewelcome.RecentlyModifiedTablePanel$RecentlyModifiedModel.<init>(RecentlyModifiedTablePanel.java:144)
	at com.inductiveautomation.ignition.designer.workspacewelcome.RecentlyModifiedTablePanel.<init>(RecentlyModifiedTablePanel.java:56)
	at com.inductiveautomation.ignition.designer.scripteditor.workspace.WorkspaceEditor$2.createPanels(WorkspaceEditor.java:78)
	at com.inductiveautomation.ignition.designer.workspacewelcome.WorkspaceWelcomePanel.<init>(WorkspaceWelcomePanel.java:78)
	at com.inductiveautomation.ignition.designer.scripteditor.workspace.WorkspaceEditor$2.<init>(WorkspaceEditor.java:53)
	at com.inductiveautomation.ignition.designer.scripteditor.workspace.WorkspaceEditor.<init>(WorkspaceEditor.java:50)
	at com.inductiveautomation.ignition.designer.scripteditor.workspace.ScriptWorkspace.<init>(ScriptWorkspace.java:66)
	at com.inductiveautomation.ignition.designer.IgnitionDesigner.loadProject(IgnitionDesigner.java:956)
	at com.inductiveautomation.ignition.designer.IgnitionDesigner$StartupProjectDialogHandler.lambda$new$2(IgnitionDesigner.java:2021)
	at java.base/java.lang.Thread.run(Unknown Source)

Ignition v8.1.17 (b2022051210)
Java: Azul Systems, Inc. 11.0.15

```

But it was definitely faster using that tool to adjust the hashes than starting/stopping the gateway! 🙂

Looks like the Designer parser just doesn’t like the absurd precision the tool added on the seconds. I’m trying to figure out the syntax to wrangle the DateFormatter line in your code. First time ever using Kotlin! Let’s see if I can wing it.

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [June 7, 2022, 9:41pm UTC](https://forum.inductiveautomation.com/t/whats-your-method-for-resolving-resource-json-git-conflicts/60096/10 "2022-06-07T21:41:00Z")

</div>

Well, I’m a lot less confident in this than the Kotlin version, but I wanted a learning project, so last week I ~recreated the CLI above in Rust:

> **[GitHub - paul-griffith/modification-updater-rs](https://github.com/paul-griffith/modification-updater-rs)**
>
> Contribute to paul-griffith/modification-updater-rs development by creating an account on GitHub.

I don’t know if it’ll work across all possible resources, but it’s guaranteed to be a lot faster:

```auto
time java -jar build/libs/modification-updater.jar -s src/test/resources/script
7ea951abc0ddc97f549f41a5670b06aa513b30e189050159f40e207cfe502b02
0.12s user 
0.03s system 
118% cpu 
0.123 total
time target/release/rust_experiments test/script
7ea951abc0ddc97f549f41a5670b06aa513b30e189050159f40e207cfe502b02
0.00s user
0.00s system 
38% cpu 
0.006 total

```

And I’m pretty sure it has the correct date-time formatting output 🙂

---

<div class="post-metadata">

**Author:** ![justin.brzozoski](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/justin.brzozoski/32/13452_2.png) [@justin.brzozoski](https://forum.inductiveautomation.com/u/justin.brzozoski)\
**Post date:** [June 8, 2022, 6:45pm UTC](https://forum.inductiveautomation.com/t/whats-your-method-for-resolving-resource-json-git-conflicts/60096/11 "2022-06-08T18:45:12Z")

</div>

The Rust one has some issues:

```auto
com.inductiveautomation.ignition.common.gson.JsonSyntaxException: com.inductiveautomation.ignition.common.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 16 column 2 path $

```

But I’m learning Rust, so I’m more prepared to fix coding issues in this one.

Don’t prioritize fixing this tool unless you’re having fun.

---

<div class="post-metadata">

**Author:** ![kcollins](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kcollins/32/19646_2.png) [@kcollins](https://forum.inductiveautomation.com/u/kcollins)\
**Post date:** [June 8, 2022, 6:58pm UTC](https://forum.inductiveautomation.com/t/whats-your-method-for-resolving-resource-json-git-conflicts/60096/12 "2022-06-08T18:58:34Z")

</div>

> [@justin.brzozoski](#):
>
> Don’t prioritize fixing this tool unless you’re having fun.

Disclaimer: it can be difficult to beat Paul G. to a Pull Request 😉 .. ![cde50dc23177881f](https://us1.discourse-cdn.com/inductiveautomation/original/3X/4/7/4742e95b8142f1755776e775c72c13c8deefdfff.gif)

---

<div class="post-metadata">

**Author:** ![reto.kunz](https://avatars.discourse-cdn.com/v4/letter/r/6a8cbe/32.png) [@reto.kunz](https://forum.inductiveautomation.com/u/reto.kunz)\
**Post date:** [June 9, 2022, 9:51am UTC](https://forum.inductiveautomation.com/t/whats-your-method-for-resolving-resource-json-git-conflicts/60096/13 "2022-06-09T09:51:11Z")

</div>

Thank you for that tool, it could be very handy to implement a workaround to handle resource files for the moment!

Especially the rust tool which is really performant. However I found a small bug there: The timestamp is not the current timestamp as stated in the readme, but is always “2022-05-27T16:47:43Z”.

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [June 9, 2022, 3:33pm UTC](https://forum.inductiveautomation.com/t/whats-your-method-for-resolving-resource-json-git-conflicts/60096/14 "2022-06-09T15:33:58Z")

</div>

> [@reto.kunz](#):
>
> Especially the rust tool which is really performant. However I found a small bug there: The timestamp is not the current timestamp as stated in the readme, but is always “2022-05-27T16:47:43Z”.

Yeah, @justin.brzozoski noticed that too. If you update the repository it should be correctly using the current local time.

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [June 11, 2022, 12:14am UTC](https://forum.inductiveautomation.com/t/whats-your-method-for-resolving-resource-json-git-conflicts/60096/15 "2022-06-11T00:14:58Z")

</div>

The rust version has been updated with _some_ edge cases I’ve discovered met, but I also don’t have 100% of tests passing, so I’m happy for help getting that to 100%.

---

<div class="post-metadata">

**Author:** ![reto.kunz](https://avatars.discourse-cdn.com/v4/letter/r/6a8cbe/32.png) [@reto.kunz](https://forum.inductiveautomation.com/u/reto.kunz)\
**Post date:** [July 28, 2022, 8:17am UTC](https://forum.inductiveautomation.com/t/whats-your-method-for-resolving-resource-json-git-conflicts/60096/16 "2022-07-28T08:17:38Z")

</div>

To come back to the original question:

> What’s your method for resolving resource.json git conflicts?

With the tool @paul-griffith created we now use the following workflow with git hookscripts (hopefully temporary):

- Add \*/resource.json to gitignore
  - This is what we have been waiting for all the time 🙂

- pre-commit: pack all resource files in the repository into one big json file. Drop all autogenerated content (signature), add original path information.
  - This way you keep the important metadata and even the last change information (if needed) in your repository. You only have one file that changes and only if you willingly apply changes to project resources.

- post-commit, post-checkout, post-merge: Unpack the packed resource json into the original, individual files. Run the helper tool to generate new valid signatures using the metadata which is stored in the packed json file.
  - This ensures you always have a consistent repository after checking out a new branch and even directly after cloning a new repository.
  - You can slightly modify the rust tool to take your original timestamp and user as parameters if you want to keep this information.

Optional but useful: ensure that git hook scripts are always executed on all systems you are using!

- configure the system wide git setting to use a different hook script path (a path in your repository)
- place the hook scripts in this path in your repository
  - Now if you clone a remote repository which contains the hook scripts, the resource files are automatically unpacked and your project is ready directly after the clone.

Quite an effort only to avoid autogenerated content in the repository, but so far this works just fine. Maybe this helps someone to create his own personalized workaround.

---

<div class="post-metadata">

**Author:** ![Jay\_Baker](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/jay_baker/32/35448_2.png) [@Jay\_Baker](https://forum.inductiveautomation.com/u/Jay_Baker)\
**Post date:** [August 15, 2022, 5:36am UTC](https://forum.inductiveautomation.com/t/whats-your-method-for-resolving-resource-json-git-conflicts/60096/17 "2022-08-15T05:36:02Z")

</div>

Have you tried this one?

> [@Using Git with Ignition projects](https://forum.inductiveautomation.com/t/using-git-with-ignition-projects/60475/4):
>
> Ok, here’s my solution, which mostly seems to work pretty well. Step 1: Create a powershell file called something like ps\_fix\_resource.ps1, containing: filter sed($before,$after) { %{$\_ -replace $before,$after} } $input |sed '"actor": ".\*"' '"actor": "system"'|sed '"timestamp": ".\*"' '"timestamp": "2022-01-01T00:00:00Z"'|sed '"lastModificationSignature": ".\*"' '"lastModificationSignature": "4a15e0122c9a955ca05b407bd9fa06810c1a05bd02f35e6ab4cc38c0654af46"' This replaces your name (as ‘actor’) …

---

<div class="post-metadata">

**Author:** ![reto.kunz](https://avatars.discourse-cdn.com/v4/letter/r/6a8cbe/32.png) [@reto.kunz](https://forum.inductiveautomation.com/u/reto.kunz)\
**Post date:** [August 15, 2022, 6:37am UTC](https://forum.inductiveautomation.com/t/whats-your-method-for-resolving-resource-json-git-conflicts/60096/18 "2022-08-15T06:37:26Z")

</div>

If you can get rid of all the “last modification” information this is an easy way to do it which also works. I thought it was nice to keep as much of this information as possible, but honestly git manages that for you so if it does not cause any problems with Ignition we do not really need it.

---

<div class="post-metadata">

**Author:** ![wpmccormick](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/wpmccormick/32/13940_2.png) [@wpmccormick](https://forum.inductiveautomation.com/u/wpmccormick)\
**Post date:** [March 1, 2023, 8:58pm UTC](https://forum.inductiveautomation.com/t/whats-your-method-for-resolving-resource-json-git-conflicts/60096/19 "2023-03-01T20:58:48Z")

</div>

I feel like there's some missing detail here, so some questions:

1. What would the impact be of ONLY adding \*/resource.json to .gitignore be?
2. I have only a little exp with Rust, and no exp with it on Windoze; If I'm relegated to some highly managed AWS Workspace running Windows, is there hope for making any of this work?
3. Does the Rust _helper tool_ program do all this packing/unpacking?

Thanks!

---

<div class="post-metadata">

**Author:** ![cesrom](https://avatars.discourse-cdn.com/v4/letter/c/ea666f/32.png) [@cesrom](https://forum.inductiveautomation.com/u/cesrom)\
**Post date:** [March 1, 2023, 9:05pm UTC](https://forum.inductiveautomation.com/t/whats-your-method-for-resolving-resource-json-git-conflicts/60096/20 "2023-03-01T21:05:37Z")

</div>

I managed to solve all conflicts by doing the following:

> [@Ignition touching project files every five minutes on Windows](https://forum.inductiveautomation.com/t/ignition-touching-project-files-every-five-minutes-on-windows/65488/8):
>
> In my setup, I already had a .gitattributes global file. So I just had to add the following: Before: \*.md diff=markdown \*.py diff=python After: \* text=auto \*.json text eol=lf \*.md text diff=markdown eol=lf \*.py text diff=python eol=lf I had already set autocrlf to true on my .gitconfig global settings. But @Craig.Lovold's suggestion is what solved this issue. Thanks everyone for your suggestions!

Hope that helps

[Next page](https://forum.inductiveautomation.com/t/whats-your-method-for-resolving-resource-json-git-conflicts/60096.md?page=2)
