SlideShare a Scribd company logo
1 of 50
Download to read offline
git as a NoSQL database
Kenneth Truyers
.NET Developer
Microsoft MVP / Pluralsight author
@kennethtruyers
www.kenneth-truyers.net
Mechanics of
git as a database
Why it’s a
fantastic idea
Why it’s a
terrible idea
Database
“a structured set of data held in a computer, especially one that is
accessible in various ways”
NoSQL
“provides a mechanism for storage and retrieval of data in means
other than the tabular relations used in relational databases”
Schema-less Non relational
The naïve way
> git init myDatabase
Initialized empty Git repository in D:/myDatabase/.git/
> cd myDatabase
> echo {"id": 1, "name": "kenneth"} > 1.json
> git add 1.json
> git commit -m "Added person"
[master (root-commit) 6c6b907] Added person
1 file changed, 1 insertion(+)
create mode 100644 1.json
> git show master:1.json
{"id": 1, "name": "kenneth"}
HOW
Git repositories
Client Server (Bare repository)
Git data model
HOW
commit
05c1ce
tree
d6916d
blob
da95f82
tree
2c5d87r
master
commit
9918e4
tree
2c59c06
blob
42d0620
commit
5d8r56c
tree
4d52c5a
blob
da95f82
Reference Database
Object Database
Git commands
add archive bisect branch
checkout cherry-pick clean clone
commit diff fetch gc
init log merge mv
pull push rebase reset
revert rm show shortlog
stash status submodule tag
HOW
Porcelain
HOW
apply commit-tree hash-object merge-file
mktag mktree for-each-ref read-tree
update-ref write-tree cat-file diff-files
diff-index diff-tree merge-base rev-list
show-index show-ref unpack-tree send-pack
http-fetch http-push shell check-attr
mailinfo mailsplit sh-setup stripspace
Git commands
Plumbing
Plumbing
We need to get our hands dirty
Blobs
> echo {"id":1, "name": "kenneth"} | git hash-object –w
--stdin
da95f8264a0ffe3df10e94eed6371ea83aee9a4d
> git cat-file -p da95f
{"id": 1, "name": "kenneth"}
blob
da95f82
HOW
Trees
> git update-index --add --cacheinfo 100644
da95f8264a0ffe3df10e94eed6371ea83aee9a4d 1.json
> git write-tree
d6916d3e27baa9ef2742c2ba09696f22e41011a1
> git cat-file -p d6916d
100644 blob da95f8264a0ffe3df10e94eed6371ea83aee9a4d
1.json tree
d6916d3
blob: 1.json
blob
da95f82
HOW
Commits
> echo "commit kenneth" | git commit-tree d6916d
05c1cec5685bbb84e806886dba0de5e2f120ab2a
> git log --stat 05c1ce
commit 05c1cec5685bbb84e806886dba0de5e2f120ab2a
Author: Kenneth Truyers <truyers.kenneth@gmail.com>
Date: Sat Apr 29 10:15:23 2017 +0200
"commit kenneth"
1.json | 1 +
1 files changed, 1 insertions(+)
> git show 05c1cec:1.json
{"id": 1, "name": "kenneth"}
commit
05c1cec
tree: d6916d3
tree
d6916d3
blob: 1.json
blob
da95f82
HOW
Updating the file
> echo {"id": 1, "name": "updated name"} | git hash-
object -w --stdin
42d0d209ecf70a96666f5a4c8ed97f3fd2b75dda
> git update-index --add --cacheinfo 100644
42d0d209ecf70a96666f5a4c8ed97f3fd2b75dda 1.json
> git write-tree
2c59068b29c38db26eda42def74b7142de392212
> echo "Commit Kenneth v2" | git commit-tree 2c59068 -p
05c1cec
9918e46dfc4241f0782265285970a7c16bf499e4
commit
9918e46
tree: 2c59c06
tree
2c59c06
blob: 1.json
blob
42d0620
commit
05c1cec
tree: d6916d3
tree
d6916d3
blob: 1.json
blob
da95f82
HOW
Updating the file
> git log --stat 9918e46
9918e46dfc4241f0782265285970a7c16bf4 "commit Kenneth v2"
1.json | 1 +
1 file changed, 1 insertions(+)
05c1cec5685bbb84e806886dba0de5e2f120 "commit kenneth"
1.json | 1 +
1 file changed, 1 insertion(+)
> git show 9918e4:1.json
{"id": 1, "name": "updated name"}
> git show 05c1cec:1.json
{"id": 1, "name": "kenneth"}
commit
9918e46
tree: 2c59c06
tree
2c59c06
blob: 1.json
blob
42d0620
commit
05c1cec
tree: d6916d3
tree
d6916d3
blob: 1.json
blob
da95f82
HOW
master
commit: 9918e46
commit
9918e46
tree: 2c59c06
tree
2c59c06
blob: 1.json
blob
42d0620
commit
05c1cec
tree: d6916d3
tree
d6916d3
blob: 1.json
blob
da95f82
Refs
> git update-ref refs/heads/master 9918e4
> git show master:1.json
{"id": 1, "name": "updated name"}
HOW
Cool, but… I’m a programmer
portable, pure C implementation
of the core git methods
https://libgit2.github.com/
libgit2sharp
brings might and speed of libgit2 to the
managed world of .NET and Mono
https://github.com/libgit2/libgit2sharp
HOW
Building a git db in C#
public class GitDb
{
public string Save<T>(string branch, string key, T value)
{
}
public T Get<T>(string branch, string key)
{
}
}
HOW
Building a git db in C#
> git init --bare public class GitDb
{
readonly Repository _repo;
public GitDb(string path)
{
Repository.Init(path, isBare: true);
_repo = new Repository(path);
}
public string Save<T>(string branch, string key, T value)
{
}
public T Get<T>(string branch, string key)
{
}
}
HOW
Writing a blob
public string Save<T>(string branch, string key, T value)
{
string val = JsonConvert.SerializeObject(value);
byte[] bytes = Encoding.UTF8.GetBytes(val);
Stream stream = new MemoryStream(bytes);
Blob blob = _repo.ObjectDatabase.CreateBlob(stream);
}
commit
9918e46
tree
2c59c06
blob
42d0620
master
commit: 05c1cec
commit
05c1cec
tree: d6916d3
tree
d6916d3
blob: 1.json
blob
da95f82
HOW
Writing a tree
public string Save<T>(string branch, string key, T value)
{
string val = JsonConvert.SerializeObject(value);
byte[] bytes = Encoding.UTF8.GetBytes(val);
Stream stream = new MemoryStream(bytes);
Blob blob = _repo.ObjectDatabase.CreateBlob(stream);
Commit currentCommit = _repo.Branches[branch].Tip;
TreeDefinition treeDef = TreeDefinition.From(currentCommit);
treeDef.Add(key, blob, Mode.NonExecutableFile);
Tree tree = _repo.ObjectDatabase.CreateTree(treeDef);
}
commit
9918e46
tree
2c59c06
blob: 1.json
blob
42d0620
master
commit: 05c1cec
commit
05c1cec
tree: d6916d3
tree
d6916d3
blob: 1.json
blob
da95f82
HOW
Committing the tree
public string Save<T>(string branch, string key, T value)
{
string val = JsonConvert.SerializeObject(value);
byte[] bytes = Encoding.UTF8.GetBytes(val);
Stream stream = new MemoryStream(bytes);
Blob blob = _repo.ObjectDatabase.CreateBlob(stream);
Commit currentCommit = _repo.Branches[branch].Tip;
TreeDefinition treeDef = TreeDefinition.From(currentCommit);
treeDef.Add(key, blob, Mode.NonExecutableFile);
var tree = _repo.ObjectDatabase.CreateTree(treeDef);
var now = DateTimeOffset.Now;
Commit commit = _repo.ObjectDatabase.CreateCommit(
author: new Signature("author", "email", now),
message: "commit message",
tree: tree,
parents: new List<Commit> {currentCommit});
}
commit
9918e46
tree: 2c59c06
tree
2c59c06
blob: 1.json
blob
42d0620
master
commit: 05c1cec
commit
05c1cec
tree: d6916d3
tree
d6916d3
blob: 1.json
blob
da95f82
HOW
master
commit: 9918e46
commit
9918e46
tree: 2c59c06
tree
2c59c06
blob: 1.json
blob
42d0620
master
commit: 05c1cec
commit
05c1cec
tree: d6916d3
tree
d6916d3
blob: 1.json
blob
da95f82
Updating the branch
public string Save<T>(string branch, string key, T value)
{
string val = JsonConvert.SerializeObject(value);
byte[] bytes = Encoding.UTF8.GetBytes(val);
Stream stream = new MemoryStream(bytes);
Blob blob = _repo.ObjectDatabase.CreateBlob(stream);
Commit currentCommit = _repo.Branches[branch].Tip;
TreeDefinition treeDef = TreeDefinition.From(currentCommit);
treeDef.Add(key, blob, Mode.NonExecutableFile);
var tree = _repo.ObjectDatabase.CreateTree(treeDef);
var now = DateTimeOffset.Now;
Commit commit = _repo.ObjectDatabase.CreateCommit(
author: new Signature("author", "email", now),
message: "commit message",
tree: tree,
parents: new List<Commit> {currentCommit});
String refName = _repo.Branches
.Single(b => b.FriendlyName == branch)
.CanonicalName;
_repo.Refs.UpdateTarget(_repo.Refs[refName], commit.Id);
return commit.Sha;
}
HOW
Reading
public T Get<T>(string branch, string key)
{
Branch branchRef = _repo.Branches[branch];
Commit commit = branchRef.Tip;
TreeEntry entry = commit[key];
GitObject gitObj = entry.Target;
Blob blob = gitObj as Blob;
string content = blob.GetContentText();
return JsonConvert.DeserializeObject<T>(content);
}
master
commit: 9918e4
commit
9918e46
tree: 2c59c06
tree
2c59c06
blob: 1.json
blob
42d0620
commit
05c1cec
tree: d6916d3
tree
d6916d3
blob: 1.json
blob
da95f82
HOW
Cool, but… where’s my ORM?
HOW
github.com/YellowLineParking/Appy.GitDb
goo.gl/vQpxra
Why it’s a
fantastic idea
Schema-less
public class User
{
public int Id { get; set; }
public string Name { get; set; }
}
WHY
public class User
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Street { get; set; }
public string Country { get; set; }
}
Versioning and roll-back
WHY
> git show master:1.json
{"id": 1, "name": "updated name"}
> git update-ref refs/heads/master 05c1ce
> git show master:1.json
{"id": 1, "name": "kenneth"}'
master
commit: 9918e46
commit
9918e46
tree: 2c59c06
tree
2c59c06
blob: 1.json
blob
42d0620
master
commit: 05c1ce
commit
05c1cec
tree: d6916d3
tree
d6916d3
blob: 1.json
blob
da95f82
Diff
WHY
> git diff 9918e4 05c1ce -- 1.json
diff --git a/1.json b/1.json
--- a/1.json
+++ b/1.json
@@ -1 +1 @@
-{"id": 1, "name": "updated name"}
+{"id": 1, "name": "kenneth"}
master
commit
9918e46
tree: 2c59c06
tree
2c59c06
blob: 1.json
blob
42d0620
master
commit: 05c1ce
commit
05c1cec
tree: d6916d3
tree
d6916d3
blob: 1.json
blob
da95f82
Backup & Replication
WHY
> git remote add backup https://github.com/user/repo.git
> git push backup
> type .git/hooks/post-commit
#!/bin/sh
git push backup
Transactions
Short lived
WHY
> echo "file1" | git hash-object -w --stdin
42d0d20...
> echo "file2" | git hash-object -w --stdin
5d8f5r0...
> git update-index --add --cacheinfo 100644 42d0d20... 1.json
> git update-index --add --cacheinfo 100644 5d8f5r0... 2.json
> git write-tree
9c38db2...
> echo "commit transaction" | git commit-tree 9c38db2 -p
05c1cec
9918e46...
Transactions
Long lived
WHY
> git checkout -b transaction
...
...
...
> git checkout master
> git checkout merge transaction
Tooling
WHY
App
GIT
Repository
Appy.GitDb
bash
Why it’s a
terrible idea
Queries
WHY
NOT
KEY
KEY PREFIX (sort of*)
Solution
App
GIT
SQL
ElasticSearch
...
WRITE READ
COMMIT HOOK
WHY
NOT
public string Save<T>(string branch, string key, T value)
{
Blob blob = _repo.ObjectDatabase.CreateBlob(...);
TreeDefinition treeDef = TreeDefinition.From(...);
treeDef.Add(key, blob, Mode.NonExecutableFile);
Tree tree = _repo.ObjectDatabase.CreateTree(treeDef);
Commit commit = _repo.ObjectDatabase.CreateCommit(...);
_repo.Refs.UpdateTarget(_repo.Refs[refName], commit.Id);
}
Concurrency
WHY
NOT
public string Save<T>(string branch, string key, T value)
{
Blob blob = _repo.ObjectDatabase.CreateBlob(...);
TreeDefinition treeDef = TreeDefinition.From(...);
treeDef.Add(key, blob, Mode.NonExecutableFile);
Tree tree = _repo.ObjectDatabase.CreateTree(treeDef);
Commit commit = _repo.ObjectDatabase.CreateCommit(...);
_repo.Refs.UpdateTarget(_repo.Refs[refName], commit.Id);
}
Concurrency
WHY
NOT
blob
A
tree
A
commit
A
master
tree
B
blob
B
tree
C
blob
C
public string Save<T>(string branch, string key, T value)
{
Blob blob = _repo.ObjectDatabase.CreateBlob(...);
TreeDefinition treeDef = TreeDefinition.From(...);
treeDef.Add(key, blob, Mode.NonExecutableFile);
Tree tree = _repo.ObjectDatabase.CreateTree(treeDef);
Commit commit = _repo.ObjectDatabase.CreateCommit(...);
_repo.Refs.UpdateTarget(_repo.Refs[refName], commit.Id);
}
Concurrency
WHY
NOT
commit
A
master
commit
B
commit
C
mastermaster
var locks = new Dictionary<string, object>
{
{"master", new object() },
{"branch", new object() },
};
lock (locks[branch])
{
// ...
}
Solution WHY
NOT
Performance
WHY
NOT
Writes per second
125 (10,000 files)
18 (1,000,000 files)
100644 blob b9e36d8ed060ebdad585e93cec84 1.json
100644 blob 5a947c79aae7b7f6c663f632bfcf 2.json
.
.
100644 blob 4b54f5a8e56cfbc90947e3071ef6 999998.json
100644 blob 06179b3af5668bf7aa1dcb205949 999999.json
100644 blob a3d0db85108eb3e0c3d2b989a2ce 1000000.json
tree
B
tree
A
commit
master
...
100644 blob b9e36d8ed060ebdad585e93cec84 1.json
100644 blob 5a947c79aae7b7f6c663f632bfcf 2.json
.
.
100644 blob 4b54f5a8e56cfbc90947e3071ef6 999998.json
100644 blob 06179b3af5668bf7aa1dcb205949 999999.json
100644 blob a3d0db85108eb3e0c3d2b989a2ce 1000000.json
100644 blob 5bc5e544f68a56f992ca2be2fd26 1000001.json
...
100
...
100
...
100
...
100
...
100
...
100
...
100
Solution: tree nesting WHY
NOT
Writes per second
125 (10,000 files)
18 (1,000,000 files)
250 (1,000,000 files)
Solution: partitioning WHY
NOT
App
Repo 1
Disk 1
Repo 2
Disk 2
Repo 3
Disk 3
... ...
Solution: back-end WHY
NOT
App
GIT
Merge conflicts
WHY
NOT
Solution? WHY
NOT
Good idea Bad idea
Content heavy
CMS, Wiki, …
Partitionable
Country, customer, …
Fast writes
Immediate consistency
Demo
(ab)use your tools
Kenneth Truyers
@kennethtruyers
www.kenneth-truyers.net
bit.ly/git-db-code
bit.ly/git-nosql

