{
  "version": "https://jsonfeed.org/version/1.1",
  "title": "Continuous Learning",
  "home_page_url": "https://anders.dev/",
  "feed_url": "https://anders.dev/feed.json",
  "description": "This is where I share and save my findings for you and my future self.",
  "language": "en-us",
  
  "authors": [
    {
      "name": "Anders",
      "url": "https://anders.dev/"
      ,
      "avatar": "https://anders.dev/images/me.png"
      
    }
  ],
  
  "items": [
    
    
    
    {
      "id": "https://anders.dev/posts/4-moosic/",
      "url": "https://anders.dev/posts/4-moosic/",
      "title": "Moosic",
      "content_html": "\u003ch2 class=\"heading\" id=\"how-it-started\"\u003e\n  How it started\n  \u003ca href=\"#how-it-started\"\u003e#\u003c/a\u003e\n\u003c/h2\u003e\n\u003cp\u003eIt started on March 18th.\u003c/p\u003e\n\u003cp\u003eThat was the day I published \u003cstrong\u003e\u003ca href=\"https://github.com/andvision/fugue\"\u003eFugue proxy\u003c/a\u003e\u003c/strong\u003e ready to be used other than me. Nothing flashy, just bytes flowing through the right pipes, in the right shape, at the right time. But it was enough. Enough to know that the thing in my head was actually buildable.\u003c/p\u003e\n\u003cp\u003eSo I did what you do when something clicks: I brought it to my friends. Not the developer ones, the \u003cem\u003eother\u003c/em\u003e ones. The group chat. I pitched the idea of reviving Winamp on top of this proxy, using the Navidrome API as the backend. A proper music player. Skins. The visualizer. That whole feeling.\u003c/p\u003e\n\u003cp\u003eThe response was, more or less: \u003cem\u003e“sounds like it’s on your table, then.”\u003c/em\u003e\u003c/p\u003e\n\u003cp\u003eAnd they weren’t wrong. Nobody else was going to build it. That’s the quiet truth behind most side projects that actually ship, there’s a thing you want to exist in the world, you look around, and the chair where someone else might build it is empty.\u003c/p\u003e\n\u003cp\u003eBut underneath the pitch was something I hadn’t really said out loud yet. It wasn’t just nostalgia for Winamp, though there was plenty of that, late nights, custom skins, the orange glow of the equalizer, the llama. It was more that I miss what listening to music \u003cem\u003efelt\u003c/em\u003e like back then. Intentional. Owned. Something you picked and put on, not something an algorithm drip-fed you between ads.\u003c/p\u003e\n\u003cp\u003eWhat we have today is mostly noise. Playlists of AI-generated filler designed to be metabolized without being heard. Music that passes through your ears without ever arriving. I want the other thing back, the thing where you sat down, queued up an album, and \u003cem\u003elistened\u003c/em\u003e. I can’t fix the industry, but I can build the player I want to use. And if someone else wants to use it too, even better.\u003c/p\u003e\n\u003cp\u003eThat player became \u003cstrong\u003e\u003ca href=\"https://moosic.now\"\u003eMoosic\u003c/a\u003e\u003c/strong\u003e.\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 class=\"heading\" id=\"the-technical-story\"\u003e\n  The technical story\n  \u003ca href=\"#the-technical-story\"\u003e#\u003c/a\u003e\n\u003c/h2\u003e\n\u003cp\u003eFrom here on, this gets technical. If you came for the vibes, the vibes are above. Below is the actual architecture, the choices, the dead ends, and the reasoning.\u003c/p\u003e\n\u003ch3 class=\"heading\" id=\"the-problem-space\"\u003e\n  The problem space\n  \u003ca href=\"#the-problem-space\"\u003e#\u003c/a\u003e\n\u003c/h3\u003e\n\u003cp\u003eThe Subsonic API is, at this point, the closest thing the self-hosted music world has to a lingua franca. Navidrome is the most pleasant server implementation of it I’ve used, fast, opinionated in the right ways, low-drama to operate. So the server side was, effectively, a solved problem. I didn’t want to build another server. I wanted to build the \u003cem\u003eclient\u003c/em\u003e I kept wishing existed.\u003c/p\u003e\n\u003cp\u003eThe existing Subsonic client landscape has good options, but none of them scratched the specific itch: a native desktop player with a deliberate aesthetic, built for people who are nostaldic about their mp3 usage.\u003c/p\u003e\n\u003ch3 class=\"heading\" id=\"why-a-proxy-at-all-fugue\"\u003e\n  Why a proxy at all: Fugue\n  \u003ca href=\"#why-a-proxy-at-all-fugue\"\u003e#\u003c/a\u003e\n\u003c/h3\u003e\n\u003cp\u003eHere’s the part of the story that gets out of order if you’re not careful: \u003cstrong\u003eFugue came first. Moosic came out of Fugue.\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eI had multiple Navidrome instances, different libraries on different boxes, for different reasons, and no good way to make a single client see them as one. As far as I could find, nothing in the Subsonic ecosystem merged libraries across servers. So I built Fugue: a Subsonic-compatible proxy that sits in front of one or more upstream servers, presents a unified library to whatever client connects, routes stream requests back to whichever server actually owns each track, and handles auth and a caching layer along the way.\u003c/p\u003e\n\u003cp\u003eTo the client, Fugue looks like a regular Subsonic server. Underneath, it can be fronting a single Navidrome or a fleet of them, and the client doesn’t have to know or care.\u003c/p\u003e\n\u003cp\u003eFugue is its own project, separate repository, fully open source, useful with any Subsonic client. Moosic does not require it. You can point Moosic straight at a Navidrome and it will work fine. But the two have a love story: when Moosic talks to Fugue specifically, they can establish a \u003cstrong\u003eQUIC connection with NAT traversal via Iroh\u003c/strong\u003e, which means you can run Fugue at home and reach it from anywhere without port-forwarding, dynamic DNS, or a VPN. The underlying API is still Subsonic, just delivered over a much friendlier transport.\u003c/p\u003e\n\u003cp\u003eThe March 18th proof of concept was scrappier than it sounds. Winamp skins rendering, music actually streaming through the proxy, and roughly as many bugs as you’d expect from a one-day prototype. But all the pieces were in the same room for the first time, and that’s when I knew it was a real thing.\u003c/p\u003e\n\u003cp\u003eThe exploration with Fugue is what led to Moosic. Once I had a clean library layer to point a client at, the question of what the ideal client on top of it looked like turned into a retro-inspired desktop player, and that question wouldn’t leave me alone.\u003c/p\u003e\n\u003ch3 class=\"heading\" id=\"why-rust\"\u003e\n  Why Rust\n  \u003ca href=\"#why-rust\"\u003e#\u003c/a\u003e\n\u003c/h3\u003e\n\u003cp\u003eRust was not a foregone conclusion. The honest reasons it won:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eIt’s the language I want to maintain code in five years from now.\u003c/strong\u003e A commercial music player has to be something I can still build, ship, and debug long after the initial burst of enthusiasm fades. Rust’s compile-time guarantees are a gift to future-me, who will have forgotten everything.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eDistribution.\u003c/strong\u003e A single statically-linked binary per platform, no runtime for the user to install, no “please install the correct .NET version” support emails.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eAudio and concurrency.\u003c/strong\u003e The ecosystem (\u003ccode\u003ecpal\u003c/code\u003e, \u003ccode\u003esymphonia\u003c/code\u003e, \u003ccode\u003erodio\u003c/code\u003e, async runtimes) is genuinely good, and the borrow checker keeps the audio thread honest.\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch3 class=\"heading\" id=\"why-skia-for-the-gui\"\u003e\n  Why Skia for the GUI\n  \u003ca href=\"#why-skia-for-the-gui\"\u003e#\u003c/a\u003e\n\u003c/h3\u003e\n\u003cp\u003eI went back and forth between GPUI and Skia before landing on Skia. The decision came down to:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eControl over the aesthetic.\u003c/strong\u003e A Winamp-inspired player needs pixel-level control, custom widgets, and the freedom to ignore platform conventions when that’s the right call. Immediate-mode-ish rendering on top of Skia gives me that without fighting a framework.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eCross-platform consistency.\u003c/strong\u003e The same renderer on macOS (Metal backend), Windows, and Linux means the player looks and feels identical everywhere, which matters when the \u003cem\u003elook\u003c/em\u003e is a significant part of the product.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eMaturity.\u003c/strong\u003e Skia is what Chrome, Flutter, and a lot of other serious software render with. It is not going away.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eWhat I didn’t expect was how \u003cem\u003epleasant\u003c/em\u003e Skia would feel coming back from years of web stacks. You’re handed a canvas and a pile of pixels, and that’s it. No component framework with the wrong primitive for what you’re trying to build. No escape hatch into a workaround for a workaround. There’s more boilerplate, sure, text shaping, hit testing, layout, you write all of it, but the trade is that nothing is in your way. I had forgotten how good that felt.\u003c/p\u003e\n\u003ch3 class=\"heading\" id=\"the-winamp-question-aesthetic-not-clone\"\u003e\n  The Winamp question: aesthetic, not clone\n  \u003ca href=\"#the-winamp-question-aesthetic-not-clone\"\u003e#\u003c/a\u003e\n\u003c/h3\u003e\n\u003cp\u003eI started this as a pure Winamp clone for Navidrome streaming, and within a few days I could feel myself fighting the design constraints. It stopped being fun. So I stopped, and asked the question I should have asked at the start: what would I want a music player to be \u003cem\u003etoday\u003c/em\u003e, and what am I missing from the streaming services I actually use? Things like having visiable queue without a ceremony. A queue that’s always one click away, not buried two screens deep. Something that lives on your desktop instead of in a tab.\u003c/p\u003e\n\u003cp\u003eReviving “the feeling of Winamp” is not the same as cloning Winamp. I looked carefully at the trade dress question early on, skin format compatibility, iconography, layout, and drew a line. Moosic takes inspiration from that era of music software (compact, dense, \u003cem\u003epresent\u003c/em\u003e on your desktop rather than hidden in a browser tab), but it is its own product with its own visual identity.\u003c/p\u003e\n\u003cp\u003eThat identity, concretely:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eTwo UIs in one app.\u003c/strong\u003e A modern UI as the default, and a Retro UI for the people who want the dense, skinnable, era-correct experience. Anything skin-related lives in the Retro UI; the modern UI deliberately does not support skin formats.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eCompact, never fullscreen.\u003c/strong\u003e Fullscreen is the one mode Moosic does not have. It is meant to live in the corner of your screen, ready when you want it. There is a mini player and an always-on-top mode for the times you don\u0026rsquo;t want loose it.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eTypography.\u003c/strong\u003e Inter, with Helvetica Neue as fallback.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eDefault palette.\u003c/strong\u003e Warm yellows on a dark background, with a light mode for people who prefer it. Paid users can change the palette to whatever they like.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eNo fancy visualizations. No plugin system.\u003c/strong\u003e I don’t think we need either today. Prove me wrong.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 class=\"heading\" id=\"licensing-offline-verifiable-signed-license-blobs\"\u003e\n  Licensing: offline-verifiable signed license blobs\n  \u003ca href=\"#licensing-offline-verifiable-signed-license-blobs\"\u003e#\u003c/a\u003e\n\u003c/h3\u003e\n\u003cp\u003eMoosic is commercial software, but I refuse to ship a player that phones home every time it starts. That would betray the entire premise. So the licensing model is \u003cstrong\u003efully offline-verifiable\u003c/strong\u003e:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eThe user receives a license as a signed JSON blob.\u003c/li\u003e\n\u003cli\u003eThe blob is signed with an \u003cstrong\u003eEd25519\u003c/strong\u003e private key. The corresponding \u003cstrong\u003epublic key is hardcoded into the Moosic binary.\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003eVerification at runtime is a pure function: parse the blob, check the signature against the embedded public key, done. No network call. No server dependency. If my business disappears tomorrow, every existing license keeps working forever.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eThe blob itself is small and boring on purpose:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003eschema_version\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003ename\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eemail\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003etier\u003c/code\u003e, defaults to lifetime\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003efeatures\u003c/code\u003e, part of the signed payload, so it’s tamper-proof\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eissued_at\u003c/code\u003e, Unix time\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eexpires_at\u003c/code\u003e, defaults to “never”\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003enonce\u003c/code\u003e, used for refund handling\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eI don’t store the license blob itself anywhere on my side. The signing service generates it, sends it, and forgets it. The only things I keep are the Polar order id and the nonce, enough to process a refund and nothing more.\u003c/p\u003e\n\u003cp\u003eThe license is \u003cstrong\u003enot bound to a specific machine.\u003c/strong\u003e Once the blob leaves my service, it’s a piece of paper the user owns. Run it on your laptop and your desktop. Reinstall the OS. I don’t care, and I don’t want to know.\u003c/p\u003e\n\u003cp\u003eIf my signing key is ever lost or compromised, the existing licenses keep working, they’re already signed and verify against the embedded public key in their corresponding Moosic version. I’d generate a new keypair, ship a new version of Moosic that embeds the new public key, and re-issue licenses for that version going forward. The price of that is a one-time inconvenience for me; the benefit is that no user ever has a license stop working because of something on my end.\u003c/p\u003e\n\u003cp\u003eI’m aiming for \u003cstrong\u003ev1 to be feature-complete on its own.\u003c/strong\u003e If a v2 ever happens, it will be something genuinely radical, likely with a different financing model, and not a way to charge people again for the thing they already bought. Hopefully we never get there.\u003c/p\u003e\n\u003ch3 class=\"heading\" id=\"checkout-polarsh-as-merchant-of-record-but-not-as-license-service\"\u003e\n  Checkout: Polar.sh as merchant of record, but not as license service\n  \u003ca href=\"#checkout-polarsh-as-merchant-of-record-but-not-as-license-service\"\u003e#\u003c/a\u003e\n\u003c/h3\u003e\n\u003cp\u003eFor payments I’m using \u003cstrong\u003ePolar.sh\u003c/strong\u003e as the merchant of record. The reason is boring and correct: I do not want to be in the business of collecting VAT across the World, handling chargebacks, or arguing with Stripe about dispute fees. Polar handles the commercial surface and I stay focused on the product.\u003c/p\u003e\n\u003cp\u003eWhat I am specifically \u003cem\u003enot\u003c/em\u003e using is Polar’s license issuing service, because that path involves a phone-home check and that is the line I am not crossing. Instead:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003ePolar processes the purchase and fires a webhook.\u003c/li\u003e\n\u003cli\u003eA \u003cstrong\u003eserverless worker\u003c/strong\u003e receives the webhook, generates the signed license blob, and sends the email via \u003cstrong\u003eResend\u003c/strong\u003e.\u003c/li\u003e\n\u003cli\u003eThe user’s inbox is the only place the license lives. They can forward it to themselves, save it, archive it, it’s theirs.\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003eThe whole thing is end-to-end automated, runs in a serverless worker, and has no piece of persistent infrastructure I have to babysit.\u003c/p\u003e\n\u003ch3 class=\"heading\" id=\"distribution\"\u003e\n  Distribution\n  \u003ca href=\"#distribution\"\u003e#\u003c/a\u003e\n\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003emacOS:\u003c/strong\u003e bundled with \u003ccode\u003ecargo-bundle\u003c/code\u003e, then \u003ccode\u003eproductbuild\u003c/code\u003e, signed and notarized. Mac App Store submission is on the roadmap once there’s revenue to justify the time, sandboxing constraints and the reviewer-testability problem (you need a Subsonic server to meaningfully test the app) are the two open questions there.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eWindows:\u003c/strong\u003e unsigned binaries today. A code signing certificate is on the list as soon as there’s revenue from the app to pay for it. Until then, SmartScreen will be unhappy and that’s a tradeoff I’m taking knowingly.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eLinux:\u003c/strong\u003e package format is intentionally unsettled. AppImage, Flatpak, AUR, I’m waiting to see what users actually ask for before committing to one.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 class=\"heading\" id=\"what-i-learned-from-poc--product\"\u003e\n  What I learned from PoC → product\n  \u003ca href=\"#what-i-learned-from-poc--product\"\u003e#\u003c/a\u003e\n\u003c/h3\u003e\n\u003cp\u003eA few honest ones:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eThe last 10% takes 90% of the time, and it isn’t code.\u003c/strong\u003e Quirks, CI/CD, a website that doesn’t embarrass you, figuring out tax across jurisdictions, that’s what was actually hard until i found out about the magic word MoS. The audio pipeline was the easy part, Mac OS handling of sampling was kind of interesting and worth it\u0026rsquo;s own post.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eSkia after web stacks is a holiday.\u003c/strong\u003e I’ve already said this above but it bears repeating. Pixels and a canvas. Some boilerplate. Nothing in your way.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eThe Subsonic API is mostly complete, but its extensibility is the weak point.\u003c/strong\u003e I’d love for it to be a bit more agnostic. For things like podcasts, OpenSubsonic is where I’m looking next.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eThere are an absurd number of turn-key licensing and subscription SDKs in 2026.\u003c/strong\u003e You can be selling software in an afternoon. I deliberately chose not to use any of them, because every single one would have created either a phone-home dependency or a “this app stops working when the vendor disappears” failure mode. Both are betrayals of what I’m trying to build.\u003c/li\u003e\n\u003c/ol\u003e\n\u003chr\u003e\n\u003ch2 class=\"heading\" id=\"where-its-going\"\u003e\n  Where it’s going\n  \u003ca href=\"#where-its-going\"\u003e#\u003c/a\u003e\n\u003c/h2\u003e\n\u003cp\u003eShort list of what’s next:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eCasting and AirPlay.\u003c/strong\u003e First on the list. People have phones and speakers; the player should meet them there.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eParty mode, with Fugue.\u003c/strong\u003e Friends listening to the same library and contributing to the same queue, riding on Fugue’s NAT-traversed connection. Still an idea, not yet a plan.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eA SHOUTcast-shaped thought.\u003c/strong\u003e I keep turning over what a modern, opinionated take on SHOUTcast could look like in the Moosic + Fugue world. No promises, just curiosity.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eIf you want to try it, you can. Download Moosic and play your first 10 tracks for free, that’s enough to know whether it’s the player you’ve been wanting. If it is, it’s \u003cstrong\u003e$19, lifetime\u003c/strong\u003e, at \u003cstrong\u003ebuy.moosic.now\u003c/strong\u003e. I’d be genuinely happy to have you as a customer. Try it first.\u003c/p\u003e\n\u003cp\u003eA note on what Moosic is \u003cem\u003enot\u003c/em\u003e: it is not a player for arbitrary files on your disk. It is a streaming client for Navidrome and other Subsonic-compatible servers. If that’s the gap you’ve been waiting to be filled, same.\u003c/p\u003e\n",
      "date_published": "2026-04-26T00:00:00Z"
      ,
      "date_modified": "2026-04-26T00:00:00Z"
      
      ,
      "tags": ["moosic","rust"]
      
      
    }
    
    ,
    {
      "id": "https://anders.dev/posts/3-homelab-part-1/",
      "url": "https://anders.dev/posts/3-homelab-part-1/",
      "title": "Homelab",
      "content_html": "\u003cp\u003eAs long as I can remember that I have had flat rate internet connection (the village I\u0026rsquo;m from we gathered together and digged our own fiber optics but that\u0026rsquo;s a story for later), I have always had some sort of homelab up and running, started with a fire hazard cardboard box with a 133 Mhz motherboard from a IBM Aptiva in it, for the sake of easy modifications, thank god that it never catch fire.\u003c/p\u003e\n\u003cp\u003eIn university years it was mainly some raspberry pi placed nearby the router. And up to today a few raspberry pi\u0026rsquo;s and a Synology NAS everything is maxed out on CPU usage and RAM memory allocation, docker instances provisioned by Hashicorp Nomad and different services around for service discovery. I\u0026rsquo;m in big need for an upgrade, the NAS is not intended for this kind of load.\u003c/p\u003e\n\u003cp\u003eSo when I found out about the \u003ca href=\"https://mini-rack.jeffgeerling.com/\"\u003eMINI RACK project\u003c/a\u003e initiated by Jeff Geerling I was hooked. For the software stack I was kind of clueless I had got bitten by the bug with specified deployments instead of writing long bash scripts for setting up a service, or manually install everything and doing ClickOps. I needed to go further with the next steps in my journey of handling a homelab.\u003c/p\u003e\n\u003cp\u003eLet me present GitOps a term which I have ignored for so many years due to time constrains in my life but \u003ca href=\"https://mischavandenburg.com/\"\u003eMischa van den Burg\u003c/a\u003e have introduced with a clear path defining everything in Git and let the magic happens to be deployed to a kubernetes cluster so why not just build my own cluster then? The truth was that the idea of building my own homelab sparked by Mischa.\u003c/p\u003e\n\u003cp\u003eHere we are! my homelab is being upgraded and redesigned from scratch but my NAS will still be in the picture but only for long term backup and nothing else.\u003c/p\u003e\n\u003cp\u003e![[1 Projects/HomeLab/rack drawing.md#^group=ehMHUDvhqVNq46NiOh9xF]]\u003c/p\u003e\n\u003cp\u003eThe software stack with Hashicorp Nomad is migrated to Kubernetes, instead of different kind of pipeline scripts for deploying the services, I use FluxCD for the Gitops part, instead of using the NAS slow mechanical disk i build a Rook-Ceph cluster where data on the Minisforum MS-A2 NVMe disks can be shared between the nodes, on its own 10 GBe SPF+ network. I started with two worker nodes and a raspberry PI as a companion for handling the control plane to maintain quorum. Too keep my hands from custom quick fix I use Talos Linux which is a distribution for Kubernetes and keep it\u0026rsquo;s file system immutable and without SSH ability.\u003c/p\u003e\n\u003ctable\u003e\n  \u003cthead\u003e\n      \u003ctr\u003e\n          \u003cth\u003eUnits\u003c/th\u003e\n          \u003cth\u003eType\u003c/th\u003e\n          \u003cth\u003eSKU\u003c/th\u003e\n          \u003cth\u003ePrice (SEK)\u003c/th\u003e\n          \u003cth\u003eNote\u003c/th\u003e\n          \u003cth\u003eBought\u003c/th\u003e\n      \u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e1\u003c/td\u003e\n          \u003ctd\u003eSwitch\u003c/td\u003e\n          \u003ctd\u003eMikrotik CRS305-1G-4S+IN\u003c/td\u003e\n          \u003ctd\u003e1400\u003c/td\u003e\n          \u003ctd\u003e\u003c/td\u003e\n          \u003ctd\u003ex\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e5\u003c/td\u003e\n          \u003ctd\u003eCable\u003c/td\u003e\n          \u003ctd\u003eSFP+ DAC\u003c/td\u003e\n          \u003ctd\u003e147\u003c/td\u003e\n          \u003ctd\u003e\u003c/td\u003e\n          \u003ctd\u003ex\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e2\u003c/td\u003e\n          \u003ctd\u003eNode\u003c/td\u003e\n          \u003ctd\u003eMinisform MS-A2\u003c/td\u003e\n          \u003ctd\u003e10258\u003c/td\u003e\n          \u003ctd\u003e\u003c/td\u003e\n          \u003ctd\u003ex\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e2\u003c/td\u003e\n          \u003ctd\u003eNVMe\u003c/td\u003e\n          \u003ctd\u003eCrucial T500 4TB CT4000T500SSD3\u003c/td\u003e\n          \u003ctd\u003e3272\u003c/td\u003e\n          \u003ctd\u003e4 TB\u003c/td\u003e\n          \u003ctd\u003ex\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e2\u003c/td\u003e\n          \u003ctd\u003eNVme\u003c/td\u003e\n          \u003ctd\u003eBootdisk: SABRENT 2230 M.2 NVMe Gen 4 1TB\u003c/td\u003e\n          \u003ctd\u003e1257\u003c/td\u003e\n          \u003ctd\u003e\u003c/td\u003e\n          \u003ctd\u003ex\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e2\u003c/td\u003e\n          \u003ctd\u003eAdapter\u003c/td\u003e\n          \u003ctd\u003eNFHK M.2(A+E Key) 2230MM to NVME M-Key\u003c/td\u003e\n          \u003ctd\u003e153\u003c/td\u003e\n          \u003ctd\u003e\u003c/td\u003e\n          \u003ctd\u003ex\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e2\u003c/td\u003e\n          \u003ctd\u003eRAM\u003c/td\u003e\n          \u003ctd\u003eCrucial DDR5 RAM 96GB Kit CT2K48G56C46S5\u003c/td\u003e\n          \u003ctd\u003e2422\u003c/td\u003e\n          \u003ctd\u003e\u003c/td\u003e\n          \u003ctd\u003ex\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e1\u003c/td\u003e\n          \u003ctd\u003eUPS\u003c/td\u003e\n          \u003ctd\u003e\u003c/td\u003e\n          \u003ctd\u003e\u003c/td\u003e\n          \u003ctd\u003eNot decided yet\u003c/td\u003e\n          \u003ctd\u003e\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e1\u003c/td\u003e\n          \u003ctd\u003eRPI\u003c/td\u003e\n          \u003ctd\u003e\u003c/td\u003e\n          \u003ctd\u003e\u003c/td\u003e\n          \u003ctd\u003e\u003ca href=\"https://networkupstools.org/\"\u003eNUTS\u003c/a\u003e\u003c/td\u003e\n          \u003ctd\u003e\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e1\u003c/td\u003e\n          \u003ctd\u003erack\u003c/td\u003e\n          \u003ctd\u003eDeskPi RackMate T1\u003c/td\u003e\n          \u003ctd\u003e1947\u003c/td\u003e\n          \u003ctd\u003e\u003c/td\u003e\n          \u003ctd\u003ex\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e1\u003c/td\u003e\n          \u003ctd\u003ehylla\u003c/td\u003e\n          \u003ctd\u003eGeeekPi DeskPi Rack Shelf 10\u0026quot;\u003c/td\u003e\n          \u003ctd\u003e343\u003c/td\u003e\n          \u003ctd\u003e\u003c/td\u003e\n          \u003ctd\u003ex\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e\u003c/td\u003e\n          \u003ctd\u003e\u003c/td\u003e\n          \u003ctd\u003eTotal\u003c/td\u003e\n          \u003ctd\u003e39 129\u003c/td\u003e\n          \u003ctd\u003e\u003c/td\u003e\n          \u003ctd\u003e\u003c/td\u003e\n      \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp\u003eThe only issue I have found is that I cannot boot with the NVMe I have on the Wifi slot with a M.2(A+E Key) adaptor, but that is solved with PXE network boot, so not an issue in my setup.\u003c/p\u003e\n\u003cp\u003eI\u0026rsquo;m not done with the networking parts yet, still need to reconfigure the VLANs and get one more Switch with more ports\u003c/p\u003e\n\u003cp\u003eBut this is what I have in mind\u003c/p\u003e\n\u003cp\u003e!\n\n\n\n\n\n\n\n\n\n\n\n\u003cfigure class=\"\"\u003e\n\n    \u003cdiv\u003e\n        \u003cimg loading=\"lazy\" alt=\"Image Description\" src=\"/images/Network.png\" \u003e\n    \u003c/div\u003e\n\n    \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003cp\u003eIn the next post, I will go through the software stack of the cluster and how it is configured.\u003c/p\u003e\n",
      "date_published": "2025-06-18T00:00:00Z"
      ,
      "date_modified": "2025-06-18T00:00:00Z"
      
      ,
      "tags": ["tag1","tag2"]
      
      
    }
    
    ,
    {
      "id": "https://anders.dev/posts/2-bazel-build-system-and-rust/",
      "url": "https://anders.dev/posts/2-bazel-build-system-and-rust/",
      "title": "Bazel build system and Rust",
      "content_html": "\u003cp\u003e\u003cem\u003eI will write more posts for each step I\u0026rsquo;m learning Bazel together with Rust, but don\u0026rsquo;t wait for the next post because that could take a while.\u003c/em\u003e\u003c/p\u003e\n\u003cp\u003eA build system is a tool for automating the build process of software. There are multiple well known build systems which have been used for decades, \u003ccode\u003emake\u003c/code\u003e is one of the older ones. Then we have CMake, MSBuild, Gradle, Ant, Maven and the list can go on.\u003c/p\u003e\n\u003cp\u003eWhat is common for all build systems is: They have a process for how to compile source code into binary code, packaging binary code, and running automated tests.\u003c/p\u003e\n\u003cp\u003eMost common way to use build systems is to use a continuous integration chain which is activated when there is a committed change in the source or a new release.\u003c/p\u003e\n\u003cp\u003eBut still developers need to be able to build and execute their code locally on their desktops for shorter round trip to have a binary to test against in their environment.\u003c/p\u003e\n\u003cp\u003eBazels way of defining the builds enables that both the continuous integration chain and the developers local compiling process can take advantage of each other by having a shared cache of all builds and its dependencies. Developers have multiple iterations and changing their code and then compile it until they are satisfied, all these changes will have their own build which can be tracked and cached. So when the developer commit their code to the central repository, the build cache is also shared with the continuous integration chain so it can jump directly to testing without the need to rebuild everything.\u003c/p\u003e\n\u003cp\u003eThis enables so a developer can pull the whole source code and build it without rebuilding, because everything is in the cache.\u003c/p\u003e\n\u003ch1 class=\"heading\" id=\"why-not-cargo\"\u003e\n  Why not cargo\n  \u003ca href=\"#why-not-cargo\"\u003e#\u003c/a\u003e\n\u003c/h1\u003e\n\u003cp\u003eCargo is the build system and package manager in Rust and is well used by the rust community. It is the de facto standard in the Rust sphere. And by that it is easy to have a package system for different libraries or crates which they are called in Rust.\u003c/p\u003e\n\u003cp\u003eSo why not continue to use Cargo, you would first start argue with.\u003c/p\u003e\n\u003cp\u003eFor most of the projects out there, Cargo will be sufficient and there is no need to use Bazel or other build systems than Cargo.\u003c/p\u003e\n\u003cp\u003eBut the moment you have multiple teams in charge of different software components which shall work together in a bigger system, Cargo gets out grown pretty quickly. It can also be the case that different parts of the system is written in different programming languages. Bazel can handle different programming languages with rules, which is a set of actions which Bazel need to perform for making a build for that specific programming language or toolchain.\u003c/p\u003e\n\u003ch1 class=\"heading\" id=\"a-simple-example\"\u003e\n  A simple example\n  \u003ca href=\"#a-simple-example\"\u003e#\u003c/a\u003e\n\u003c/h1\u003e\n\u003cp\u003eThe following example is a minimal example of a simple rust project consisting of a binary, library and external crates. This can be handled by Bazel.\u003c/p\u003e\n\u003cp\u003eYou can view and clone the following project from github \u003ca href=\"https://github.com/Anders-Linden/rust_bazel_hello_world\"\u003eAnders-Linden / rust_bazel_hello_world\u003c/a\u003e\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003egit clone \u0026lt;https://github.com/Anders-Linden/rust_bazel_hello_world.git\u0026gt;\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eor just continue to follow bellow and manually set up the project.\u003c/p\u003e\n\u003ch2 class=\"heading\" id=\"folder-structure\"\u003e\n  Folder structure\n  \u003ca href=\"#folder-structure\"\u003e#\u003c/a\u003e\n\u003c/h2\u003e\n\u003cp\u003e\u003ccode\u003emkdir -p hello_world/srcmkdir -p hello_world/utilities/srcmkdir hello_world/assets\u003c/code\u003e\u003c/p\u003e\n\u003ch2 class=\"heading\" id=\"workspace\"\u003e\n  Workspace\n  \u003ca href=\"#workspace\"\u003e#\u003c/a\u003e\n\u003c/h2\u003e\n\u003cp\u003eThe Workspace file is the place Bazel is considering as the root path of the workspace, in this file it is stated what rules this project is going to be built by.\u003c/p\u003e\n\u003cp\u003eThis example uses the rust rules\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003ecat \u0026lt;\u0026lt;EOF \u0026gt; hello_world/WORKSPACE.bazel\nload(\u0026#34;@bazel_tools//tools/build_defs/repo:http.bzl\u0026#34;, \u0026#34;http_archive\u0026#34;)\n\nhttp_archive(\n    name = \u0026#34;io_bazel_rules_rust\u0026#34;,\n    sha256 = \u0026#34;618cba29165b7a893960de7bc48510b0fb182b21a4286e1d3dbacfef89ace906\u0026#34;,\n    strip_prefix = \u0026#34;rules_rust-5998baf9016eca24fafbad60e15f4125dd1c5f46\u0026#34;,\n    urls = [\n        # Master branch as of 2020-09-24\n        \u0026#34;\u0026lt;https://github.com/bazelbuild/rules_rust/archive/5998baf9016eca24fafbad60e15f4125dd1c5f46.tar.gz\u0026gt;\u0026#34;,\n    ],\n)\n\nload(\u0026#34;@io_bazel_rules_rust//rust:repositories.bzl\u0026#34;, \u0026#34;rust_repositories\u0026#34;)\n\nrust_repositories(version = \u0026#34;1.47.0\u0026#34;, edition=\u0026#34;2018\u0026#34;)\n\nload(\u0026#34;@io_bazel_rules_rust//:workspace.bzl\u0026#34;, \u0026#34;rust_workspace\u0026#34;)\n\nrust_workspace()\n\nload(\u0026#34;//cargo:crates.bzl\u0026#34;, \u0026#34;hello_cargo_library_fetch_remote_crates\u0026#34;)\n\nhello_cargo_library_fetch_remote_crates()\nEOF\n\u003c/code\u003e\u003c/pre\u003e\u003ch2 class=\"heading\" id=\"build-files\"\u003e\n  Build files\n  \u003ca href=\"#build-files\"\u003e#\u003c/a\u003e\n\u003c/h2\u003e\n\u003cp\u003eFor each binary or library or other artifact there is a BUILD file, this defines the source files and its dependendencies.\u003c/p\u003e\n\u003ch3 class=\"heading\" id=\"binary-build-file\"\u003e\n  Binary build file\n  \u003ca href=\"#binary-build-file\"\u003e#\u003c/a\u003e\n\u003c/h3\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003ecat \u0026lt;\u0026lt;EOF \u0026gt; hello_world/BUILD.bazel\nload(\u0026#34;@io_bazel_rules_rust//rust:rust.bzl\u0026#34;, \u0026#34;rust_binary\u0026#34;)\n\nrust_binary(\n    name = \u0026#34;hello_world\u0026#34;,\n    srcs = [\u0026#34;src/main.rs\u0026#34;],\n    data = [\u0026#34;assets/hello_world.txt\u0026#34;],\n    deps = [\u0026#34;//utilities\u0026#34;,\n            \u0026#34;//cargo:log\u0026#34;,\n            \u0026#34;//cargo:env_logger\u0026#34;],\n)\nEOF\n\u003c/code\u003e\u003c/pre\u003e\u003ch3 class=\"heading\" id=\"library-build-file\"\u003e\n  Library build file\n  \u003ca href=\"#library-build-file\"\u003e#\u003c/a\u003e\n\u003c/h3\u003e\n\u003cp\u003eA library is also built and then linked to a binary and the same code can be used in multiple binaries.\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003ecat \u0026lt;\u0026lt;EOF \u0026gt; hello_world/utilities/BUILD.bazel\npackage(default_visibility = [\u0026#34;//visibility:public\u0026#34;])\n\nload(\u0026#34;@io_bazel_rules_rust//rust:rust.bzl\u0026#34;, \u0026#34;rust_library\u0026#34;)\n\nrust_library(\n    name = \u0026#34;utilities\u0026#34;,\n    edition = \u0026#34;2018\u0026#34;,\n    srcs = [\n        \u0026#34;src/lib.rs\u0026#34;,\n    ],\n)\nEOF\n\u003c/code\u003e\u003c/pre\u003e\u003ch2 class=\"heading\" id=\"source-files\"\u003e\n  Source files\n  \u003ca href=\"#source-files\"\u003e#\u003c/a\u003e\n\u003c/h2\u003e\n\u003cp\u003eThis is ordinary Rust source files for the project\u003c/p\u003e\n\u003ch3 class=\"heading\" id=\"library-source\"\u003e\n  Library source\n  \u003ca href=\"#library-source\"\u003e#\u003c/a\u003e\n\u003c/h3\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003ecat \u0026lt;\u0026lt;EOF \u0026gt; hello_world/utilities/src/lib.rs\nuse std::fs::File;\nuse std::io::BufReader;\n\npub fn open_input(file_path: \u0026amp;str) -\u0026gt; std::io::BufReader\u0026lt;std::fs::File\u0026gt; {\n\tlet file = match File::open(file_path) {\n\t\tErr(why) =\u0026gt; panic!(\u0026#34;couldn\u0026#39;t open, {}\u0026#34;, why),\n\t\tOk(file) =\u0026gt; file,\n\t};\n\tBufReader::new(file)\n}\nEOF\n\u003c/code\u003e\u003c/pre\u003e\u003ch3 class=\"heading\" id=\"binary-source\"\u003e\n  Binary source\n  \u003ca href=\"#binary-source\"\u003e#\u003c/a\u003e\n\u003c/h3\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003ecat \u0026lt;\u0026lt;EOF \u0026gt; hello_world/src/main.rs\nuse std::io::prelude::*;\nextern crate utilities as utils;\n\nuse log;\n\nfn main()  {\n    env_logger::init();\n    log::info!(\u0026#34;Starting\u0026#34;);\n\tfor line in utils::open_input(\u0026#34;./assets/hello_world.txt\u0026#34;).lines() {\n        log::info!(\u0026#34;{}\u0026#34;, line.unwrap());\n\t}\n}\nEOF\n\u003c/code\u003e\u003c/pre\u003e\u003ch2 class=\"heading\" id=\"asset-file\"\u003e\n  Asset file\n  \u003ca href=\"#asset-file\"\u003e#\u003c/a\u003e\n\u003c/h2\u003e\n\u003cp\u003eJust a simple text-file which is going to be read and parsed.\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003ecat \u0026lt;\u0026lt;EOF \u0026gt; hello_world/assets/hello_world.txt\nhello, this is first row\nand this is the second row\nEOF\n\u003c/code\u003e\u003c/pre\u003e\u003ch2 class=\"heading\" id=\"cargo-file\"\u003e\n  Cargo file\n  \u003ca href=\"#cargo-file\"\u003e#\u003c/a\u003e\n\u003c/h2\u003e\n\u003cp\u003eThe cargo file is used by cargo-raze for generating an environment and the BUILD files for each external crate.\u003c/p\u003e\n\u003cp\u003eCargo-raze have different ways of handling crates\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eVendoring mode\u003c/li\u003e\n\u003cli\u003eRemote Dependency Mode\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eAnd then there is different ways of handling the building of crates depending on the complexity of the crate.\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eSimple crates\u003c/li\u003e\n\u003cli\u003eUnconventional Crates\u003c/li\u003e\n\u003cli\u003eCrates that need system libraries\u003c/li\u003e\n\u003cli\u003eCrates that supply useful binaries\u003c/li\u003e\n\u003cli\u003eCrates that only provide binaries\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eRead the documentation on \u003ca href=\"https://github.com/google/cargo-raze\"\u003eGithub cargo-raze\u003c/a\u003e\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003ecat \u0026lt;\u0026lt;EOF \u0026gt; hello_world/Cargo.toml\n[package]\nname = \u0026#34;hello_world\u0026#34;\nversion = \u0026#34;0.0.1\u0026#34;\nedition = \u0026#34;2018\u0026#34;\n\n[dependencies]\nlog = {version = \u0026#34;0.4.11\u0026#34;, features = [\u0026#34;std\u0026#34;]}\nenv_logger = \u0026#34;0.8.1\u0026#34;\n\n[[bin]]\nname = \u0026#34;hello_world\u0026#34;\npath = \u0026#34;src/main.rs\u0026#34;\n\n[raze]\nworkspace_path = \u0026#34;//cargo\u0026#34;\ntarget = \u0026#34;x86_64-apple-darwin\u0026#34;\noutput_buildfile_suffix = \u0026#34;BUILD.bazel\u0026#34;\ngen_workspace_prefix = \u0026#34;hello_cargo_library\u0026#34;\ngenmode = \u0026#34;Remote\u0026#34;\ndefault_gen_buildrs = true\nEOF\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eGo inside the workspace path\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003ecd hello_world\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eThe cargo lockfile consist of the exact information for each dependency which is used in the rust project\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003ecargo generate-lockfile\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eThe command for generating the Bazel Build files for external crates\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003ecargo raze\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eCommand for building and running the application.\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003ebazel run :hello_world\n\u003c/code\u003e\u003c/pre\u003e",
      "date_published": "2020-10-21T00:00:00Z"
      ,
      "date_modified": "2020-10-21T00:00:00Z"
      
      ,
      "tags": ["buildsystems","bazel"]
      
      
    }
    
    ,
    {
      "id": "https://anders.dev/posts/1-git-rebase-when-you-understand-why/",
      "url": "https://anders.dev/posts/1-git-rebase-when-you-understand-why/",
      "title": "Git rebase when you understand why",
      "content_html": "\u003cp\u003eI find often that people have hard time to understand Git, they often get stuck in between the local repository and the remote repository where the local is detached and suddenly they end up in a merge conflict.\u003c/p\u003e\n\u003cp\u003eThe conceptual idea of what Git is, is most of the time the main issue, and what shall be stored in Git. You cannot always blame the users when organizations force non-experienced developers to use a version-control system to store various things, without a thought of what shall be stored in Git.\u003c/p\u003e\n\u003cp\u003eIn organizations there are a mixture of people in which does not always have a background in software development, they will more or less use Git as it was a network file system with some extra steps where you put things in to share with your peers.\u003c/p\u003e\n\u003cp\u003eWhat experienced developers do really bad is explaining Git with Git terms which will only make a lot more confusing situation. The moment you trying to explain Git you will start pouring out words like, clone, commit, stage, branch, merge, merge conflict, resolve, push, pull, rebase.\u003c/p\u003e\n\u003cp\u003eWhen it is just the conceptual idea of how Git sees the world as a tree with snapshots which pointing to a parent snapshot, and how you can as a user change these links between the\nsnapshots, then you can also explain why some commands need to be executed.\u003c/p\u003e\n\u003cp\u003e!\n\n\n\n\n\n\n\n\n\n\n\n\u003cfigure class=\"\"\u003e\n\n    \u003cdiv\u003e\n        \u003cimg loading=\"lazy\" alt=\"Image Description\" src=\"/images/xlcd1597.png\" \u003e\n    \u003c/div\u003e\n\n    \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003cp\u003eOtherwise it will end up in as \u003ca href=\"https://xkcd.com/1597/\"\u003eXKCD #1597\u003c/a\u003e explains which you can read above. So if you try to explain Git for some one please make sure you know whats happening with the graph tree, which Git is based on; DAG (Directed Acyclic Graph) which is in simple words a graph without loops, If you follow the relationships from one node you will never end up in the same one you started with. In Git every node in the graph is a commit, a snapshot of the code you working with.\u003c/p\u003e\n\u003cp\u003eThe snapshots can be stored on your computer or on other computers, how you choose to transfer the state of your DAG is up to you, one way is to format patches with git format-patch give it you your friend and and then use git am to apply it, or you can send it by e-mail with git send-mail you can find a good tutorial of git send-mail \u003ca href=\"https://git-send-email.io/\"\u003ehere\u003c/a\u003e. Most common way is to setup a \u003ca href=\"https://git-scm.com/book/en/v2/Git-Basics-Working-with-Remotes\"\u003eremote\u003c/a\u003e with git remote add URL and use the commands push and pull.\u003c/p\u003e\n\u003cp\u003eThe way it is designed the only commit you will have to care about is the latest, because it will always point to a parent commit, and the parent commit will point to it\u0026rsquo;s parent until the \u0026ldquo;initial commit\u0026rdquo;, so then you have the full history.\u003c/p\u003e\n\u003cp\u003eA commit can have many children which means it is branched. You can change the parent of a commit with the command rebase, this is useful if your local commit is behind the remote tree which is common if you have team mates which is faster than you to write and commit code to the repository. Simple solution is the command bellow:\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003egit pull origin --rebase\u003c/code\u003e\u003c/p\u003e\n\u003cp\u003eThat\u0026rsquo;s how you most of the time can avoid merging every time there is a new commit on the remote. What git is doing it will apply your changes as new commits on top of the latest from the remote origin. This means that you can also delete commits your are not proud of, by adding \u003ccode\u003egit pull origin --rebase=i\u003c/code\u003e and you have options for each commit. You can also use rebase within branches \u003ccode\u003egit rebase a_branch_name\u003c/code\u003e\u003c/p\u003e\n\u003cp\u003eWant to play with rebase follow \u003ca href=\"http://git-rebase.io/\"\u003ethis tutorial\u003c/a\u003e\u003c/p\u003e\n",
      "date_published": "2019-07-08T00:00:00Z"
      ,
      "date_modified": "2019-07-08T00:00:00Z"
      
      ,
      "tags": ["source control","git"]
      
      
    }
    
    ,
    {
      "id": "https://anders.dev/posts/0-initial-post/",
      "url": "https://anders.dev/posts/0-initial-post/",
      "title": "Initial post",
      "content_html": "\u003cp\u003e…\u003c/p\u003e\n",
      "date_published": "2019-06-27T00:00:00Z"
      ,
      "date_modified": "2019-06-27T00:00:00Z"
      
      ,
      "tags": ["init","git"]
      
      
    }
    
  ]
}
