Git repo – En analyse
Du vet, Github sine diagrammer på profil-siden? De har jeg alltid sett på og tenkt: “Det hadde vært gøy å lage flere av disse – se koden sin gang over tid”.
Men hvordan får vi til dette? Hvor starter man?
Jo, det vi må gjøre først er å trekke ut dataene vi trenger fra git. Så må vi putte dataene inn i en database. Ved å gjøre dette får vi alle fordelene en database gir oss, så som å kjøre spørringer mot dataene. Sist men ikke minst må vi tegne opp dataene på et eller annet vis.
Steg 1 - Samle inn dataene vi trenger
For å få innblikk i et repo sin git-historikk kan vi anvende git log
. Den gir
oss en tekstlig historikk av alt som har skjedd i repo-et siden det ble
opprettet.
Tekst kan vi ikke gjøre så mye med, så vi må parse dataene først. Ved å kjøre
git log
får vi dette:
commit 4582c769dcf751b029f0934bc60afc62df0e9616
Author: Christian Johansen <christian@jaliksom.du>
Date: Sat Jun 14 10:19:06 2025 +0200
Oppdater Dataspex
commit eb15e5b76f28ec124944e7fbda5f06e47b6d4572
Author: Magnar Sveen <magnar@ja.serr>
Date: Fri Jun 13 14:54:54 2025 +0200
Fullfør enhetliggjøringen av sentinels: submission-sentinel
Istedenfor å bruke bare form-id for å finne tilbake til en submission i
sentinelen, så bruker vi nå :form/kind med en optional :form/key. Dette
tilsvarer da command-sentinel og query-sentinel, og tillater flere instanser av
samme skjema på samme side.
Men dette er ikke så enkelt å parse. Ikke stress, for git log
støtter å
formatere resultatet. Med flagget --pretty=format:
kan du legge til hvilke
felter du ønsker og i hvilken form. I tilleg kan du legge til --numstat
som
gir deg antal linjer lagt til og fjernet for hver fil i hver commit. Da får vi
denne kommandoen:
git log --numstat --pretty=format:%H%n%an%n%ae%n%aI%n%cn%n%ce%n%cI%n%s%n%b
Feltene vi har her er:
%H
: full git sha%an
: forfatter navn%ae
: forfatter epost%aI
: forfatter dato%cn
: committer navn%ce
: committer epost%cI
: committer dato%s
: commit melding%b
: commit beskrivelse%n
: ny linje
Resultatet vi får ut da, blir:
4582c769dcf751b029f0934bc60afc62df0e9616
Christian Johansen
christian@jaliksom.du
2025-06-14T10:19:06+02:00
Christian Johansen
christian@jaliksom.du
2025-06-15T22:38:44+02:00
Oppdater Dataspex
2 2 deps.edn
7 2 src/matnyttig/ui/dev.cljs
eb15e5b76f28ec124944e7fbda5f06e47b6d4572
Magnar Sveen
magnar@ja.serr
2025-06-13T14:54:54+02:00
Magnar Sveen
magnar@ja.serr
2025-06-13T14:54:54+02:00
Fullfør enhetliggjøringen av sentinels: submission-sentinel
Istedenfor å bruke bare form-id for å finne tilbake til en submission i
sentinelen, så bruker vi nå :form/kind med en optional :form/key. Dette
tilsvarer da command-sentinel og query-sentinel, og tillater flere instanser av
samme skjema på samme side.
3 3 org/røkla.org
1 1 src/matnyttig/imperative_shell/client/director.cljs
11 9 src/matnyttig/imperative_shell/client/submission_center.cljs
3 14 src/matnyttig/sider/adressevaskside/konkluder_adressevask_skjema.cljc
3 3 src/matnyttig/sider/adressevaskside/sjekk_adresse_skjema.cljc
8 5 src/matnyttig/sider/planlegging_av_tur/ui.cljc
27 15 src/matnyttig/sider/preferanser/ui.cljc
2 2 src/matnyttig/sider/smilefjessteder/ui.cljc
1 1 src/matnyttig/sider/sok/sokeskjema.cljc
1 1 src/matnyttig/sider/sok/ui.cljc
5 5 src/matnyttig/sider/vask_av_opptatt_lokale/konkluder_opptatt_lokale_skjema.cljc
16 9 src/matnyttig/ui/submission_sentinel.cljc
Dette er brukbart! 🙌
Med verdiene på hver sin linje blir det veldig enkelt å parse.
Steg 2 - Parse dataene
Dette er ganske rett frem. Nesten 😅
Vi kommer veldig langt med å splitte på \n
. Men for den skarpe leseren kan
commit beskrivelsen være over flere linjer. Dette må håndteres på en eller annen
vis. Det samme med linje-endringene.
Men med litt fiks-fakseri ender vi opp med:
[["4582c769dcf751b029f0934bc60afc62df0e9616"
"Christian Johansen"
"christian@jaliksom.du"
"2025-06-14T10:19:06+02:00"
"Christian Johansen"
"christian@jaliksom.du"
"2025-06-15T22:38:44+02:00"
"Oppdater Dataspex"
""
[["2" "2" "deps.edn"] ["7" "2" "src/matnyttig/ui/dev.cljs"]]]
["eb15e5b76f28ec124944e7fbda5f06e47b6d4572"
"Magnar Sveen"
"magnar@ja.serr"
"2025-06-13T14:54:54+02:00"
"Magnar Sveen"
"magnar@ja.serr"
"2025-06-13T14:54:54+02:00"
"Fullfør enhetliggjøringen av sentinels: submission-sentinel"
"Istedenfor å bruke bare form-id for å finne tilbake til en submission i\nsentinelen, så bruker vi nå :form/kind med en optional :form/key. Dette\ntilsvarer da command-sentinel og query-sentinel, og tillater flere instanser av\nsamme skjema på samme side."
[["3" "3" "\"org/r\\303\\270kla.org\""]
["1" "1" "src/matnyttig/imperative_shell/client/director.cljs"]
["11" "9" "src/matnyttig/imperative_shell/client/submission_center.cljs"]
["3"
"14"
"src/matnyttig/sider/adressevaskside/konkluder_adressevask_skjema.cljc"]
["3" "3" "src/matnyttig/sider/adressevaskside/sjekk_adresse_skjema.cljc"]
["8" "5" "src/matnyttig/sider/planlegging_av_tur/ui.cljc"]
["27" "15" "src/matnyttig/sider/preferanser/ui.cljc"]
["2" "2" "src/matnyttig/sider/smilefjessteder/ui.cljc"]
["1" "1" "src/matnyttig/sider/sok/sokeskjema.cljc"]
["1" "1" "src/matnyttig/sider/sok/ui.cljc"]
["5"
"5"
"src/matnyttig/sider/vask_av_opptatt_lokale/konkluder_opptatt_lokale_skjema.cljc"]
["16" "9" "src/matnyttig/ui/submission_sentinel.cljc"]]]]
Da er vi bare en mapping-funksjon unna en god datastruktur! 💯
Steg 3 - Put dataene inn i en database
Ved å putte dataene inn i en database, blir den veldig enkel å jobbe med 💪
Ved å putte dataene inn i Datomic eller Datascript, blir den enda enklere å jobbe med 🙌
Uansett hvilket diagram vi ønsker oss å tegne, har vi dataene rett ved fingerspissene og kan forespørre den om hva vi vil på kryss og tvers 🎉
Helt strålende!
Mapping-funksjonen nevnt over tar bare hver item i hver commit og mapper til en mer medgjørlig datastruktur – og èn databasen vil skjønne. Resultatet av mappinga ser omtrent sånn ut:
({:commit/full-hash "4582c769dcf751b029f0934bc60afc62df0e9616"
:commit/subject "Oppdater Dataspex"
:commit/body ""
:commit/author-date #inst "2025-06-14T08:19:06.000-00:00"
:commit/commit-date #inst "2025-06-15T20:38:44.000-00:00"
:commit/author {:person/email "christian@jaliksom.du"
:person/name "Christian Johansen"}
:commit/committer {:person/email "christian@jaliksom.du"
:person/name "Christian Johansen"}
:commit/filestats [{:file/name "deps.edn"
:file/added 2
:file/removed 2}
{:file/name "src/matnyttig/ui/dev.cljs"
:file/added 7
:file/removed 2}]}
{:commit/full-hash "eb15e5b76f28ec124944e7fbda5f06e47b6d4572"
:commit/subject "Fullfør enhetliggjøringen av sentinels: submission-sentinel"
:commit/body "Istedenfor å bruke bare form-id for å finne tilbake til en submission i\nsentinelen så bruker vi nå :form/kind med en optional :form/key. Dette\ntilsvarer da command-sentinel og query-sentinel og tillater flere instanser av\nsamme skjema på samme side."
:commit/author-date #inst "2025-06-13T12:54:54.000-00:00"
:commit/commit-date #inst "2025-06-13T12:54:54.000-00:00"
:commit/author {:person/email "magnar@ja.serr"
:person/name "Magnar Sveen"}
:commit/committer {:person/email "magnar@ja.serr"
:person/name "Magnar Sveen"}
:commit/filestats [{:file/name "org/røkla.org"
:file/added 3
:file/removed 3}
{:file/name "src/matnyttig/imperative_shell/client/director.cljs"
:file/added 1
:file/removed 1}
{:file/name "src/matnyttig/imperative_shell/client/submission_center.cljs"
:file/added 11
:file/removed 9}
{:file/name "src/matnyttig/sider/adressevaskside/konkluder_adressevask_skjema.cljc"
:file/added 3
:file/removed 14}
{:file/name "src/matnyttig/sider/adressevaskside/sjekk_adresse_skjema.cljc"
:file/added 3
:file/removed 3}
{:file/name "src/matnyttig/sider/planlegging_av_tur/ui.cljc"
:file/added 8
:file/removed 5}
{:file/name "src/matnyttig/sider/preferanser/ui.cljc"
:file/added 27
:file/removed 15}
{:file/name "src/matnyttig/sider/smilefjessteder/ui.cljc"
:file/added 2
:file/removed 2}
{:file/name "src/matnyttig/sider/sok/sokeskjema.cljc"
:file/added 1
:file/removed 1}
{:file/name "src/matnyttig/sider/sok/ui.cljc"
:file/added 1
:file/removed 1}
{:file/name "src/matnyttig/sider/vask_av_opptatt_lokale/konkluder_opptatt_lokale_skjema.cljc"
:file/added 5
:file/removed 5}
{:file/name "src/matnyttig/ui/submission_sentinel.cljc"
:file/added 16
:file/removed 9}]})
Steg 4 – Tegn resten av ugla 🤷♂️
Nå har vi alt vi trenger for å gjøre noe med disse dataene, og vi har kommet til artiklens faktiske formål.
Jeg har valgt å bruke D3 som er et javascript visualiseringsbibliotek. Det eksponerer mange funksjoner for å jobbe med data og bruker kraften av SVG til å tegne opp diagrammer - akkurat som du vil ha dem ✨
Jeg kommer ikke til å gå i dypden med hvordan D3 fungerer. Det er det ikke plass til her så det får bli en annen bloggpost.
Jeg etterlater dere med antall commits lagt til i Matnyttig hver måned:
Mer spennende ting kommer, men enn så lenge – her er koden så langt
Med denne, kanskje litt anti-klimatiske, avslutningen, da var poenget her ikke å vise kule innsikter i kodebasen vår eller imponerende grafer, men rettere hvordan man kan få tak i dataene under panseret til git og gjøre den om til en deilig, smibar masse. Og da ligger mulighetene helt oppe.