{"id":19324362,"url":"https://github.com/frblondin/gitobjectdb","last_synced_at":"2025-04-22T19:32:39.785Z","repository":{"id":59820132,"uuid":"137947514","full_name":"frblondin/GitObjectDb","owner":"frblondin","description":"Configuration management versioning stored in Git. See https://gitobjectdb.readthedocs.io","archived":false,"fork":false,"pushed_at":"2025-01-06T08:20:38.000Z","size":35802,"stargazers_count":8,"open_issues_count":0,"forks_count":6,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-04-02T03:43:09.545Z","etag":null,"topics":["configuration-management","csharp","git","net"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/frblondin.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-06-19T21:28:46.000Z","updated_at":"2025-01-06T08:17:52.000Z","dependencies_parsed_at":"2024-03-29T15:30:18.627Z","dependency_job_id":"db25bd75-d6ea-4a91-b7b5-291f5f59bf7e","html_url":"https://github.com/frblondin/GitObjectDb","commit_stats":{"total_commits":257,"total_committers":5,"mean_commits":51.4,"dds":0.04280155642023342,"last_synced_commit":"3195e2a600a0194582815051bea26f7b88bd4438"},"previous_names":[],"tags_count":43,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/frblondin%2FGitObjectDb","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/frblondin%2FGitObjectDb/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/frblondin%2FGitObjectDb/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/frblondin%2FGitObjectDb/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/frblondin","download_url":"https://codeload.github.com/frblondin/GitObjectDb/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250308633,"owners_count":21409312,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["configuration-management","csharp","git","net"],"created_at":"2024-11-10T02:04:53.032Z","updated_at":"2025-04-22T19:32:39.775Z","avatar_url":"https://github.com/frblondin.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"**GitObjectDb simplifies the configuration management versioning by backing it in Git.**\n\n| Name | Badge |\n| --- | --- |\n| GitObjectDb  | [![NuGet Badge](https://img.shields.io/nuget/vpre/GitObjectDb)](https://www.nuget.org/packages/GitObjectDb/) |\n| GitObjectDb.SystemTextJson | [![NuGet Badge](https://img.shields.io/nuget/vpre/GitObjectDb.SystemTextJson)](https://www.nuget.org/packages/GitObjectDb.SystemTextJson/) |\n| GitObjectDb.YamlDotNet | [![NuGet Badge](https://img.shields.io/nuget/vpre/GitObjectDb.YamlDotNet)](https://www.nuget.org/packages/GitObjectDb.YamlDotNet/) |\n| GitObjectDb.Api.OData | [![NuGet Badge](https://img.shields.io/nuget/vpre/GitObjectDb.Api.OData)](https://www.nuget.org/packages/GitObjectDb.Api.OData/) |\n| GitObjectDb.Api.GraphQL | [![NuGet Badge](https://img.shields.io/nuget/vpre/GitObjectDb.Api.GraphQL)](https://www.nuget.org/packages/GitObjectDb.Api.GraphQL/) |\n| GitObjectDb.Api.ProtoBuf | [![NuGet Badge](https://img.shields.io/nuget/vpre/GitObjectDb.Api.ProtoBuf)](https://www.nuget.org/packages/GitObjectDb.Api.ProtoBuf/) |\n| GitObjectDb.Api.ProtoBuf.Model | [![NuGet Badge](https://img.shields.io/nuget/vpre/GitObjectDb.Api.ProtoBuf.Model)](https://www.nuget.org/packages/GitObjectDb.Api.ProtoBuf.Model/) |\n\n[![Build Status](https://github.com/frblondin/GitObjectDb/actions/workflows/CI.yml/badge.svg)](https://github.com/frblondin/GitObjectDb/actions/workflows/Release.yml)\n[![](https://sonarcloud.io/api/project_badges/measure?project=GitObjectDb\u0026metric=alert_status)](https://sonarcloud.io/dashboard/index/GitObjectDb)\n[![](https://sonarcloud.io/api/project_badges/measure?project=GitObjectDb\u0026metric=bugs)](https://sonarcloud.io/project/issues?id=GitObjectDb\u0026resolved=false\u0026types=BUG)\n[![](https://sonarcloud.io/api/project_badges/measure?project=GitObjectDb\u0026metric=coverage)](https://sonarcloud.io/component_measures?id=GitObjectDb\u0026metric=Coverage)\n[![](https://sonarcloud.io/api/project_badges/measure?project=GitObjectDb\u0026metric=code_smells)](https://sonarcloud.io/project/issues?id=GitObjectDb\u0026resolved=false\u0026types=CODE_SMELL)\n\n# Overview\n\nGitObjectDb is designed to simplify the configuration management versioning. It does so by removing the need for hand-coding the commands needed to interact with Git.\n\nThe Git repository is used as a pure database as the files containing the serialized copy of the objects are never fetched in the filesystem. GitObjectDb only uses the blob storage provided by Git.\n\nHere's a simple example:\n1. Define your own repository data model:\n    ```csharp\n    [GitFolder(\"Applications\")]\n    public record Application : Node\n    {\n        public string Name { get; init; }\n\n        public string Description { get; init; }\n    }\n    [GitFolder(\"Pages\")]\n    public record Table : Node\n    {\n        public string Name { get; init; }\n\n        public string Description { get; init; }\n\n        [StoreAsSeparateFile(Extension = \"txt\")]\n        public string? RichContent { get; init; }\n    }\n    ```\n2. Manipulate objects as follows:\n    ```csharp\n\tvar existingApplication = connection.Lookup\u003cApplication\u003e(\"main\", \"applications\", new UniqueId(id));\n\tvar newTable = new Table { ... };\n\tconnection\n\t    .Update(\"main\", c =\u003e c.CreateOrUpdate(newTable, parent: existingApplication))\n\t\t.Commit(new(\"Added new table.\", author, committer));\n    ```\n\n# Features\n\n## Structured \u0026 unstructured data storage\n\n```csharp\nvar node = new SomeNode\n{\n    SomeProperty = \"Value stored as json\",\n    RichContent = \"Value stored as raw text in separate Git blob, next to primary one\",\n}:\n```\n... gets stored in Git as follows:\n* zerzrzrz.json\n```json\n{\n  \"$type\": \"Sample.SomeNode\",\n  \"id\": \"zerzrzrz\",\n  \"someProperty\": \"Value stored as json\"\n}\n```\n* zerzrzrz.RichContent.txt\n```text\nValue stored many dynamic resources in separate Git blob, next to primary one\n```\nYou can also store resources as separate files:\n```csharp\nnew Resource(node, \"Some/Folder\", \"File.txt\", new Resource.Data(\"Value stored in a separate file in \u003cnode path\u003e/Resources/Some/Folder/File.txt\"));\n```\n\n## Branching\n\n```csharp\nconnection\n    .Update(\"main\", c =\u003e c.CreateOrUpdate(table with { Description = newDescription }))\n    .Commit(new(\"Some message\", signature, signature));\nconnection.Checkout(\"newBranch\", \"main~1\");\nconnection\n    .Update(\"main\", c =\u003e c.CreateOrUpdate(table with { Name = newName }))\n    .Commit(new(\"Another message\", signature, signature));\n```\n\n## Comparing commits\n\n```csharp\nvar comparison = connection.Compare(\"main~5\", \"main\");\nvar nodeChanges = comparison.Modified.OfType\u003cChange.NodeChange\u003e();\n```\n\n## Node references\n\nNode references allows linking existing nodes in a repository:\n\n```csharp\npublic record Order : Node\n{\n    public Client Client { get; set; }\n    // ...\n}\npublic record Client : Node\n{\n    // ...\n}\n// Nodes get loaded with their references (using a shared )\nvar cache = new Dictionary\u003cDataPath, ITreeItem\u003e();\nvar order = connection.GetNodes\u003cOrder\u003e(\"main\", referenceCache: cache).First();\nConsole.WriteLine(order.Client.Id);\n```\n\n## Merge, Rebase, Cherry-pick\n\n```csharp\n// main:      A---B    A---B\n//             \\    -\u003e  \\   \\\n// newBranch:   C        C---x\n\nconnection\n    .Update(\"main\", c =\u003e c.CreateOrUpdate(table with { Description = newDescription }))\n    .Commit(new(\"B\", signature, signature));\nconnection.Repository.Branches.Add(\"newBranch\", \"main~1\");\nconnection\n    .Update(\"newBranch\", c =\u003e c.CreateOrUpdate(table with { Name = newName }))\n    .Commit(new(\"C\", signature, signature));\n\nsut.Merge(upstreamCommittish: \"main\");\n```\n\n## Node versioning management\n\nImagine a scenario where you define in your code a first type:\n```csharp\n[GitFolder(FolderName = \"Items\", UseNodeFolders = false)]\n[IsDeprecatedNodeType(typeof(SomeNodeV2))]\nprivate record SomeNodeV1 : Node\n{\n    public int Flags { get; set; }\n}\n\n[GitFolder(FolderName = \"Items\", UseNodeFolders = false)]\nprivate record SomeNodeV2 : Node\n{\n    public BindingFlags TypedFlags { get; set; }\n}\n```\nYou then want to introduce a new change so that the `Flags` property contains more meaningful information, relying on enums:\n```csharp\n[GitFolder(FolderName = \"Items\", UseNodeFolders = false)]\nprivate record SomeNodeV2 : Node\n{\n    public BindingFlags TypedFlags { get; set; }\n}\n```\nAll you need to do is to #1 add the `[IsDeprecatedNodeType(typeof(SomeNodeV2))]` attribute. This will instruct the deserializer to convert nodes to new version, using a converter. #2 converter needs to be provided in the model. You can use AutoMapper or other tools at your convenience.\n```csharp\n[GitFolder(FolderName = \"Items\", UseNodeFolders = false)]\n[IsDeprecatedNodeType(typeof(SomeNodeV2))]\nprivate record SomeNodeV1 : Node\n{\n    // ...\n}\nvar model = new ConventionBaseModelBuilder()\n    .RegisterType\u003cSomeNodeV1\u003e()\n    .RegisterType\u003cSomeNodeV2\u003e()\n    .AddDeprecatedNodeUpdater(UpdateDeprecatedNode)\n    .Build();\nNode UpdateDeprecatedNode(Node old, Type targetType)\n{\n    var nodeV1 = (SomeNodeV1)old;\n    return new SomeNodeV2\n    {\n        Id = old.Id,\n        TypedFlags = (BindingFlags)nodeV1.Flags,\n    };\n}\n```\n\n\n# Documentation\n\nSee [documentation][Documentation].\n\n [Documentation]: https://gitobjectdb.readthedocs.io\n\n# Prerequisites\n\n - .NET Standard 2.0 or 2.1\n\n# Online resources\n\n - [LibGit2Sharp][LibGit2Sharp] (Requires NuGet 2.7+)\n\n [LibGit2Sharp]: https://github.com/libgit2/libgit2sharp\n\n# Quick contributing guide\n\n - Fork and clone locally\n - Create a topic specific branch. Add some nice feature. Do not forget the tests ;-)\n - Send a Pull Request to spread the fun!\n\n# License\n\nThe MIT license (Refer to the [LICENSE][license] file).\n\n [license]: https://github.com/frblondin/GitObjectDb/blob/master/LICENSE\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffrblondin%2Fgitobjectdb","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffrblondin%2Fgitobjectdb","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffrblondin%2Fgitobjectdb/lists"}