<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Lamka Joy</title>
    <description>The latest articles on DEV Community by Lamka Joy (@jlamka).</description>
    <link>https://dev.to/jlamka</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3967812%2F5d51ba8d-8abe-4395-9fce-013404b3b40d.png</url>
      <title>DEV Community: Lamka Joy</title>
      <link>https://dev.to/jlamka</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jlamka"/>
    <language>en</language>
    <item>
      <title>Git Real: From Faking Conflicts to Surviving Real Ones</title>
      <dc:creator>Lamka Joy</dc:creator>
      <pubDate>Mon, 20 Jul 2026 08:44:33 +0000</pubDate>
      <link>https://dev.to/jlamka/git-real-from-faking-conflicts-to-surviving-real-ones-2dm5</link>
      <guid>https://dev.to/jlamka/git-real-from-faking-conflicts-to-surviving-real-ones-2dm5</guid>
      <description>&lt;p&gt;Let’s be honest: learning Git as a beginner can feel like absolute hell.&lt;br&gt;
In the beginning, you’re memorizing commands like magic spells such as git add, git commit -m "fixed stuff", git push, without really understanding what’s happening behind the curtain. You hear developers talk about branches, rebasing, and merge conflicts as if they're everyday occurrences, but until you hit those hurdles yourself, it all feels abstract.&lt;/p&gt;

&lt;p&gt;Recently, while working on projects at my developer program, I went from intentionally trying to break Git just to see what a conflict looked like, to unintentionally manifesting a full-blown merge conflict in my very next project. Here is what that journey taught me about navigating Git, resolving conflicts, and surviving the dangerous lure of the force push.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Weird World of "Ghost" Conflicts&lt;/strong&gt;&lt;br&gt;
During one of our early team assignments, we were specifically instructed to practice handling merge conflicts. A conflict happens when Git cannot automatically reconcile differences between two commits, typically because two people modified the exact same line in the exact same file in contradictory ways.&lt;/p&gt;

&lt;p&gt;I set up my separate branches, made edits on both sides, prepared my mind for chaos, and executed the merge. To my complete surprise, everything merged smoothly without a single warning or conflict marker. It was baffling to say the least.Then now I actually had to go out of my way to force a failure just so I could learn how to solve one. I had to manually edit identical lines across both branches to finally trigger those infamous angle-bracket conflict markers. At the time, it felt like a controlled laboratory experiment, but as every developer quickly learns, real software projects rarely stay inside the lab for long.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Be Careful What You Wish For: Manifesting a Real Conflict&lt;/strong&gt;&lt;br&gt;
Fast forward to my next project. I was working on a web application, feeling confident, and pushing code across different features when suddenly an actual merge conflict halted my build. It felt as though I had manifested the very nightmare I was trying to simulate earlier.&lt;/p&gt;

&lt;p&gt;Unlike my rehearsed test, this was real code that I could not afford to lose. The initial shock quickly dissolved once I realized that a merge conflict is not a system failure, but rather Git asking for human judgment. Instead of making risky assumptions about which code matters more, Git pauses and hands control back to you.&lt;/p&gt;

&lt;p&gt;To resolve a conflict without relying on structured step-by-step checklists, you simply treat the file like any other code review. You open the conflicted file, locate the section flagged by the markers, and evaluate both versions side by side. Once you choose the ground truth—whether that means keeping your local changes, accepting the incoming branch's changes, or manually combining both into a better solution—you erase the leftover conflict markers. Staging the modified file and executing a standard commit seals the resolution, leaving the repository clean and ready for deployment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rebase vs. Merge: Keeping History Clean&lt;/strong&gt;&lt;br&gt;
As branching becomes second nature, developers inevitably encounter git rebase as an alternative to git merge. While standard merges preserve every historic branch intersection by creating a dedicated merge commit, they can leave your commit history looking like a chaotic subway map.&lt;/p&gt;

&lt;p&gt;Rebasing solves this visual clutter by taking your branch's unique commits and replaying them individually on top of another target branch. This process rewrites history to present a clean, linear story of development. However, because rebasing alters existing commit hashes, it introduces a vital rule of thumb: you should never rebase commits that have already been pushed to a shared public repository, as it disrupts the history for everyone else on the team.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Playing with Fire: The Infamous Force Push&lt;/strong&gt;&lt;br&gt;
This historical rewriting brings us to one of the most dangerous commands in a developer's toolkit: git push --force. When you rebase a local branch that was previously pushed upstream, Git will reject a standard push command because your local history no longer aligns with the remote server's records.&lt;/p&gt;