More Related Content

What's hot

Ebook Pembuatan Aplikasi Rental film 2012
Ebook Pembuatan Aplikasi Rental film 2012Ebook Pembuatan Aplikasi Rental film 2012
Ebook Pembuatan Aplikasi Rental film 2012yantoit2011
 
Kamil Chmielewski, Jacek Juraszek - "Hadoop. W poszukiwaniu złotego młotka."
Kamil Chmielewski, Jacek Juraszek - "Hadoop. W poszukiwaniu złotego młotka."Kamil Chmielewski, Jacek Juraszek - "Hadoop. W poszukiwaniu złotego młotka."
Kamil Chmielewski, Jacek Juraszek - "Hadoop. W poszukiwaniu złotego młotka."sjabs
 
JJUG CCC 2011 Spring
JJUG CCC 2011 SpringJJUG CCC 2011 Spring
JJUG CCC 2011 SpringKiyotaka Oku
 
CloudClustering: Toward a scalable machine learning toolkit for Windows Azure
CloudClustering: Toward a scalable machine learning toolkit for Windows AzureCloudClustering: Toward a scalable machine learning toolkit for Windows Azure
CloudClustering: Toward a scalable machine learning toolkit for Windows AzureAnkur Dave
 
Mythbusting: Understanding How We Measure the Performance of MongoDB
Mythbusting: Understanding How We Measure the Performance of MongoDBMythbusting: Understanding How We Measure the Performance of MongoDB
Mythbusting: Understanding How We Measure the Performance of MongoDBMongoDB
 
Mythbusting: Understanding How We Measure Performance at MongoDB
Mythbusting: Understanding How We Measure Performance at MongoDBMythbusting: Understanding How We Measure Performance at MongoDB
Mythbusting: Understanding How We Measure Performance at MongoDBMongoDB
 
Java Persistence Frameworks for MongoDB
Java Persistence Frameworks for MongoDBJava Persistence Frameworks for MongoDB
Java Persistence Frameworks for MongoDBMongoDB
 
2019-01-29 - Demystifying Kotlin Coroutines
2019-01-29 - Demystifying Kotlin Coroutines2019-01-29 - Demystifying Kotlin Coroutines
2019-01-29 - Demystifying Kotlin CoroutinesEamonn Boyle
 
The Ring programming language version 1.5.2 book - Part 40 of 181
The Ring programming language version 1.5.2 book - Part 40 of 181The Ring programming language version 1.5.2 book - Part 40 of 181
The Ring programming language version 1.5.2 book - Part 40 of 181Mahmoud Samir Fayed
 
Java Development with MongoDB
Java Development with MongoDBJava Development with MongoDB
Java Development with MongoDBScott Hernandez
 
Back to Basics Webinar 5: Introduction to the Aggregation Framework
Back to Basics Webinar 5: Introduction to the Aggregation FrameworkBack to Basics Webinar 5: Introduction to the Aggregation Framework
Back to Basics Webinar 5: Introduction to the Aggregation FrameworkMongoDB
 
The Ring programming language version 1.5.2 book - Part 11 of 181
The Ring programming language version 1.5.2 book - Part 11 of 181The Ring programming language version 1.5.2 book - Part 11 of 181
The Ring programming language version 1.5.2 book - Part 11 of 181Mahmoud Samir Fayed
 
Writing Domain-Specific Languages for BeepBeep
Writing Domain-Specific Languages for BeepBeepWriting Domain-Specific Languages for BeepBeep
Writing Domain-Specific Languages for BeepBeepSylvain Hallé
 
Operational Intelligence with MongoDB Webinar
Operational Intelligence with MongoDB WebinarOperational Intelligence with MongoDB Webinar
Operational Intelligence with MongoDB WebinarMongoDB
 
The Ring programming language version 1.8 book - Part 30 of 202
The Ring programming language version 1.8 book - Part 30 of 202The Ring programming language version 1.8 book - Part 30 of 202
The Ring programming language version 1.8 book - Part 30 of 202Mahmoud Samir Fayed
 