&lt;p&gt;Executing a force push instructs the remote repository to discard its current state and forcibly accept your local history. If a teammate pushed code to that remote branch in the meantime, their hard work gets completely wiped out without warning. To prevent accidental data loss, experienced developers favor using --force-with-lease instead. This safer option acts as an automatic guardrail, refusing to overwrite the remote repository if anyone else has updated it since your last pull.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;br&gt;
Mastering Git commands like checkout, rebase, and reset requires making mistakes and stepping through uncomfortable terminal errors. Yet, once you get the hang of it, Git transforms from an intimidating chore into an indispensable superpower. It provides a safety net that allows you to experiment freely, recover from mistakes, and collaborate seamlessly across teams. The initial learning curve may be steep, but emerging on the other side as a confident developer makes every struggle worth it.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>codenewbie</category>
      <category>git</category>
      <category>learning</category>
    </item>
    <item>
      <title>From Terminal to Container: The Evolution and Dockerization of an ASCII Art Web Application.</title>
      <dc:creator>Lamka Joy</dc:creator>
      <pubDate>Mon, 20 Jul 2026 08:26:38 +0000</pubDate>
      <link>https://dev.to/jlamka/from-terminal-to-container-the-evolution-and-dockerization-of-an-ascii-art-web-application-4dde</link>
      <guid>https://dev.to/jlamka/from-terminal-to-container-the-evolution-and-dockerization-of-an-ascii-art-web-application-4dde</guid>
      <description>&lt;p&gt;Being a software developer just looks like a journey of learning something new everyday. Recently, I embarked on this exact progression with a project called ascii-web art. What began as a simple command-line interface (CLI) application written in Go evolved into an interactive web service, which was ultimately packaged inside a Docker container. Through this process, I gained firsthand experience in web development, containerization, and did research on the foundational principles of container orchestration with Kubernetes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Phase 1: Building in the Terminal&lt;/strong&gt;&lt;br&gt;
The initial iteration of the project was a pure terminal application. The core logic read plain text input from the command line, parsed each character, and mapped it to corresponding ASCII banner characters stored in template files such as standard, shadow, or thinkertoy.&lt;/p&gt;

&lt;p&gt;While building a CLI application was an excellent way to practice core programming logic, algorithms, and file parsing in Go, it had inherent limitations in terms of usability:&lt;/p&gt;

&lt;p&gt;Execution required direct access to a command terminal and the underlying source code environment.&lt;/p&gt;

&lt;p&gt;Formatting and visual output depended heavily on the user's local terminal dimensions and font settings.&lt;/p&gt;

&lt;p&gt;Non-technical users could not easily interact with or benefit from the tool.&lt;/p&gt;

&lt;p&gt;To overcome these barriers and make the program accessible to a wider audience, the next logical step was bringing the application to the web.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Phase 2: Transitioning to the Web&lt;/strong&gt;&lt;br&gt;
Transitioning the project to a web application meant wrapping the core ASCII generation logic inside an HTTP server using Go's standard library.&lt;/p&gt;

&lt;p&gt;Instead of accepting command-line arguments, the application served a web interface containing a clean HTML form. Users could enter their desired text, choose an ASCII font style, and submit the request. The Go backend received the POST request, processed the string through the ASCII generator, and rendered the rendered banner dynamically on the web page.&lt;/p&gt;

&lt;p&gt;While this solved the user-accessibility problem, it introduced a common software engineering challenge: environment dependency, commonly summarized as the "works on my machine" problem. Running the application required anyone pulling the project to have Go installed, correctly configure their local environment, and manage directory dependencies for templates and banner files.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Phase 3: Containerization with Docker&lt;/strong&gt;&lt;br&gt;
To make the application truly portable and self-contained, we containerized it using Docker.&lt;/p&gt;

&lt;p&gt;At its core, Docker wraps application code along with its specific runtime, system libraries, configuration files, and dependencies into a single, standardized unit known as a Docker Image. When executed, this image runs inside an isolated environment called a Docker Container. Because the container carries its own lightweight runtime environment, it guarantees that the application runs identically regardless of the underlying host operating system—whether Linux, macOS, or Windows.&lt;/p&gt;

&lt;p&gt;The Dockerfile Blueprint&lt;br&gt;
To containerize ascii-web art, we authored a Dockerfile at the root of the project to serve as the build recipe:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Phase 4: Beyond Single Containers—Understanding Kubernetes&lt;/strong&gt;&lt;br&gt;
Working with Docker naturally opens the door to broader infrastructure questions: How do you manage, scale, and maintain hundreds of containers in a production environment across multiple server nodes?&lt;/p&gt;

&lt;p&gt;This is where Kubernetes (K8s) comes into play. While Docker excels at packaging and running individual containers on a single host, Kubernetes is a container orchestraPhase 3: Containerization with Dockertion platform designed to automate management at scale. It handles essential operational needs including:&lt;/p&gt;

&lt;p&gt;Autoscaling: Spinning up additional instances of a container during traffic spikes.&lt;/p&gt;

&lt;p&gt;Self-Healing: Automatically restarting or replacing containers that crash or fail health checks.&lt;/p&gt;

&lt;p&gt;Load Balancing: Distributing network traffic across multiple container instances to maintain uptime and performance.&lt;/p&gt;

&lt;p&gt;In essence, Docker provides the container, and Kubernetes provides the system to manage an entire fleet of them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;br&gt;
The journey of building and containerizing ascii-web art highlighted the practical value of modern software architecture patterns. Moving from a CLI utility to a web application made the software accessible to end-users, while wrapping it in a Docker container made it instantly deployable for developers and systems administrators alike. Understanding containerization—along with the foundational concepts of orchestration tools like Kubernetes—provides a strong foundation for building portable, scalable, and resilient cloud-native applications.with Kubernetes.&lt;/p&gt;

</description>
      <category>docker</category>
      <category>go</category>
      <category>showdev</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