برنامج محادثة باستخدام الاستدعاء العكسي في استدعاء الطرق البعيدة بلغة الجافا ...
برنامج محادثة باستخدام الاستدعاء العكسي في استدعاء الطرق البعيدة بلغة الجافا ...برنامج محادثة باستخدام الاستدعاء العكسي في استدعاء الطرق البعيدة بلغة الجافا ...
برنامج محادثة باستخدام الاستدعاء العكسي في استدعاء الطرق البعيدة بلغة الجافا ...Abdulrazak Zakieh
 
MongoDB + Java + Spring Data
MongoDB + Java + Spring DataMongoDB + Java + Spring Data
MongoDB + Java + Spring DataAnton Sulzhenko
 
Webinaire 2 de la série « Retour aux fondamentaux » : Votre première applicat...
Webinaire 2 de la série « Retour aux fondamentaux » : Votre première applicat...Webinaire 2 de la série « Retour aux fondamentaux » : Votre première applicat...
Webinaire 2 de la série « Retour aux fondamentaux » : Votre première applicat...MongoDB
 

What's hot (20)

Ebook Pembuatan Aplikasi Rental film 2012
Ebook Pembuatan Aplikasi Rental film 2012Ebook Pembuatan Aplikasi Rental film 2012
Ebook Pembuatan Aplikasi Rental film 2012
 
NoSQL Infrastructure
NoSQL InfrastructureNoSQL Infrastructure
NoSQL Infrastructure
 
Kamil Chmielewski, Jacek Juraszek - "Hadoop. W poszukiwaniu złotego młotka."
Kamil Chmielewski, Jacek Juraszek - "Hadoop. W poszukiwaniu złotego młotka."Kamil Chmielewski, Jacek Juraszek - "Hadoop. W poszukiwaniu złotego młotka."
Kamil Chmielewski, Jacek Juraszek - "Hadoop. W poszukiwaniu złotego młotka."
 
JJUG CCC 2011 Spring
JJUG CCC 2011 SpringJJUG CCC 2011 Spring
JJUG CCC 2011 Spring
 
CloudClustering: Toward a scalable machine learning toolkit for Windows Azure
CloudClustering: Toward a scalable machine learning toolkit for Windows AzureCloudClustering: Toward a scalable machine learning toolkit for Windows Azure
CloudClustering: Toward a scalable machine learning toolkit for Windows Azure
 
Mythbusting: Understanding How We Measure the Performance of MongoDB
Mythbusting: Understanding How We Measure the Performance of MongoDBMythbusting: Understanding How We Measure the Performance of MongoDB
Mythbusting: Understanding How We Measure the Performance of MongoDB
 
Mythbusting: Understanding How We Measure Performance at MongoDB
Mythbusting: Understanding How We Measure Performance at MongoDBMythbusting: Understanding How We Measure Performance at MongoDB
Mythbusting: Understanding How We Measure Performance at MongoDB
 
Java Persistence Frameworks for MongoDB
Java Persistence Frameworks for MongoDBJava Persistence Frameworks for MongoDB
Java Persistence Frameworks for MongoDB
 
2019-01-29 - Demystifying Kotlin Coroutines
2019-01-29 - Demystifying Kotlin Coroutines2019-01-29 - Demystifying Kotlin Coroutines
2019-01-29 - Demystifying Kotlin Coroutines
 
The Ring programming language version 1.5.2 book - Part 40 of 181
The Ring programming language version 1.5.2 book - Part 40 of 181The Ring programming language version 1.5.2 book - Part 40 of 181
The Ring programming language version 1.5.2 book - Part 40 of 181
 
Java Development with MongoDB
Java Development with MongoDBJava Development with MongoDB
Java Development with MongoDB
 
Back to Basics Webinar 5: Introduction to the Aggregation Framework
Back to Basics Webinar 5: Introduction to the Aggregation FrameworkBack to Basics Webinar 5: Introduction to the Aggregation Framework
Back to Basics Webinar 5: Introduction to the Aggregation Framework
 
The Ring programming language version 1.5.2 book - Part 11 of 181
The Ring programming language version 1.5.2 book - Part 11 of 181The Ring programming language version 1.5.2 book - Part 11 of 181
The Ring programming language version 1.5.2 book - Part 11 of 181
 
ROracle
ROracle ROracle
ROracle
 
Writing Domain-Specific Languages for BeepBeep
Writing Domain-Specific Languages for BeepBeepWriting Domain-Specific Languages for BeepBeep
Writing Domain-Specific Languages for BeepBeep
 
Operational Intelligence with MongoDB Webinar
Operational Intelligence with MongoDB WebinarOperational Intelligence with MongoDB Webinar
Operational Intelligence with MongoDB Webinar
 
The Ring programming language version 1.8 book - Part 30 of 202
The Ring programming language version 1.8 book - Part 30 of 202The Ring programming language version 1.8 book - Part 30 of 202
The Ring programming language version 1.8 book - Part 30 of 202
 
برنامج محادثة باستخدام الاستدعاء العكسي في استدعاء الطرق البعيدة بلغة الجافا ...
برنامج محادثة باستخدام الاستدعاء العكسي في استدعاء الطرق البعيدة بلغة الجافا ...برنامج محادثة باستخدام الاستدعاء العكسي في استدعاء الطرق البعيدة بلغة الجافا ...
برنامج محادثة باستخدام الاستدعاء العكسي في استدعاء الطرق البعيدة بلغة الجافا ...
 
MongoDB + Java + Spring Data
MongoDB + Java + Spring DataMongoDB + Java + Spring Data
MongoDB + Java + Spring Data
 
Webinaire 2 de la série « Retour aux fondamentaux » : Votre première applicat...
Webinaire 2 de la série « Retour aux fondamentaux » : Votre première applicat...Webinaire 2 de la série « Retour aux fondamentaux » : Votre première applicat...
Webinaire 2 de la série « Retour aux fondamentaux » : Votre première applicat...
 

Similar to Kenneth Truyers - Using Git as a NoSql database - Codemotion Milan 2018

New Views on your History with git replace
New Views on your History with git replaceNew Views on your History with git replace
New Views on your History with git replaceChristian Couder
 
Git Going for the Transylvania JUG
Git Going for the Transylvania JUGGit Going for the Transylvania JUG
Git Going for the Transylvania JUGMatthew McCullough
 
Postgres & Redis Sitting in a Tree- Rimas Silkaitis, Heroku
Postgres & Redis Sitting in a Tree- Rimas Silkaitis, HerokuPostgres & Redis Sitting in a Tree- Rimas Silkaitis, Heroku
Postgres & Redis Sitting in a Tree- Rimas Silkaitis, HerokuRedis Labs
 
Understanding GIT
Understanding GITUnderstanding GIT
Understanding GIThybr1s
 
Introducción a git y GitHub
Introducción a git y GitHubIntroducción a git y GitHub
Introducción a git y GitHubLucas Videla
 
Yevhen Tatarynov "From POC to High-Performance .NET applications"
Yevhen Tatarynov "From POC to High-Performance .NET applications"Yevhen Tatarynov "From POC to High-Performance .NET applications"
Yevhen Tatarynov "From POC to High-Performance .NET applications"LogeekNightUkraine
 
Apache Calcite Tutorial - BOSS 21
Apache Calcite Tutorial - BOSS 21Apache Calcite Tutorial - BOSS 21
Apache Calcite Tutorial - BOSS 21Stamatis Zampetakis
 
Rewriting the Drupal Theme layer
Rewriting the Drupal Theme layerRewriting the Drupal Theme layer
Rewriting the Drupal Theme layerc4rl
 
Introduction to Presto at Treasure Data
Introduction to Presto at Treasure DataIntroduction to Presto at Treasure Data
Introduction to Presto at Treasure DataTaro L. Saito
 
Git Introduction Tutorial
Git Introduction TutorialGit Introduction Tutorial
Git Introduction TutorialThomas Rausch
 
The Ring programming language version 1.8 book - Part 33 of 202
The Ring programming language version 1.8 book - Part 33 of 202The Ring programming language version 1.8 book - Part 33 of 202
The Ring programming language version 1.8 book - Part 33 of 202Mahmoud Samir Fayed
 
Importing Data into Neo4j quickly and easily - StackOverflow
Importing Data into Neo4j quickly and easily - StackOverflowImporting Data into Neo4j quickly and easily - StackOverflow
Importing Data into Neo4j quickly and easily - StackOverflowNeo4j
 
Beginning direct3d gameprogrammingcpp02_20160324_jintaeks
Beginning direct3d gameprogrammingcpp02_20160324_jintaeksBeginning direct3d gameprogrammingcpp02_20160324_jintaeks
Beginning direct3d gameprogrammingcpp02_20160324_jintaeksJinTaek Seo
 
Creating, Updating and Deleting Document in MongoDB
Creating, Updating and Deleting Document in MongoDBCreating, Updating and Deleting Document in MongoDB
Creating, Updating and Deleting Document in MongoDBWildan Maulana
 
Git Tutorial Yang Yang
Git Tutorial Yang YangGit Tutorial Yang Yang
Git Tutorial Yang YangYang Yang
 
Rapid and Scalable Development with MongoDB, PyMongo, and Ming
Rapid and Scalable Development with MongoDB, PyMongo, and MingRapid and Scalable Development with MongoDB, PyMongo, and Ming
Rapid and Scalable Development with MongoDB, PyMongo, and MingRick Copeland
 
Introducing BinarySortedMultiMap - A new Flink state primitive to boost your ...
Introducing BinarySortedMultiMap - A new Flink state primitive to boost your ...Introducing BinarySortedMultiMap - A new Flink state primitive to boost your ...
Introducing BinarySortedMultiMap - A new Flink state primitive to boost your ...Flink Forward
 
Git: An introduction of plumbing and porcelain commands
Git: An introduction of plumbing and porcelain commandsGit: An introduction of plumbing and porcelain commands
Git: An introduction of plumbing and porcelain commandsth507
 

Similar to Kenneth Truyers - Using Git as a NoSql database - Codemotion Milan 2018 (20)

New Views on your History with git replace
New Views on your History with git replaceNew Views on your History with git replace
New Views on your History with git replace
 
Git Going for the Transylvania JUG
Git Going for the Transylvania JUGGit Going for the Transylvania JUG
Git Going for the Transylvania JUG
 
Postgres & Redis Sitting in a Tree- Rimas Silkaitis, Heroku
Postgres & Redis Sitting in a Tree- Rimas Silkaitis, HerokuPostgres & Redis Sitting in a Tree- Rimas Silkaitis, Heroku
Postgres & Redis Sitting in a Tree- Rimas Silkaitis, Heroku
 
Understanding GIT
Understanding GITUnderstanding GIT
Understanding GIT
 
Introducción a git y GitHub
Introducción a git y GitHubIntroducción a git y GitHub
Introducción a git y GitHub
 
Yevhen Tatarynov "From POC to High-Performance .NET applications"
Yevhen Tatarynov "From POC to High-Performance .NET applications"Yevhen Tatarynov "From POC to High-Performance .NET applications"
Yevhen Tatarynov "From POC to High-Performance .NET applications"
 
Apache Calcite Tutorial - BOSS 21
Apache Calcite Tutorial - BOSS 21Apache Calcite Tutorial - BOSS 21
Apache Calcite Tutorial - BOSS 21
 
Git Basic
Git BasicGit Basic
Git Basic
 
Rewriting the Drupal Theme layer
Rewriting the Drupal Theme layerRewriting the Drupal Theme layer
Rewriting the Drupal Theme layer
 
Introduction to Presto at Treasure Data
Introduction to Presto at Treasure DataIntroduction to Presto at Treasure Data
Introduction to Presto at Treasure Data
 
Git Introduction Tutorial
Git Introduction TutorialGit Introduction Tutorial
Git Introduction Tutorial
 
The Ring programming language version 1.8 book - Part 33 of 202
The Ring programming language version 1.8 book - Part 33 of 202The Ring programming language version 1.8 book - Part 33 of 202
The Ring programming language version 1.8 book - Part 33 of 202
 
Importing Data into Neo4j quickly and easily - StackOverflow
Importing Data into Neo4j quickly and easily - StackOverflowImporting Data into Neo4j quickly and easily - StackOverflow
Importing Data into Neo4j quickly and easily - StackOverflow
 
Beginning direct3d gameprogrammingcpp02_20160324_jintaeks
Beginning direct3d gameprogrammingcpp02_20160324_jintaeksBeginning direct3d gameprogrammingcpp02_20160324_jintaeks
Beginning direct3d gameprogrammingcpp02_20160324_jintaeks
 
Creating, Updating and Deleting Document in MongoDB
Creating, Updating and Deleting Document in MongoDBCreating, Updating and Deleting Document in MongoDB
Creating, Updating and Deleting Document in MongoDB
 
Introduction to git
Introduction to gitIntroduction to git
Introduction to git
 
Git Tutorial Yang Yang
Git Tutorial Yang YangGit Tutorial Yang Yang
Git Tutorial Yang Yang
 
Rapid and Scalable Development with MongoDB, PyMongo, and Ming
Rapid and Scalable Development with MongoDB, PyMongo, and MingRapid and Scalable Development with MongoDB, PyMongo, and Ming
Rapid and Scalable Development with MongoDB, PyMongo, and Ming
 
Introducing BinarySortedMultiMap - A new Flink state primitive to boost your ...
Introducing BinarySortedMultiMap - A new Flink state primitive to boost your ...Introducing BinarySortedMultiMap - A new Flink state primitive to boost your ...
Introducing BinarySortedMultiMap - A new Flink state primitive to boost your ...
 
Git: An introduction of plumbing and porcelain commands
Git: An introduction of plumbing and porcelain commandsGit: An introduction of plumbing and porcelain commands
Git: An introduction of plumbing and porcelain commands
 

More from Codemotion

Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...
Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...
Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...Codemotion
 
Pompili - From hero to_zero: The FatalNoise neverending story
Pompili - From hero to_zero: The FatalNoise neverending storyPompili - From hero to_zero: The FatalNoise neverending story
Pompili - From hero to_zero: The FatalNoise neverending storyCodemotion
 
Pastore - Commodore 65 - La storia
Pastore - Commodore 65 - La storiaPastore - Commodore 65 - La storia
Pastore - Commodore 65 - La storiaCodemotion
 
Pennisi - Essere Richard Altwasser
Pennisi - Essere Richard AltwasserPennisi - Essere Richard Altwasser
Pennisi - Essere Richard AltwasserCodemotion
 
Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...
Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...
Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...Codemotion
 
Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019
Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019
Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019Codemotion
 
Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019
Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019
Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019Codemotion
 
Francesco Baldassarri - Deliver Data at Scale - Codemotion Amsterdam 2019 -
Francesco Baldassarri  - Deliver Data at Scale - Codemotion Amsterdam 2019 - Francesco Baldassarri  - Deliver Data at Scale - Codemotion Amsterdam 2019 -
Francesco Baldassarri - Deliver Data at Scale - Codemotion Amsterdam 2019 - Codemotion
 
Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...
Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...
Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...Codemotion
 
Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...
Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...
Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...Codemotion
 
Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...
Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...
Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...Codemotion
 
Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...
Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...
Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...Codemotion
 
Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019
Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019
Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019Codemotion
 
Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019
Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019
Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019Codemotion
 
Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019
Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019
Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019Codemotion
 
James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...
James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...
James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...Codemotion
 
Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...
Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...
Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...Codemotion
 
Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019
Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019
Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019Codemotion
 
Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019
Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019
Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019Codemotion
 
Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019
Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019
Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019Codemotion
 

More from Codemotion (20)

Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...
Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...
Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...
 
Pompili - From hero to_zero: The FatalNoise neverending story
Pompili - From hero to_zero: The FatalNoise neverending storyPompili - From hero to_zero: The FatalNoise neverending story
Pompili - From hero to_zero: The FatalNoise neverending story
 
Pastore - Commodore 65 - La storia
Pastore - Commodore 65 - La storiaPastore - Commodore 65 - La storia
Pastore - Commodore 65 - La storia
 
Pennisi - Essere Richard Altwasser
Pennisi - Essere Richard AltwasserPennisi - Essere Richard Altwasser
Pennisi - Essere Richard Altwasser
 
Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...
Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...
Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...
 
Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019
Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019
Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019
 
Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019
Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019
Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019
 
Francesco Baldassarri - Deliver Data at Scale - Codemotion Amsterdam 2019 -
Francesco Baldassarri  - Deliver Data at Scale - Codemotion Amsterdam 2019 - Francesco Baldassarri  - Deliver Data at Scale - Codemotion Amsterdam 2019 -
Francesco Baldassarri - Deliver Data at Scale - Codemotion Amsterdam 2019 -
 
Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...
Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...
Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...
 
Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...
Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...
Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...
 
Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...
Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...
Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...
 
Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...
Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...
Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...
 
Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019
Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019
Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019
 
Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019
Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019
Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019
 
Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019
Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019
Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019
 
James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...
James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...
James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...
 
Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...
Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...
Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...
 
Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019
Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019
Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019
 
Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019
Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019
Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019
 
Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019
Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019
Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019
 

Recently uploaded

How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
Snow Chain-Integrated Tire for a Safe Drive on Winter Roads
Snow Chain-Integrated Tire for a Safe Drive on Winter RoadsSnow Chain-Integrated Tire for a Safe Drive on Winter Roads
Snow Chain-Integrated Tire for a Safe Drive on Winter RoadsHyundai Motor Group
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphSIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphNeo4j
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions
 
How to Remove Document Management Hurdles with X-Docs?
How to Remove Document Management Hurdles with X-Docs?How to Remove Document Management Hurdles with X-Docs?
How to Remove Document Management Hurdles with X-Docs?XfilesPro
 
Artificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning eraArtificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning eraDeakin University
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Scott Keck-Warren
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesSinan KOZAK
 
Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxOnBoard
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Patryk Bandurski
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitecturePixlogix Infotech
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationSafe Software
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...shyamraj55
 

Recently uploaded (20)

How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
Snow Chain-Integrated Tire for a Safe Drive on Winter Roads
Snow Chain-Integrated Tire for a Safe Drive on Winter RoadsSnow Chain-Integrated Tire for a Safe Drive on Winter Roads
Snow Chain-Integrated Tire for a Safe Drive on Winter Roads
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphSIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food Manufacturing
 
How to Remove Document Management Hurdles with X-Docs?
How to Remove Document Management Hurdles with X-Docs?How to Remove Document Management Hurdles with X-Docs?
How to Remove Document Management Hurdles with X-Docs?
 
Artificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning eraArtificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning era
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen Frames
 
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptxE-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
 
Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptx
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
 
Vulnerability_Management_GRC_by Sohang Sengupta.pptx
Vulnerability_Management_GRC_by Sohang Sengupta.pptxVulnerability_Management_GRC_by Sohang Sengupta.pptx
Vulnerability_Management_GRC_by Sohang Sengupta.pptx
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC Architecture
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
 

Kenneth Truyers - Using Git as a NoSql database - Codemotion Milan 2018

  • 1. git as a NoSQL database Kenneth Truyers .NET Developer Microsoft MVP / Pluralsight author @kennethtruyers www.kenneth-truyers.net
  • 2.
  • 3.
  • 4. Mechanics of git as a database Why it’s a fantastic idea Why it’s a terrible idea
  • 5. Database “a structured set of data held in a computer, especially one that is accessible in various ways” NoSQL “provides a mechanism for storage and retrieval of data in means other than the tabular relations used in relational databases” Schema-less Non relational
  • 6. The naïve way > git init myDatabase Initialized empty Git repository in D:/myDatabase/.git/ > cd myDatabase > echo {"id": 1, "name": "kenneth"} > 1.json > git add 1.json > git commit -m "Added person" [master (root-commit) 6c6b907] Added person 1 file changed, 1 insertion(+) create mode 100644 1.json > git show master:1.json {"id": 1, "name": "kenneth"} HOW
  • 7. Git repositories Client Server (Bare repository)
  • 9. Git commands add archive bisect branch checkout cherry-pick clean clone commit diff fetch gc init log merge mv pull push rebase reset revert rm show shortlog stash status submodule tag HOW Porcelain
  • 10. HOW apply commit-tree hash-object merge-file mktag mktree for-each-ref read-tree update-ref write-tree cat-file diff-files diff-index diff-tree merge-base rev-list show-index show-ref unpack-tree send-pack http-fetch http-push shell check-attr mailinfo mailsplit sh-setup stripspace Git commands Plumbing
  • 11. Plumbing We need to get our hands dirty
  • 12. Blobs > echo {"id":1, "name": "kenneth"} | git hash-object –w --stdin da95f8264a0ffe3df10e94eed6371ea83aee9a4d > git cat-file -p da95f {"id": 1, "name": "kenneth"} blob da95f82 HOW
  • 13. Trees > git update-index --add --cacheinfo 100644 da95f8264a0ffe3df10e94eed6371ea83aee9a4d 1.json > git write-tree d6916d3e27baa9ef2742c2ba09696f22e41011a1 > git cat-file -p d6916d 100644 blob da95f8264a0ffe3df10e94eed6371ea83aee9a4d 1.json tree d6916d3 blob: 1.json blob da95f82 HOW
  • 14. Commits > echo "commit kenneth" | git commit-tree d6916d 05c1cec5685bbb84e806886dba0de5e2f120ab2a > git log --stat 05c1ce commit 05c1cec5685bbb84e806886dba0de5e2f120ab2a Author: Kenneth Truyers <truyers.kenneth@gmail.com> Date: Sat Apr 29 10:15:23 2017 +0200 "commit kenneth" 1.json | 1 + 1 files changed, 1 insertions(+) > git show 05c1cec:1.json {"id": 1, "name": "kenneth"} commit 05c1cec tree: d6916d3 tree d6916d3 blob: 1.json blob da95f82 HOW
  • 15. Updating the file > echo {"id": 1, "name": "updated name"} | git hash- object -w --stdin 42d0d209ecf70a96666f5a4c8ed97f3fd2b75dda > git update-index --add --cacheinfo 100644 42d0d209ecf70a96666f5a4c8ed97f3fd2b75dda 1.json > git write-tree 2c59068b29c38db26eda42def74b7142de392212 > echo "Commit Kenneth v2" | git commit-tree 2c59068 -p 05c1cec 9918e46dfc4241f0782265285970a7c16bf499e4 commit 9918e46 tree: 2c59c06 tree 2c59c06 blob: 1.json blob 42d0620 commit 05c1cec tree: d6916d3 tree d6916d3 blob: 1.json blob da95f82 HOW
  • 16. Updating the file > git log --stat 9918e46 9918e46dfc4241f0782265285970a7c16bf4 "commit Kenneth v2" 1.json | 1 + 1 file changed, 1 insertions(+) 05c1cec5685bbb84e806886dba0de5e2f120 "commit kenneth" 1.json | 1 + 1 file changed, 1 insertion(+) > git show 9918e4:1.json {"id": 1, "name": "updated name"} > git show 05c1cec:1.json {"id": 1, "name": "kenneth"} commit 9918e46 tree: 2c59c06 tree 2c59c06 blob: 1.json blob 42d0620 commit 05c1cec tree: d6916d3 tree d6916d3 blob: 1.json blob da95f82 HOW
  • 17. master commit: 9918e46 commit 9918e46 tree: 2c59c06 tree 2c59c06 blob: 1.json blob 42d0620 commit 05c1cec tree: d6916d3 tree d6916d3 blob: 1.json blob da95f82 Refs > git update-ref refs/heads/master 9918e4 > git show master:1.json {"id": 1, "name": "updated name"} HOW
  • 18. Cool, but… I’m a programmer portable, pure C implementation of the core git methods https://libgit2.github.com/ libgit2sharp brings might and speed of libgit2 to the managed world of .NET and Mono https://github.com/libgit2/libgit2sharp HOW
  • 19. Building a git db in C# public class GitDb { public string Save<T>(string branch, string key, T value) { } public T Get<T>(string branch, string key) { } } HOW
  • 20. Building a git db in C# > git init --bare public class GitDb { readonly Repository _repo; public GitDb(string path) { Repository.Init(path, isBare: true); _repo = new Repository(path); } public string Save<T>(string branch, string key, T value) { } public T Get<T>(string branch, string key) { } } HOW
  • 21. Writing a blob public string Save<T>(string branch, string key, T value) { string val = JsonConvert.SerializeObject(value); byte[] bytes = Encoding.UTF8.GetBytes(val); Stream stream = new MemoryStream(bytes); Blob blob = _repo.ObjectDatabase.CreateBlob(stream); } commit 9918e46 tree 2c59c06 blob 42d0620 master commit: 05c1cec commit 05c1cec tree: d6916d3 tree d6916d3 blob: 1.json blob da95f82 HOW
  • 22. Writing a tree public string Save<T>(string branch, string key, T value) { string val = JsonConvert.SerializeObject(value); byte[] bytes = Encoding.UTF8.GetBytes(val); Stream stream = new MemoryStream(bytes); Blob blob = _repo.ObjectDatabase.CreateBlob(stream); Commit currentCommit = _repo.Branches[branch].Tip; TreeDefinition treeDef = TreeDefinition.From(currentCommit); treeDef.Add(key, blob, Mode.NonExecutableFile); Tree tree = _repo.ObjectDatabase.CreateTree(treeDef); } commit 9918e46 tree 2c59c06 blob: 1.json blob 42d0620 master commit: 05c1cec commit 05c1cec tree: d6916d3 tree d6916d3 blob: 1.json blob da95f82 HOW
  • 23. Committing the tree public string Save<T>(string branch, string key, T value) { string val = JsonConvert.SerializeObject(value); byte[] bytes = Encoding.UTF8.GetBytes(val); Stream stream = new MemoryStream(bytes); Blob blob = _repo.ObjectDatabase.CreateBlob(stream); Commit currentCommit = _repo.Branches[branch].Tip; TreeDefinition treeDef = TreeDefinition.From(currentCommit); treeDef.Add(key, blob, Mode.NonExecutableFile); var tree = _repo.ObjectDatabase.CreateTree(treeDef); var now = DateTimeOffset.Now; Commit commit = _repo.ObjectDatabase.CreateCommit( author: new Signature("author", "email", now), message: "commit message", tree: tree, parents: new List<Commit> {currentCommit}); } commit 9918e46 tree: 2c59c06 tree 2c59c06 blob: 1.json blob 42d0620 master commit: 05c1cec commit 05c1cec tree: d6916d3 tree d6916d3 blob: 1.json blob da95f82 HOW
  • 24. master commit: 9918e46 commit 9918e46 tree: 2c59c06 tree 2c59c06 blob: 1.json blob 42d0620 master commit: 05c1cec commit 05c1cec tree: d6916d3 tree d6916d3 blob: 1.json blob da95f82 Updating the branch public string Save<T>(string branch, string key, T value) { string val = JsonConvert.SerializeObject(value); byte[] bytes = Encoding.UTF8.GetBytes(val); Stream stream = new MemoryStream(bytes); Blob blob = _repo.ObjectDatabase.CreateBlob(stream); Commit currentCommit = _repo.Branches[branch].Tip; TreeDefinition treeDef = TreeDefinition.From(currentCommit); treeDef.Add(key, blob, Mode.NonExecutableFile); var tree = _repo.ObjectDatabase.CreateTree(treeDef); var now = DateTimeOffset.Now; Commit commit = _repo.ObjectDatabase.CreateCommit( author: new Signature("author", "email", now), message: "commit message", tree: tree, parents: new List<Commit> {currentCommit}); String refName = _repo.Branches .Single(b => b.FriendlyName == branch) .CanonicalName; _repo.Refs.UpdateTarget(_repo.Refs[refName], commit.Id); return commit.Sha; } HOW
  • 25. Reading public T Get<T>(string branch, string key) { Branch branchRef = _repo.Branches[branch]; Commit commit = branchRef.Tip; TreeEntry entry = commit[key]; GitObject gitObj = entry.Target; Blob blob = gitObj as Blob; string content = blob.GetContentText(); return JsonConvert.DeserializeObject<T>(content); } master commit: 9918e4 commit 9918e46 tree: 2c59c06 tree 2c59c06 blob: 1.json blob 42d0620 commit 05c1cec tree: d6916d3 tree d6916d3 blob: 1.json blob da95f82 HOW
  • 26. Cool, but… where’s my ORM? HOW github.com/YellowLineParking/Appy.GitDb goo.gl/vQpxra
  • 28. Schema-less public class User { public int Id { get; set; } public string Name { get; set; } } WHY public class User { public int Id { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public string Street { get; set; } public string Country { get; set; } }
  • 29. Versioning and roll-back WHY > git show master:1.json {"id": 1, "name": "updated name"} > git update-ref refs/heads/master 05c1ce > git show master:1.json {"id": 1, "name": "kenneth"}' master commit: 9918e46 commit 9918e46 tree: 2c59c06 tree 2c59c06 blob: 1.json blob 42d0620 master commit: 05c1ce commit 05c1cec tree: d6916d3 tree d6916d3 blob: 1.json blob da95f82
  • 30. Diff WHY > git diff 9918e4 05c1ce -- 1.json diff --git a/1.json b/1.json --- a/1.json +++ b/1.json @@ -1 +1 @@ -{"id": 1, "name": "updated name"} +{"id": 1, "name": "kenneth"} master commit 9918e46 tree: 2c59c06 tree 2c59c06 blob: 1.json blob 42d0620 master commit: 05c1ce commit 05c1cec tree: d6916d3 tree d6916d3 blob: 1.json blob da95f82
  • 31. Backup & Replication WHY > git remote add backup https://github.com/user/repo.git > git push backup > type .git/hooks/post-commit #!/bin/sh git push backup
  • 32. Transactions Short lived WHY > echo "file1" | git hash-object -w --stdin 42d0d20... > echo "file2" | git hash-object -w --stdin 5d8f5r0... > git update-index --add --cacheinfo 100644 42d0d20... 1.json > git update-index --add --cacheinfo 100644 5d8f5r0... 2.json > git write-tree 9c38db2... > echo "commit transaction" | git commit-tree 9c38db2 -p 05c1cec 9918e46...
  • 33. Transactions Long lived WHY > git checkout -b transaction ... ... ... > git checkout master > git checkout merge transaction
  • 38. public string Save<T>(string branch, string key, T value) { Blob blob = _repo.ObjectDatabase.CreateBlob(...); TreeDefinition treeDef = TreeDefinition.From(...); treeDef.Add(key, blob, Mode.NonExecutableFile); Tree tree = _repo.ObjectDatabase.CreateTree(treeDef); Commit commit = _repo.ObjectDatabase.CreateCommit(...); _repo.Refs.UpdateTarget(_repo.Refs[refName], commit.Id); } Concurrency WHY NOT
  • 39. public string Save<T>(string branch, string key, T value) { Blob blob = _repo.ObjectDatabase.CreateBlob(...); TreeDefinition treeDef = TreeDefinition.From(...); treeDef.Add(key, blob, Mode.NonExecutableFile); Tree tree = _repo.ObjectDatabase.CreateTree(treeDef); Commit commit = _repo.ObjectDatabase.CreateCommit(...); _repo.Refs.UpdateTarget(_repo.Refs[refName], commit.Id); } Concurrency WHY NOT blob A tree A commit A master tree B blob B tree C blob C
  • 40. public string Save<T>(string branch, string key, T value) { Blob blob = _repo.ObjectDatabase.CreateBlob(...); TreeDefinition treeDef = TreeDefinition.From(...); treeDef.Add(key, blob, Mode.NonExecutableFile); Tree tree = _repo.ObjectDatabase.CreateTree(treeDef); Commit commit = _repo.ObjectDatabase.CreateCommit(...); _repo.Refs.UpdateTarget(_repo.Refs[refName], commit.Id); } Concurrency WHY NOT commit A master commit B commit C mastermaster
  • 41. var locks = new Dictionary<string, object> { {"master", new object() }, {"branch", new object() }, }; lock (locks[branch]) { // ... } Solution WHY NOT
  • 42. Performance WHY NOT Writes per second 125 (10,000 files) 18 (1,000,000 files) 100644 blob b9e36d8ed060ebdad585e93cec84 1.json 100644 blob 5a947c79aae7b7f6c663f632bfcf 2.json . . 100644 blob 4b54f5a8e56cfbc90947e3071ef6 999998.json 100644 blob 06179b3af5668bf7aa1dcb205949 999999.json 100644 blob a3d0db85108eb3e0c3d2b989a2ce 1000000.json tree B tree A commit master ... 100644 blob b9e36d8ed060ebdad585e93cec84 1.json 100644 blob 5a947c79aae7b7f6c663f632bfcf 2.json . . 100644 blob 4b54f5a8e56cfbc90947e3071ef6 999998.json 100644 blob 06179b3af5668bf7aa1dcb205949 999999.json 100644 blob a3d0db85108eb3e0c3d2b989a2ce 1000000.json 100644 blob 5bc5e544f68a56f992ca2be2fd26 1000001.json
  • 43. ... 100 ... 100 ... 100 ... 100 ... 100 ... 100 ... 100 Solution: tree nesting WHY NOT Writes per second 125 (10,000 files) 18 (1,000,000 files) 250 (1,000,000 files)
  • 44. Solution: partitioning WHY NOT App Repo 1 Disk 1 Repo 2 Disk 2 Repo 3 Disk 3 ... ...
  • 48. Good idea Bad idea Content heavy CMS, Wiki, … Partitionable Country, customer, … Fast writes Immediate consistency
  • 49. Demo
  • 50. (ab)use your tools Kenneth Truyers @kennethtruyers www.kenneth-truyers.net bit.ly/git-db-code bit.ly/git-nosql