<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Dhruv's DevOps & Engineering Notes]]></title><description><![CDATA[Notes on DevOps and web engineering fundamentals.]]></description><link>https://blog.dhruvbhartia.com</link><generator>RSS for Node</generator><lastBuildDate>Wed, 08 Apr 2026 13:12:31 GMT</lastBuildDate><atom:link href="https://blog.dhruvbhartia.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[I used to think Docker + systemd was enough]]></title><description><![CDATA[Around late 2019 / early 2020, I was working with setups where applications were running directly on VMs.
Each team had their own set of VMs, environments were split, CIDR ranges were being managed se]]></description><link>https://blog.dhruvbhartia.com/i-used-to-think-docker-systemd-was-enough</link><guid isPermaLink="true">https://blog.dhruvbhartia.com/i-used-to-think-docker-systemd-was-enough</guid><category><![CDATA[Kubernetes]]></category><category><![CDATA[Docker]]></category><category><![CDATA[systemd]]></category><category><![CDATA[Devops]]></category><category><![CDATA[cloud native]]></category><category><![CDATA[containers]]></category><category><![CDATA[distributed systems]]></category><category><![CDATA[cka]]></category><category><![CDATA[ckad]]></category><category><![CDATA[engineering-thinking]]></category><dc:creator><![CDATA[Dhruv Bhartia]]></dc:creator><pubDate>Wed, 25 Mar 2026 23:12:54 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/62d3d651bc2c7a1dc67274f7/fbb904fa-500f-4407-bb35-99eb310cd03f.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Around late 2019 / early 2020, I was working with setups where applications were running directly on VMs.</p>
<p>Each team had their own set of VMs, environments were split, CIDR ranges were being managed separately. Deployments were done using scripts/playbooks, which felt like mini package managers in their own way - it was quite a lot.</p>
<p>At that time, I remember having very basic questions:</p>
<p>why so many VMs?<br />why can't we just run multiple apps on the same machine using different ports?</p>
<p>I didn't really have a clear answer back then. It just felt like "this is how it's done".</p>
<p>Around the same time, I had also started exploring Kubernetes.</p>
<p>So there were two things happening in parallel:</p>
<ul>
<li>seeing apps run on VMs in this structured but slightly heavy setup</li>
<li>and learning Kubernetes, without fully understanding where it actually fits</li>
</ul>
<p>I didn't connect these two at that point.</p>
<hr />
<p>Recently in 2026, while preparing for CKA/CKAD, I found myself thinking about that phase again.</p>
<p>Back when I had just started exploring Kubernetes, I used to hear explanations like:</p>
<blockquote>
<p>"we can't use just Docker, we need Kubernetes as it makes the system reliable"</p>
</blockquote>
<p>At that time, I interpreted it very literally.</p>
<p>Containers can go down.<br />Kubernetes makes sure they come back up.</p>
<p>And somewhere in that, a very practical doubt came up:</p>
<p>if I can package an app in a container, and use something like systemd to restart it when it crashes.. isn't that enough?</p>
<p>So it would be like:</p>
<ul>
<li>container handles packaging</li>
<li>systemd handles restarts</li>
</ul>
<p>so what exactly is Kubernetes adding here?</p>
<p>I didn't push that thought very far.</p>
<p>I didn't have enough context, and over time it just faded.</p>
<blockquote>
<p>Experiment: Here is a github link with steps if anyone is interested: <a href="https://github.com/dhruvbhartia07/devops-lab/tree/main/docker-systemd-reliability">lab - docker-systemd-reliability</a></p>
</blockquote>
<hr />
<p>But recently, when I came back to that old thought, I tried to reason through it again.</p>
<p>Q. What if I need more than one instance?</p>
<p>-&gt; Okay.. I can probably run multiple containers.</p>
<p>Q. What if they need to run on different machines?</p>
<p>-&gt; Hmm.. maybe we need a proxy at each VM for that app, but the exact approach was unclear.</p>
<p>Q. What if one of those machines goes down?</p>
<p>-&gt; Now it starts to resemble the old setup, where we can't do much without manual intervention.</p>
<hr />
<p>These questions made me realize:</p>
<p>Earlier, I was thinking about how to run this app properly. My view was limited to Docker and systemd, which were right in front of me. I was just seeing it as an app and a server.</p>
<p>The setup itself isn't failing. It works at an individual level, but it doesn't really answer these new questions - the ones that go beyond a single machine.</p>
<hr />
<p>And that's where Kubernetes started to make more sense - not as a tool or usage pattern, but in terms of the problem it is actually solving.</p>
<p>It is handling the part I wasn't even looking at earlier. For the questions above, it kind of fills that missing gap.</p>
<p>I have been using Kubernetes for some time now, learning and adapting it in my daily work:</p>
<p>I knew how to:</p>
<ul>
<li>deploy things</li>
<li>debug issues</li>
<li>check logs</li>
<li>fix problems</li>
</ul>
<p>And interestingly, those steps haven't really changed even now. What has changed is the depth and design that I see behind the same actions.</p>
<p>And on top of that, the idea of "run something and keep it alive on the machine" still exists - kubelet.</p>
<p>Kubelet is not exactly systemd + Docker and does a lot more, but a part of its responsibility still feels similar: making sure whatever is supposed to run is actually running on the node.</p>
<hr />
<p>What has changed is how I see what's happening underneath.</p>
<p>Earlier, <code>kubectl</code> felt like a command.</p>
<p>Now it feels more like:</p>
<blockquote>
<p>I'm making an API call to a system</p>
</blockquote>
<ul>
<li>auth details are stored in a context (kubeconfig)</li>
<li>there's a control plane</li>
<li>components talking to each other</li>
<li>state being stored and reconciled</li>
<li>decisions being made about where things should run</li>
</ul>
<p>It all feels more real now, instead of just a tool or command line. The architecture and extensibility make more sense beyond just YAML.</p>
<hr />
<p>It reminds me of how web development is taught.</p>
<p>At first, a browser is just:</p>
<blockquote>
<p>something that loads a webpage</p>
</blockquote>
<p>Later you realize:</p>
<ul>
<li>there's a rendering engine</li>
<li>networking layer</li>
<li>JS engine</li>
<li>parsing, reflow, painting</li>
</ul>
<p>Same browser.<br />Different understanding.</p>
<p>Feels like I've unlocked a deeper understanding of Kubernetes in a similar way.</p>
<hr />
<p>And maybe that's why that old Docker + systemd thought came back.</p>
<p>Not because it was wrong.</p>
<p>But because now I can finally see where it fits and where it stops.</p>
]]></content:encoded></item><item><title><![CDATA[Understanding Network Devices: How the Internet Reaches Your Device]]></title><description><![CDATA[We all use the internet today.
The most common way is via Wi-Fi or mobile data, with Wi-Fi being the most prominent.Ever wondered how your device actually gets that Spotify song, YouTube video, or even shows you this particular blog?
It often feels l...]]></description><link>https://blog.dhruvbhartia.com/understanding-network-devices-how-the-internet-reaches-your-device</link><guid isPermaLink="true">https://blog.dhruvbhartia.com/understanding-network-devices-how-the-internet-reaches-your-device</guid><category><![CDATA[#Network Fundamentals]]></category><category><![CDATA[networking]]></category><category><![CDATA[computer networks]]></category><category><![CDATA[router]]></category><category><![CDATA[SWITCH]]></category><category><![CDATA[firewall]]></category><category><![CDATA[Load Balancer]]></category><category><![CDATA[Backend Engineering]]></category><category><![CDATA[Devops]]></category><category><![CDATA[System Design]]></category><dc:creator><![CDATA[Dhruv Bhartia]]></dc:creator><pubDate>Fri, 30 Jan 2026 18:30:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1769852391731/1a56f71a-09ac-414b-8b57-6e5a5c109839.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>We all use the internet today.</p>
<p>The most common way is via <strong>Wi-Fi or mobile data</strong>, with Wi-Fi being the most prominent.<br />Ever wondered how your device actually gets that Spotify song, YouTube video, or even shows you this particular blog?</p>
<p>It often feels like we are in a direct connection with Spotify or YouTube from our system - but that’s not the case.</p>
<p>There are <strong>multiple layers and multiple devices</strong> involved before a request from your device reaches a server and comes back with a response.</p>
<p>It’s also not that we weren’t connected to the world before the internet. We already had means like <strong>telephones and cable TV</strong>.<br />The internet is just another medium - one that expanded the horizon of what kind of data can be shared over an existing connection to the world.</p>
<p>Let’s break down the key devices that make this entire journey possible.</p>
<hr />
<h2 id="heading-modem-translating-languages-between-worlds">Modem - Translating Languages Between Worlds</h2>
<p>In the earlier days of the internet, computers were connected using <strong>telephone lines</strong>:</p>
<pre><code class="lang-plaintext">Telephone Line → Modem → Ethernet Cable → Computer
</code></pre>
<p>We already had telephone connections with companies that were well connected across regions and countries.<br />The only issue was the <strong>language of communication</strong>.</p>
<ul>
<li><p>Telephone lines understood <strong>analog signals</strong></p>
</li>
<li><p>Computers spoke in <strong>digital signals</strong></p>
</li>
</ul>
<p>Telephones didn’t transmit our voice as-is.<br />The microphone converted sound into <strong>analog signals</strong>, sent them over the wire, and the receiver converted them back into sound.</p>
<p>Computers needed something similar - a way to convert their digital data into a form that telephone wires could understand.</p>
<p>This is where the <strong>modem</strong> came into existence.</p>
<p>A <strong>Modem (Modulator–Demodulator)</strong>:</p>
<ul>
<li><p>Converts <strong>digital signals → analog signals</strong></p>
</li>
<li><p>Converts <strong>analog signals → digital signals</strong></p>
</li>
</ul>
<p>This translation allowed computers to communicate using existing telephone infrastructure.</p>
<hr />
<h2 id="heading-router-making-sure-traffic-reaches-the-right-device">Router – Making Sure Traffic Reaches the Right Device</h2>
<p>As time passed, the number of devices increased and <strong>Wi-Fi came into existence</strong>.</p>
<p>Now a single household might have:</p>
<ul>
<li><p>Phones</p>
</li>
<li><p>Laptops</p>
</li>
<li><p>TVs</p>
</li>
<li><p>Tablets</p>
</li>
</ul>
<p>We can’t give each device its own internet connection like mobile phones do with SIM cards.</p>
<p>So the question became:</p>
<blockquote>
<p>How do we connect multiple devices using a single internet connection?</p>
</blockquote>
<p>If a single device is requesting data, it’s easy.<br />But with multiple devices, we need a way to <strong>identify who requested what</strong>.</p>
<p>Imagine:</p>
<ul>
<li><p>You are watching a football match</p>
</li>
<li><p>Someone else in your home is watching cricket</p>
</li>
<li><p>Suddenly you start getting the cricket stream</p>
</li>
</ul>
<p>That’s exactly what a <strong>router prevents</strong>.</p>
<p>A router:</p>
<ul>
<li><p>Keeps track of devices</p>
</li>
<li><p>Ensures responses go back to the <strong>same device that requested them</strong></p>
</li>
</ul>
<p>This routing logic isn’t limited to homes.<br />Routers exist <strong>at all levels of the internet</strong>, connecting one logical network to another.</p>
<p>We’ll revisit this idea again later.</p>
<hr />
<h2 id="heading-router-vs-modem-do-routers-replace-modems">Router vs Modem – Do Routers Replace Modems?</h2>
<p>It often feels like routers have replaced modems.</p>
<p>We commonly say:</p>
<blockquote>
<p>“I have a fibre Wi-Fi router at home”</p>
</blockquote>
<p>That statement is <em>partially true</em>.</p>
<p>If we recall what a modem actually does - <strong>signal translation</strong> - we’ll realize that routers never took over that responsibility.</p>
<ul>
<li><p>A router manages and routes traffic (like a traffic policeman)</p>
</li>
<li><p>A modem translates signals so they can travel over physical media</p>
</li>
</ul>
<p>What changed is <strong>integration</strong>.</p>
<p>Today:</p>
<ul>
<li><p>Signal translation happens using <strong>light signals over fibre</strong></p>
</li>
<li><p>This role is handled by something called an <strong>ONT</strong></p>
</li>
<li><p>The modem functionality is <strong>hidden inside the same device</strong></p>
</li>
</ul>
<p>The idea remains the same - there is still a translator.</p>
<p>Analogy:</p>
<ul>
<li><p>Earlier: a human translator</p>
</li>
<li><p>Now: Google Translate</p>
</li>
</ul>
<p>Both do the same job; the implementation evolved.</p>
<p>So:</p>
<ul>
<li><p><strong>Modem and router both exist</strong></p>
</li>
<li><p>They just live inside the same physical device in most homes today</p>
</li>
</ul>
<hr />
<h2 id="heading-switch-and-hub-local-network-communication">Switch and Hub - Local Network Communication</h2>
<p>So far, we’ve talked about <strong>connecting to the internet</strong>.</p>
<p>But sometimes we only need <strong>local communication</strong>, within a limited area like:</p>
<ul>
<li><p>An office</p>
</li>
<li><p>A data center</p>
</li>
<li><p>A home network</p>
</li>
</ul>
<p>For this, we use <strong>switches and hubs</strong>.</p>
<p>Routers <em>can</em> do this, but they are <strong>overkill</strong>.</p>
<p>A simple analogy:</p>
<ul>
<li><p>Finding an item directly in a box</p>
</li>
<li><p>Versus opening a box, finding another box, and then finding the item</p>
</li>
</ul>
<p>Switches are <strong>Layer 2 (L2)</strong> devices<br />Routers are <strong>Layer 3 (L3)</strong> devices</p>
<p>More layers = more processing.</p>
<h3 id="heading-hub">Hub</h3>
<p>A hub is like a <strong>railway station announcement</strong>.</p>
<ul>
<li><p>Any message sent is broadcast to <strong>all ports</strong></p>
</li>
<li><p>Every connected device receives it</p>
</li>
<li><p>Even if the message is meant for just one device</p>
</li>
</ul>
<h3 id="heading-switch">Switch</h3>
<p>A switch is a <strong>smart hub</strong>.</p>
<ul>
<li><p>It knows which devices are connected to which ports</p>
</li>
<li><p>Sends data <strong>only to the intended recipient</strong></p>
</li>
</ul>
<p>Analogy:</p>
<ul>
<li><p>Hub → General announcement at a railway station</p>
</li>
<li><p>Switch → Airport announcements made for a specific gate</p>
</li>
</ul>
<p>This makes switches faster and more efficient for local networks.</p>
<hr />
<h2 id="heading-firewall-where-security-lives">Firewall – Where Security Lives</h2>
<p>Until now, we assumed:</p>
<ul>
<li><p>We send data</p>
</li>
<li><p>Others receive it willingly</p>
</li>
</ul>
<p>But what if:</p>
<ul>
<li><p>Someone accesses data you never intended to share?</p>
</li>
<li><p>Someone sends commands to your device from anywhere in the world?</p>
</li>
</ul>
<p>These are real problems.</p>
<p>Devices often respond to commands <strong>by default</strong> once they receive them.</p>
<p>That’s why we add <strong>security layers</strong>, such as:</p>
<ul>
<li><p>Firewall</p>
</li>
<li><p>IDS / IPS</p>
</li>
<li><p>IAM</p>
</li>
<li><p>WAF</p>
</li>
<li><p>Antivirus</p>
</li>
<li><p>SIEM</p>
</li>
</ul>
<p>A <strong>Firewall</strong> is one of these mechanisms.</p>
<p>Firewalls can operate at:</p>
<ul>
<li><p>Layer 3</p>
</li>
<li><p>Layer 4</p>
</li>
<li><p>Layer 7</p>
</li>
<li><p>Or combinations of these</p>
</li>
</ul>
<p>Analogy:</p>
<ul>
<li><p>Some guards check badges</p>
</li>
<li><p>Some check bags</p>
</li>
<li><p>Some even listen to conversations</p>
</li>
</ul>
<p>In general, when we say <em>firewall</em>, we usually mean <strong>L3 / L4 firewalls</strong>.</p>
<p>They:</p>
<ul>
<li><p>Check source and destination IP</p>
</li>
<li><p>Check ports</p>
</li>
<li><p>Check protocol type</p>
</li>
<li><p>Track connections</p>
</li>
</ul>
<p>This is why blindly disabling firewalls or allowing all traffic - just because a tutorial said so - is dangerous.</p>
<p>Your app might not be malicious, but opening everything can allow <strong>malicious actors</strong> into your system.</p>
<p>Security helps keep your application <strong>available and running</strong>.<br />But availability isn’t only about security - which brings us to the next component.</p>
<hr />
<h2 id="heading-load-balancer-handling-scale-and-availability">Load Balancer – Handling Scale and Availability</h2>
<p>Think about:</p>
<ul>
<li><p>A small local shop</p>
</li>
<li><p>A large supermarket</p>
</li>
</ul>
<p>Now imagine two groups of 1000 people:</p>
<ul>
<li><p>Group A goes to the supermarket</p>
</li>
<li><p>Group B goes to the local shop</p>
</li>
</ul>
<p>Who gets served faster?</p>
<p>Most likely, <strong>Group A</strong>.</p>
<p>Why?</p>
<p>Supermarkets have:</p>
<ul>
<li><p>Larger area</p>
</li>
<li><p>Well-defined sections</p>
</li>
<li><p>Multiple entry and exit points</p>
</li>
<li><p>Multiple billing counters</p>
</li>
</ul>
<p>Local shops:</p>
<ul>
<li><p>Small space</p>
</li>
<li><p>Single entry/exit</p>
</li>
<li><p>One billing counter</p>
</li>
</ul>
<p>Local shops aren’t badly designed - they just aren’t meant to serve <strong>large traffic at the same time</strong>.</p>
<p>Now imagine:</p>
<ul>
<li><p>A supermarket with multiple billing counters</p>
</li>
<li><p>But everyone lines up at a single counter</p>
</li>
</ul>
<p>That defeats the purpose.</p>
<p>To fix this, we need someone directing people to different counters.</p>
<p>That person is the <strong>Load Balancer</strong>.</p>
<p>A load balancer:</p>
<ul>
<li><p>Sits in front of backend servers</p>
</li>
<li><p>Distributes incoming traffic across multiple instances</p>
</li>
</ul>
<p>Scaling backend servers alone isn’t enough.<br />Users don’t know:</p>
<ul>
<li><p>Which instance exists</p>
</li>
<li><p>Which instance is free</p>
</li>
<li><p>Which instance is overloaded</p>
</li>
</ul>
<p>So users always hit the <strong>load balancer</strong>, and it decides where the request should go.</p>
<p>Load balancers use different algorithms depending on needs and intelligence required.</p>
<hr />
<h2 id="heading-how-everything-works-together-end-to-end-flow">How Everything Works Together – End-to-End Flow</h2>
<p>Let’s trace how your request reached this blog.</p>
<p>Assume you are reading this from your office computer.</p>
<h3 id="heading-flow">Flow</h3>
<ol>
<li><p>Open the browser</p>
</li>
<li><p>Enter the URL</p>
</li>
<li><p>Request goes via Ethernet connection to the <strong>switch</strong></p>
</li>
<li><p>Switch forwards it to the <strong>router</strong> (where modem translates the signal)</p>
</li>
<li><p>Router sends the request to the <strong>ISP</strong></p>
</li>
<li><p>Request passes through multiple routers</p>
</li>
<li><p>Reaches the ISP router of the hosting server</p>
</li>
<li><p>Router routes and translates the signal back to digital</p>
</li>
<li><p>Traffic goes to the <strong>switch</strong></p>
</li>
<li><p>Switch sends it to the <strong>server</strong></p>
</li>
<li><p>Server hosts a <strong>load balancer</strong></p>
</li>
<li><p>Load balancer routes request to the appropriate backend server</p>
</li>
</ol>
<p>The internal LAN and switches may be physical or virtual, and may not map 1:1 - but the <strong>logic remains the same</strong>.</p>
<hr />
<h2 id="heading-sum-up">Sum Up</h2>
<p>All these devices:</p>
<ul>
<li><p>Modem</p>
</li>
<li><p>Router</p>
</li>
<li><p>Switch</p>
</li>
<li><p>Hub</p>
</li>
<li><p>Firewall</p>
</li>
<li><p>Load Balancer</p>
</li>
</ul>
<p>Are interesting in their own way and deserve deeper dives.</p>
<p>This write-up was meant to <strong>touch upon their responsibilities</strong>, how they differ, and how they work together to deliver something as simple as this blog to your screen.</p>
]]></content:encoded></item><item><title><![CDATA[How DNS Resolution Works (Using dig to See What’s Actually Happening)]]></title><description><![CDATA[In the last article, we discussed various network devices and the basics of how a request travels across the internet.

If you’re interested, you can read it here:
Understanding Network Devices: How the Internet Reaches Your Device

In this article, ...]]></description><link>https://blog.dhruvbhartia.com/how-dns-resolution-works-using-dig-to-see-whats-actually-happening</link><guid isPermaLink="true">https://blog.dhruvbhartia.com/how-dns-resolution-works-using-dig-to-see-whats-actually-happening</guid><category><![CDATA[dns]]></category><category><![CDATA[networking]]></category><category><![CDATA[computer networks]]></category><category><![CDATA[System Design]]></category><category><![CDATA[Devops]]></category><category><![CDATA[dig]]></category><dc:creator><![CDATA[Dhruv Bhartia]]></dc:creator><pubDate>Fri, 30 Jan 2026 18:30:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1769860168905/7125c9cf-93d5-49b1-89aa-0e1afbc0533a.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In the last article, we discussed various network devices and the basics of how a request travels across the internet.</p>
<blockquote>
<p>If you’re interested, you can read it here:</p>
<p><a target="_blank" href="https://dhruvbhartia07.hashnode.dev/understanding-network-devices-how-the-internet-reaches-your-device"><strong>Understanding Network Devices: How the Internet Reaches Your Device</strong></a></p>
</blockquote>
<p>In this article, we’ll focus on <strong>DNS</strong> - what it is, why it exists, and how name resolution actually happens under the hood.</p>
<hr />
<h2 id="heading-what-is-dns-and-why-name-resolution-exists">What Is DNS and Why Name Resolution Exists</h2>
<p>DNS stands for <strong>Domain Name System</strong>.</p>
<p>As the name suggests, it is a system that holds information about <strong>domain names</strong>.</p>
<p>Domain names are simply the website names we type into applications - like <code>google.com</code>, <code>youtube.com</code>, etc.</p>
<p>In computer networks, <strong>all communication happens using IP addresses</strong>.<br />IP addresses are used on the internet to identify devices in the network. They do not have human-friendly names.</p>
<p>Just like our houses or flats have an address, IP addresses serve the same purpose for computers and network devices (Layer 3 and above).</p>
<p>At first glance, DNS feels similar to a <strong>phonebook</strong> - and that analogy works - but in a more accurate sense, it behaves closer to a <strong>distributed database</strong>.</p>
<p>Phones understand <strong>numbers</strong>, not names.<br />When you select a person’s name in your phone, the phone application automatically translates that name into a phone number.</p>
<p>DNS does the same thing for the internet.</p>
<p>You type a website name, and DNS returns the corresponding IP address to your application (browser, <code>curl</code>, Postman, etc.), which is then used to make the actual network request.</p>
<p>DNS is a <strong>massive system</strong>.</p>
<p>Think about an IPL final or a big e-commerce sale. A lot of preparation goes into handling that traffic. But every single user visiting those platforms must first resolve the domain name.</p>
<p>Even then, the <strong>comparative load on DNS is surprisingly low</strong>.<br />That’s the beauty of how this system is designed.</p>
<p>Most of the complexity is hidden from us by browsers and tools - but we <em>do</em> have ways to see what’s going on underneath.</p>
<hr />
<h2 id="heading-introducing-dig">Introducing <code>dig</code></h2>
<p><code>dig</code> is a tool used to <strong>interact directly with DNS</strong> and inspect its responses.</p>
<p>It’s a <strong>CLI tool</strong>.</p>
<p>Here’s what happens when we run:</p>
<pre><code class="lang-plaintext">dig google.com
</code></pre>
<pre><code class="lang-plaintext">;; QUESTION SECTION:
;google.com.                    IN      A

;; ANSWER SECTION:
google.com.             183     IN      A       142.251.221.142
</code></pre>
<p>This tells us that <code>google.com</code> has an <strong>A record</strong> pointing to the IP <code>142.251.221.142</code>.</p>
<p>That is a public IP for Google.</p>
<p>Try this yourself:</p>
<ol>
<li><p>Run <code>dig google.com</code></p>
</li>
<li><p>Copy the IP from the output</p>
</li>
<li><p>Paste it directly into your browser</p>
</li>
</ol>
<p>Observe what happens.</p>
<hr />
<h2 id="heading-dns-is-not-a-simple-database-lookup">DNS Is Not a Simple Database Lookup</h2>
<p>At a surface level, DNS might look like a simple database query:</p>
<blockquote>
<p>“Give me the IP for this domain.”</p>
</blockquote>
<p>But that’s not the reality.</p>
<p>Imagine storing <strong>hundreds of billions of records</strong> and querying them globally for <strong>billions of devices</strong>, all in near-real time.</p>
<p>That approach wouldn’t scale.</p>
<h3 id="heading-the-distributed-structure-of-dns">The Distributed Structure of DNS</h3>
<p>DNS works because it is <strong>distributed</strong>.</p>
<p>From top to bottom, the hierarchy looks like this:</p>
<pre><code class="lang-plaintext">Root Servers → TLD Servers → Authoritative Name Servers
</code></pre>
<p>Each layer has a very specific responsibility.</p>
<hr />
<h2 id="heading-root-name-servers">Root Name Servers</h2>
<p>Root servers are the <strong>top-most servers</strong> in the DNS hierarchy.</p>
<p>They do <strong>not</strong> store IP addresses for websites.</p>
<p>Instead, they store information about <strong>TLD (Top Level Domain) servers</strong>.</p>
<p>Based on the domain you’re trying to resolve, the root server directs you to the appropriate TLD server.</p>
<p>There are <strong>13 root server identities</strong> globally.</p>
<p>We can see them using:</p>
<pre><code class="lang-plaintext">dig . NS
</code></pre>
<p>This returns entries like:</p>
<pre><code class="lang-plaintext">a.root-servers.net.
b.root-servers.net.
...
m.root-servers.net.
</code></pre>
<p>These are the starting points for DNS resolution.</p>
<hr />
<h2 id="heading-tld-name-servers-com-in-dev-etc">TLD Name Servers (<code>.com</code>, <code>.in</code>, <code>.dev</code>, etc.)</h2>
<p>TLD servers store information about <strong>authoritative name servers</strong>.</p>
<p>Examples of TLDs:</p>
<ul>
<li><p><code>.com</code></p>
</li>
<li><p><code>.in</code></p>
</li>
<li><p><code>.dev</code></p>
</li>
<li><p><code>.ai</code></p>
</li>
</ul>
<p>To inspect <code>.com</code> TLD servers, we can run:</p>
<pre><code class="lang-plaintext">dig com NS
</code></pre>
<p>This returns servers such as:</p>
<pre><code class="lang-plaintext">a.gtld-servers.net.
b.gtld-servers.net.
...
m.gtld-servers.net.
</code></pre>
<p>At this layer, DNS still does <strong>not</strong> return IP addresses for websites.</p>
<p>Instead, it tells us <strong>where to find the authoritative servers</strong> for a given domain.</p>
<hr />
<h2 id="heading-authoritative-name-servers">Authoritative Name Servers</h2>
<p>Authoritative name servers are the servers that <strong>actually store the DNS records</strong> for a domain.</p>
<p>This includes:</p>
<ul>
<li><p>A records</p>
</li>
<li><p>AAAA records</p>
</li>
<li><p>(other record types not discussed here)</p>
</li>
</ul>
<blockquote>
<p>To know more about record types, can check article: <a target="_blank" href="https://dhruvbhartia07.hashnode.dev/how-does-a-browser-know-where-a-website-lives"><strong>How Does a Browser Know Where a Website Lives</strong></a></p>
</blockquote>
<p>For <code>google.com</code>, we can inspect them using:</p>
<pre><code class="lang-plaintext">dig google.com NS
</code></pre>
<p>This returns:</p>
<pre><code class="lang-plaintext">ns1.google.com.
ns2.google.com.
ns3.google.com.
ns4.google.com.
</code></pre>
<p>These are the servers that finally know the IP addresses for <code>google.com</code>.</p>
<p>Querying one of these servers gives us the IP we need.</p>
<hr />
<h2 id="heading-the-full-dns-resolution-flow-googlecom">The Full DNS Resolution Flow (<code>google.com</code>)</h2>
<p>If we assume <strong>no caching</strong>, DNS resolution for <code>google.com</code> follows this path:</p>
<pre><code class="lang-plaintext">Root Server → .com TLD Server → google.com Authoritative Server → IP
</code></pre>
<p>This can be visualized using:</p>
<pre><code class="lang-plaintext">dig google.com +trace
</code></pre>
<p>The output clearly shows:</p>
<ol>
<li><p>Root servers responding first</p>
</li>
<li><p><code>.com</code> TLD servers responding next</p>
</li>
<li><p>Google’s authoritative servers responding last with the A record</p>
</li>
</ol>
<p>This trace represents the <strong>entire DNS resolution chain</strong>.</p>
<hr />
<h2 id="heading-the-role-of-the-recursive-resolver">The Role of the Recursive Resolver</h2>
<p>The client (browser or application) does <strong>not</strong> perform all these steps itself.</p>
<p>There is another component in between called the <strong>recursive resolver</strong>.</p>
<p>Flow looks like this:</p>
<pre><code class="lang-plaintext">Browser / App → Recursive Resolver → DNS Hierarchy → Resolver → App
</code></pre>
<p>The application sends a DNS query to the recursive resolver.</p>
<p>The resolver:</p>
<ul>
<li><p>Talks to root servers</p>
</li>
<li><p>Talks to TLD servers</p>
</li>
<li><p>Talks to authoritative servers</p>
</li>
<li><p>Collects the final answer</p>
</li>
<li><p>Returns the IP to the application</p>
</li>
</ul>
<hr />
<h2 id="heading-caching-in-dns">Caching in DNS</h2>
<p>Caching is one of the most important reasons DNS performs so efficiently.</p>
<p>Caching happens at multiple levels:</p>
<ul>
<li><p>Browser</p>
</li>
<li><p>Operating System</p>
</li>
<li><p>Recursive Resolver</p>
</li>
</ul>
<p>Resolvers are heavily relied upon, so caching at this layer has a <strong>huge impact</strong> on performance.</p>
<p>Operating systems also have their own DNS configurations, which are checked before external resolution.<br />This is rarely used in day-to-day browsing but is extremely useful for <strong>personal testing and overrides</strong>.</p>
<blockquote>
<p><strong>Note:</strong> The command outputs mentioned are trimmed to highlight main part of the response. The actual response for the commands discussed will have much more details.</p>
</blockquote>
]]></content:encoded></item><item><title><![CDATA[How Does a Browser Know Where a Website Lives?]]></title><description><![CDATA[When you type a website name like example.com into your browser, the browser somehow figures out which server on the internet actually hosts that website.
But how?
This is where DNS comes into play.

What is DNS?
DNS (Domain Name System) is like a ph...]]></description><link>https://blog.dhruvbhartia.com/how-does-a-browser-know-where-a-website-lives</link><guid isPermaLink="true">https://blog.dhruvbhartia.com/how-does-a-browser-know-where-a-website-lives</guid><category><![CDATA[InternetFundamentals]]></category><category><![CDATA[dns]]></category><category><![CDATA[dns-records]]></category><category><![CDATA[networkingbasics]]></category><category><![CDATA[Devops]]></category><category><![CDATA[web infrastructure]]></category><dc:creator><![CDATA[Dhruv Bhartia]]></dc:creator><pubDate>Fri, 30 Jan 2026 18:30:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1769864769138/9a41b3d8-efdc-4231-b547-7c1f5b44d3b0.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When you type a website name like <code>example.com</code> into your browser, the browser somehow figures out <strong>which server on the internet</strong> actually hosts that website.</p>
<p>But how?</p>
<p>This is where <strong>DNS</strong> comes into play.</p>
<hr />
<h2 id="heading-what-is-dns">What is DNS?</h2>
<p>DNS (Domain Name System) is like a <strong>phonebook for the internet</strong>.</p>
<ul>
<li><p>Humans remember names like <code>google.com</code></p>
</li>
<li><p>Computers communicate using IP addresses like <code>142.250.183.14</code></p>
</li>
</ul>
<p>DNS helps <strong>resolve domain names to their corresponding IP addresses</strong>, so browsers know where to send requests.</p>
<p>DNS is <strong>not a single system</strong> replying with an IP address.<br />There are <strong>recursive calls made across multiple servers</strong> to finally find the correct IP.</p>
<blockquote>
<p>If you’re interested in seeing this entire flow in action, you can check out this article:</p>
<p><a target="_blank" href="https://dhruvbhartia07.hashnode.dev/how-dns-resolution-works-using-dig-to-see-whats-actually-happening"><strong>How DNS Resolution Works</strong></a></p>
</blockquote>
<hr />
<h2 id="heading-why-dns-records-are-needed">Why DNS Records Are Needed</h2>
<p>Now here’s an important question:</p>
<blockquote>
<p>How does the recursive resolver know whether it has found the <strong>actual website IP</strong> or just the <strong>next server it should ask</strong>?</p>
</blockquote>
<p>This is exactly why <strong>DNS record types</strong> exist.</p>
<p>Each DNS record type tells the resolver <strong>what the response means</strong> and <strong>what to do next</strong>.</p>
<hr />
<h2 id="heading-ns-record-who-is-responsible-for-this-domain">NS Record - Who Is Responsible for This Domain?</h2>
<p>An <strong>NS (Name Server) record</strong> tells the resolver <strong>where to look next</strong>.</p>
<ul>
<li><p>NS records point the resolver toward the <strong>authoritative name server</strong></p>
</li>
<li><p>They do <strong>not</strong> return the website IP</p>
</li>
<li><p>They tell the resolver:<br />  → “You need to ask <em>this server</em> for more information about the domain”</p>
</li>
</ul>
<hr />
<h2 id="heading-a-and-aaaa-records-the-actual-address">A and AAAA Records - The Actual Address</h2>
<p>Once the resolver finds these records, the search <strong>stops</strong>.</p>
<ul>
<li><p><strong>A Record</strong> → IPv4 address of the website</p>
</li>
<li><p><strong>AAAA Record</strong> → IPv6 address of the website</p>
</li>
</ul>
<p>These records contain the <strong>actual IP address</strong> of the domain.</p>
<p>When the resolver sees an A or AAAA record:</p>
<ul>
<li><p>It knows it has reached the destination</p>
</li>
<li><p>It returns the IP address back to the browser</p>
</li>
</ul>
<hr />
<h2 id="heading-cname-record-one-name-pointing-to-another">CNAME Record - One Name Pointing to Another</h2>
<p>A <strong>CNAME (Canonical Name)</strong> record is used to create <strong>alias names</strong>.</p>
<p>A common example:</p>
<ul>
<li><p>You host your website on Vercel</p>
</li>
<li><p>Vercel gives you a subdomain</p>
</li>
<li><p>You <strong>don’t control the public IP</strong></p>
</li>
</ul>
<p>So instead of pointing to an IP:</p>
<ul>
<li><p>Your domain uses a CNAME record</p>
</li>
<li><p>It points to Vercel’s domain</p>
</li>
</ul>
<p>What happens internally?</p>
<ul>
<li><p>The resolver sees the CNAME record</p>
</li>
<li><p>It starts a <strong>new lookup</strong> for the target domain</p>
</li>
<li><p>That lookup eventually resolves to an A or AAAA record</p>
</li>
</ul>
<hr />
<h2 id="heading-mx-record-how-emails-find-the-right-server">MX Record - How Emails Find the Right Server</h2>
<p>Email delivery works differently from web traffic.</p>
<p>That’s why <strong>MX (Mail Exchange)</strong> records exist.</p>
<ul>
<li><p>MX records specify <strong>which server should receive emails</strong></p>
</li>
<li><p>They help distinguish between:</p>
<ul>
<li><p>Web servers</p>
</li>
<li><p>Mail servers</p>
</li>
</ul>
</li>
</ul>
<p>If MX records don’t exist:</p>
<ul>
<li><p>A/AAAA records <em>act as fallback</em></p>
</li>
<li><p>But then the web server must also handle mail logic =&gt; Web Server + SMTP server</p>
</li>
</ul>
<p>To keep things simple and clean:</p>
<ul>
<li><p>MX records clearly define <strong>mail routing</strong></p>
</li>
<li><p>Web servers stay focused on serving websites</p>
</li>
</ul>
<hr />
<h2 id="heading-txt-record-extra-information-amp-verification">TXT Record - Extra Information &amp; Verification</h2>
<p>TXT records are <strong>not part of normal website routing</strong>.</p>
<p>They store <strong>extra information</strong>, mostly for verification purposes.</p>
<p>Common use case:</p>
<ul>
<li><p>SSL certificate issuance</p>
</li>
<li><p>Domain ownership verification</p>
</li>
</ul>
<p>Flow:</p>
<ul>
<li><p>Certificate Authority (CA) asks for proof of domain ownership</p>
</li>
<li><p>You add specific content to a TXT record</p>
</li>
<li><p>CA checks the TXT record</p>
</li>
<li><p>Certificate is issued if verification passes</p>
</li>
</ul>
<p>At a high level:</p>
<blockquote>
<p><strong>TXT records are to DNS what meta tags are to HTML.</strong></p>
</blockquote>
<hr />
<h2 id="heading-how-all-dns-records-work-together-end-to-end-example">How All DNS Records Work Together (End-to-End Example)</h2>
<p>Let’s put everything together.</p>
<p>Assume:</p>
<ul>
<li><p>You request a website</p>
</li>
<li><p>There is <strong>no cache</strong></p>
</li>
</ul>
<p>Step-by-step flow:</p>
<ol>
<li><p>Resolver asks the <strong>root name server</strong></p>
</li>
<li><p>Root replies with an <strong>NS record for the TLD</strong></p>
</li>
<li><p>Resolver queries the <strong>TLD server</strong></p>
</li>
<li><p>TLD replies with an <strong>NS record for the authoritative name server</strong></p>
</li>
<li><p>Resolver queries the <strong>authoritative name server</strong></p>
</li>
<li><p>Authoritative server replies with a <strong>CNAME record</strong> mapped to Vercel</p>
</li>
<li><p>The resolver performs a fresh lookup for the target domain, using cache where possible.</p>
</li>
<li><p>Resolver queries Vercel’s authoritative name server</p>
</li>
<li><p>Gets an <strong>A record</strong></p>
</li>
<li><p>Resolver returns the IP to the browser</p>
</li>
</ol>
<p>At this point, the browser finally knows <strong>where the website lives</strong>.</p>
]]></content:encoded></item><item><title><![CDATA[Getting Started with cURL]]></title><description><![CDATA[As a developer, whatever we code eventually gets deployed on a server.A server is nothing but a program that runs somewhere and serves our application to users.
Users usually interact with this server through a browser. The browser sends requests to ...]]></description><link>https://blog.dhruvbhartia.com/getting-started-with-curl</link><guid isPermaLink="true">https://blog.dhruvbhartia.com/getting-started-with-curl</guid><category><![CDATA[curl]]></category><category><![CDATA[http]]></category><category><![CDATA[api]]></category><category><![CDATA[Backend Development]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[Devops]]></category><category><![CDATA[API TESTING]]></category><category><![CDATA[cli]]></category><category><![CDATA[developers]]></category><category><![CDATA[General Programming]]></category><dc:creator><![CDATA[Dhruv Bhartia]]></dc:creator><pubDate>Fri, 30 Jan 2026 18:30:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1769875030549/81e80f83-fe96-4ff0-b79d-9294de5a1a53.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>As a developer, whatever we code eventually gets deployed on a <strong>server</strong>.<br />A server is nothing but a program that runs somewhere and serves our application to users.</p>
<p>Users usually interact with this server through a <strong>browser</strong>. The browser sends requests to the server and shows the response in a user-friendly way.</p>
<p>But as developers, we often want to test backend changes <strong>without a UI</strong>. Testing APIs or backend logic only through a browser is either impossible or very inconvenient.</p>
<p>This is where <strong>cURL</strong> comes in.</p>
<hr />
<h2 id="heading-what-is-curl">What is cURL?</h2>
<p>cURL is a <strong>command-line tool</strong> that allows us to make requests to a server.</p>
<p>In simple terms:</p>
<blockquote>
<p>cURL lets you send messages to a server directly from the terminal.</p>
</blockquote>
<p>It is very useful for developers because:</p>
<ul>
<li><p>It helps in <strong>testing backend APIs</strong></p>
</li>
<li><p>It helps in <strong>troubleshooting server issues</strong></p>
</li>
<li><p>It allows testing functionality <strong>independent of the UI</strong></p>
</li>
</ul>
<p>cURL supports multiple protocols, but in this article we will focus only on <strong>HTTP / HTTPS</strong>.</p>
<p>Even though it might look complex or scary because it’s a CLI tool, it is actually <strong>quite simple to use</strong>.</p>
<hr />
<h2 id="heading-making-your-first-request-using-curl">Making Your First Request Using cURL</h2>
<p>Let’s start with the most basic example:<br />Fetching a webpage from a locally running <strong>nginx server</strong>.</p>
<pre><code class="lang-plaintext">root@db997926b412:/# curl localhost
&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;title&gt;Welcome to nginx!&lt;/title&gt;
&lt;style&gt;
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;h1&gt;Welcome to nginx!&lt;/h1&gt;
&lt;p&gt;If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.&lt;/p&gt;

&lt;p&gt;For online documentation and support please refer to
&lt;a href="http://nginx.org/"&gt;nginx.org&lt;/a&gt;.&lt;br/&gt;
Commercial support is available at
&lt;a href="http://nginx.com/"&gt;nginx.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Thank you for using nginx.&lt;/em&gt;&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre>
<p>Here, cURL fetched the <strong>raw HTML</strong> from the server.</p>
<p>If we open the same URL in a browser, we see a nicely rendered page.<br />The content is the same - the difference is that the <strong>browser knows how to render HTML</strong>, while cURL just prints it as text.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769874794525/aeefab1a-a545-4b87-80e5-10a6063d4cf3.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769874826093/24c2ed24-84c6-4721-bf34-ce99311fa123.png" alt class="image--center mx-auto" /></p>
<hr />
<h2 id="heading-understanding-the-response-headers-and-body">Understanding the Response (Headers and Body)</h2>
<p>To see more details about what’s happening behind the scenes, we can ask cURL to show a <strong>verbose response</strong>.</p>
<pre><code class="lang-plaintext">curl -v localhost
</code></pre>
<pre><code class="lang-plaintext">*   Trying 127.0.0.1:80...
* Connected to localhost (127.0.0.1) port 80 (#0)
&gt; GET / HTTP/1.1
&gt; Host: localhost
&gt; User-Agent: curl/7.88.1
&gt; Accept: */*
&gt;
&lt; HTTP/1.1 200 OK
&lt; Server: nginx/1.27.5
&lt; Date: Sat, 31 Jan 2026 14:55:07 GMT
&lt; Content-Type: text/html
&lt; Content-Length: 615
&lt; Last-Modified: Wed, 16 Apr 2025 12:01:11 GMT
&lt; Connection: keep-alive
&lt; ETag: "67ff9c07-267"
&lt; Accept-Ranges: bytes
&lt;
&lt;!DOCTYPE html&gt;
...
</code></pre>
<p>From this output we can clearly see:</p>
<ul>
<li><p>The <strong>request</strong> being sent (<code>GET /</code>)</p>
</li>
<li><p>The <strong>response status</strong> (<code>200 OK</code>)</p>
</li>
<li><p>The <strong>headers</strong> sent by the server</p>
</li>
<li><p>The <strong>response body</strong> (HTML content)</p>
</li>
</ul>
<hr />
<h2 id="heading-what-happens-when-a-page-doesnt-exist">What Happens When a Page Doesn’t Exist?</h2>
<p>If we try to access a path that doesn’t exist, the server responds with an error.</p>
<pre><code class="lang-plaintext">curl -v localhost/path
</code></pre>
<pre><code class="lang-plaintext">&lt; HTTP/1.1 404 Not Found
&lt; Server: nginx/1.27.5
...
</code></pre>
<p>This shows a <strong>404 error</strong>, meaning the requested resource was not found.</p>
<p>All the requests we made so far were <strong>GET requests</strong>, which we can also confirm from the request headers.</p>
<hr />
<h2 id="heading-using-curl-to-talk-to-apis">Using cURL to Talk to APIs</h2>
<p>cURL is not limited to fetching web pages.<br />It is commonly used to test <strong>APIs</strong>.</p>
<p>Below is an example of using cURL to test a <strong>POST API</strong> for user registration.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769874885541/51faa147-e59b-416f-b91f-79c1027cb4cf.png" alt class="image--center mx-auto" /></p>
<p>The response shows a <strong>200 status code</strong>, which means the request was successful.</p>
<p>Next, we try logging in using the newly created user.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769874904900/7963b2e7-e24c-4918-a5f7-3516f7f1d14e.png" alt class="image--center mx-auto" /></p>
<p>The login also works successfully.</p>
<p>Now let’s try passing <strong>invalid credentials</strong>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769874914188/3cb5346b-314d-4820-b680-85d903480ae7.png" alt class="image--center mx-auto" /></p>
<p>This time, the API responds with an error, which confirms that we are properly testing different scenarios.</p>
<p>Using cURL, we are able to test APIs <strong>directly from the terminal</strong>, without needing any UI.</p>
<hr />
<h2 id="heading-basic-curl-flags-used">Basic cURL Flags Used</h2>
<p>In the API examples above, we used a few common cURL flags. Let’s understand them:</p>
<ul>
<li><p><code>--url</code><br />  Tells cURL the URL to which the request should be sent.</p>
</li>
<li><p><code>--request</code><br />  Specifies the HTTP method to use (for example, POST).</p>
</li>
<li><p><code>--header</code><br />  Used to pass headers along with the request.<br />  Multiple headers can be passed by using this flag multiple times.</p>
</li>
<li><p><code>--data</code><br />  Used to send the request body or payload expected by the API.</p>
</li>
</ul>
<p>There are many more flags and ways to use cURL, but this article focuses only on the <strong>basics</strong> needed to get started.</p>
]]></content:encoded></item><item><title><![CDATA[Why Version Control Exists: The Pendrive Story Every Developer Has Lived]]></title><description><![CDATA[General Mindset: Asking Why Before Using Any Tool
Before jumping into any new tool or technology, I like to pause and ask a few basic questions:

Why do I need this tool?

Why does this exist?

What problem does it actually solve?

Can I work without...]]></description><link>https://blog.dhruvbhartia.com/why-version-control-exists-the-pendrive-story-every-developer-has-lived</link><guid isPermaLink="true">https://blog.dhruvbhartia.com/why-version-control-exists-the-pendrive-story-every-developer-has-lived</guid><category><![CDATA[#SourceControl]]></category><category><![CDATA[vcs]]></category><category><![CDATA[version control]]></category><category><![CDATA[version control systems]]></category><category><![CDATA[software development]]></category><category><![CDATA[Git]]></category><category><![CDATA[#learninginpublic]]></category><category><![CDATA[Developer Mindset]]></category><category><![CDATA[ #TechLearning]]></category><category><![CDATA[General Programming]]></category><dc:creator><![CDATA[Dhruv Bhartia]]></dc:creator><pubDate>Fri, 16 Jan 2026 18:30:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1768661898397/a2a10ca8-9844-49f0-b665-4336a93a4760.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-general-mindset-asking-why-before-using-any-tool">General Mindset: Asking <em>Why</em> Before Using Any Tool</h2>
<p>Before jumping into any new tool or technology, I like to pause and ask a few basic questions:</p>
<ul>
<li><p>Why do I need this tool?</p>
</li>
<li><p>Why does this exist?</p>
</li>
<li><p>What problem does it actually solve?</p>
</li>
<li><p>Can I work without it?</p>
</li>
</ul>
<p>This article is written with the same mindset.</p>
<p>It is <strong>not</strong> an explanation of Git or how Git works internally.<br />Instead, it is an attempt to understand <strong>why version control systems exist in the first place</strong>, and what problems they were designed to solve.</p>
<hr />
<h2 id="heading-life-before-version-control-systems">Life Before Version Control Systems</h2>
<p>Before version control systems became mainstream, developers still built software, collaborated in teams, and shipped projects. But the way collaboration happened was very different.</p>
<p>Code was commonly shared using:</p>
<ul>
<li><p>Pendrives</p>
</li>
<li><p>Emails with ZIP attachments</p>
</li>
<li><p>Shared folders</p>
</li>
<li><p>Files and directories named like:</p>
<ul>
<li><p><code>final</code></p>
</li>
<li><p><code>final_v2</code></p>
</li>
<li><p><code>latest_final</code></p>
</li>
<li><p><code>final_latest_really</code></p>
</li>
</ul>
</li>
</ul>
<p>At a small scale, this <em>seems</em> manageable.<br />But as soon as more than one person starts working in parallel, things begin to break in subtle ways.</p>
<p>To understand this better, let’s look at a simple story.</p>
<hr />
<h2 id="heading-the-pendrive-story-three-friends-one-project">The Pendrive Story: Three Friends, One Project</h2>
<h3 id="heading-the-setup">The Setup</h3>
<p>Three friends - <strong>Alice, Bob, and Charlie</strong> - are in college and decide to build a personal profile website together.<br />They do not know about any version control system.</p>
<p>The application has three components:</p>
<ul>
<li><p>Navbar</p>
</li>
<li><p>Profile section</p>
</li>
<li><p>Blogs section</p>
</li>
</ul>
<p>They divide the work as follows:</p>
<ul>
<li><p>Alice works on the <strong>profile</strong></p>
</li>
<li><p>Bob works on the <strong>blogs page</strong></p>
</li>
<li><p>Charlie takes the <strong>navbar and index page</strong></p>
</li>
</ul>
<p>Charlie finishes early. He copies the code to a pendrive and passes it to Alice.<br />Alice copies it to her local system and then passes the pendrive to Bob.</p>
<p>At this point, Alice and Bob are working independently on their assigned features.</p>
<hr />
<h3 id="heading-where-things-start-breaking">Where Things Start Breaking</h3>
<p>While Alice and Bob are working, Charlie becomes free and decides to improve the navbar styling.<br />He asks Bob for the pendrive.</p>
<p>At the same time:</p>
<ul>
<li><p>Bob finishes his blogs page and adds it to the pendrive</p>
</li>
<li><p>Charlie copies his updated navbar to the pendrive</p>
</li>
</ul>
<p>Curious to see how things look together, Charlie runs the code with the navbar and blogs page.<br />He notices some bugs and misalignments in the blogs page and does a quick fix.</p>
<p>Meanwhile, Bob also finds a few issues in the blogs page and fixes them on his system.</p>
<p>Bob asks for the pendrive back.<br />Charlie passes it to him, along with a note explaining the changes he made in the blogs page.</p>
<p>Now Bob is stuck.</p>
<p>He can’t simply replace his entire blogs folder anymore.<br />Some issues are already fixed by Charlie, while others conflict with Bob’s own logic.</p>
<p>To deal with this, Bob creates a new folder called <code>_latest</code>, compares both versions, and manually reuses parts of the code.</p>
<hr />
<h3 id="heading-silent-overwrites-and-lost-changes">Silent Overwrites and Lost Changes</h3>
<p>During all this, Alice finishes her work and asks for the pendrive.</p>
<p>Bob passes it to her.<br />Alice copies her profile code to the pendrive.</p>
<p>While reviewing the code, Alice notices a small typo in the index page and fixes it.</p>
<p>Later, Bob completes his remaining fixes and asks for the pendrive again so they can finalize the project.</p>
<p>Alice shares the pendrive.<br />Bob replaces all the files on the pendrive with the code from his <code>_latest</code> folder, assuming Alice’s work would not be impacted.</p>
<p>When all three check the final code, Alice notices something surprising:<br />the typo she fixed in the index page is gone.</p>
<p>After discussion, Bob realizes he unintentionally overwrote Alice’s fix.<br />Alice had forgotten to leave a note about the index page change, and Bob had no way of knowing it existed.</p>
<p>The fix was silently lost.</p>
<hr />
<h2 id="heading-what-this-story-shows-us">What This Story Shows Us</h2>
<p>Even for a <strong>very small project</strong>, collaboration became difficult.</p>
<p>Problems that appeared:</p>
<ul>
<li><p>Code getting overwritten without anyone realizing</p>
</li>
<li><p>Changes getting lost silently</p>
</li>
<li><p>Manual notes becoming a dependency</p>
</li>
<li><p>Folder comparisons like <code>_latest</code> becoming normal</p>
</li>
<li><p>No reliable history of who changed what and when</p>
</li>
</ul>
<p>Everyone tried to be careful.<br />Still, things broke.</p>
<hr />
<h2 id="heading-why-this-completely-fails-at-scale">Why This Completely Fails at Scale</h2>
<p>As teams grow, this approach becomes impossible to sustain.</p>
<p>One option is to enforce strict discipline:</p>
<ul>
<li><p>Always leave notes</p>
</li>
<li><p>Always communicate every change</p>
</li>
<li><p>Be extra careful while copying files</p>
</li>
</ul>
<p>Another option is to treat the pendrive as the only editable source:</p>
<ul>
<li><p>If you have it, you can make changes</p>
</li>
<li><p>If you don’t, you wait</p>
</li>
</ul>
<p>This can be replaced by a server where only one person edits at a time.</p>
<p>While this sounds safe, it comes with heavy constraints:</p>
<ul>
<li><p>No real parallel work</p>
</li>
<li><p>Long waiting times</p>
</li>
<li><p>False sense of safety</p>
</li>
</ul>
<p>Even systems that allow multiple people to edit at the same time show how difficult it is to get things right in a single attempt.</p>
<p>This is where the illusion of <strong>parallelism vs concurrency</strong> becomes clear.</p>
<p>There is a gap - and manual coordination is not enough to fill it.</p>
<hr />
<h2 id="heading-the-idea-that-changes-everything">The Idea That Changes Everything</h2>
<p>Charlie recognizes this gap and comes up with an idea:<br />an automated tracker called <strong>Charlie Code Tracker (CCT)</strong>.</p>
<p>CCT does a few important things:</p>
<ul>
<li><p>Tracks what changed and who made the change</p>
</li>
<li><p>Can be installed on each developer’s local machine</p>
</li>
<li><p>Allows everyone to work freely on their own system</p>
</li>
<li><p>Helps highlight inconsistencies or overlaps during sync</p>
</li>
<li><p>Allows pulling others’ changes and pushing your own</p>
</li>
</ul>
<p>Because changes are tracked automatically, developers no longer need to rely on memory or notes.</p>
<p>This idea removes the restriction of working on a single device and enables safe collaboration.</p>
<hr />
<h2 id="heading-this-is-why-version-control-exists">This Is Why Version Control Exists</h2>
<p>This <strong>CCT idea</strong> represents what a <strong>version control system</strong> is meant to solve.</p>
<p>Version control systems exist to:</p>
<ul>
<li><p>Enable parallel work without overwriting</p>
</li>
<li><p>Maintain a reliable history of changes</p>
</li>
<li><p>Make collaboration safe, traceable, and scalable</p>
</li>
<li><p>Reduce human error instead of relying on discipline alone</p>
</li>
</ul>
<p>Teams may choose to treat a shared server as a coordination point, but the core value lies in <strong>tracking history and changes</strong>, not just storing files.</p>
<hr />
<p>To understand how Git handles tracking and history internally, the next article will focus on:</p>
<blockquote>
<p><strong>Give it a Read:</strong> <a target="_blank" href="https://dhruvbhartia07.hashnode.dev/how-git-works-internally-building-a-mental-model?showSharer=true"><strong>How Git Works Internally: Building a Mental Model</strong></a></p>
</blockquote>
]]></content:encoded></item><item><title><![CDATA[Understanding Git: Why It Exists and How We Use It]]></title><description><![CDATA[What is Git
Git is a type of Version Control System (VCS).It is open source and runs on your local machine.
Before diving into Git, it helps to understand why version control exists in the first place. We discussed the idea of VCS in an earlier artic...]]></description><link>https://blog.dhruvbhartia.com/understanding-git-why-it-exists-and-how-we-use-it</link><guid isPermaLink="true">https://blog.dhruvbhartia.com/understanding-git-why-it-exists-and-how-we-use-it</guid><category><![CDATA[Git]]></category><category><![CDATA[version control]]></category><category><![CDATA[git basics]]></category><category><![CDATA[Git Commands]]></category><category><![CDATA[Developer Tools]]></category><category><![CDATA[software development]]></category><category><![CDATA[Beginner Developers]]></category><dc:creator><![CDATA[Dhruv Bhartia]]></dc:creator><pubDate>Fri, 16 Jan 2026 18:30:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1768663680031/964603bc-8940-4c7c-91a2-18f7f053fab8.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-what-is-git">What is Git</h2>
<p>Git is a type of <strong>Version Control System (VCS)</strong>.<br />It is <strong>open source</strong> and runs on your <strong>local machine</strong>.</p>
<p>Before diving into Git, it helps to understand <strong>why version control exists in the first place</strong>. We discussed the idea of VCS in an earlier article.<br />Give it a read: <a target="_blank" href="https://dhruvbhartia07.hashnode.dev/why-version-control-exists-the-pendrive-story-every-developer-has-lived?showSharer=true"><strong>Why Version Control Exists: The Pendrive Story Every Developer Has Lived</strong></a></p>
<p>To understand Git better, let’s first look at how version control evolved over time.</p>
<hr />
<h3 id="heading-early-ways-of-managing-code-before-git">Early Ways of Managing Code (Before Git)</h3>
<h4 id="heading-method-1-local-versioning">Method 1: Local Versioning</h4>
<p>A very common early approach was to maintain multiple copies of the same project locally:</p>
<pre><code class="lang-plaintext">project_1  
project_2  
project_3  
project_final  
project_final_2
</code></pre>
<p>or sometimes using timestamps.</p>
<p>This approach:</p>
<ul>
<li><p>Quickly becomes messy</p>
</li>
<li><p>Leads to confusion over which version is correct</p>
</li>
<li><p>Allows only <strong>one person</strong> to work comfortably</p>
</li>
<li><p>Lives entirely on a personal device</p>
</li>
</ul>
<p>There is some sense of versioning here, but no real tracking or collaboration.</p>
<hr />
<h4 id="heading-method-2-centralized-version-control-cvcs-eg-svn">Method 2: Centralized Version Control (CVCS - e.g., SVN)</h4>
<p>A better approach was to introduce a <strong>central server</strong>.</p>
<ul>
<li><p>The server stores project files along with their history</p>
</li>
<li><p>Developers fetch a copy, make changes, and push them back</p>
</li>
<li><p>The server manages the code and its history</p>
</li>
</ul>
<p>This solved collaboration issues but introduced new problems:</p>
<ul>
<li><p>You always need connectivity to the server</p>
</li>
<li><p>If the central server fails, the project history is at risk</p>
</li>
</ul>
<hr />
<h4 id="heading-method-3-decentralized-version-control-dvcs">Method 3: Decentralized Version Control (DVCS)</h4>
<p>The centralized approach still had limitations.</p>
<p>A decentralized approach solves this by:</p>
<ul>
<li><p>Keeping the <strong>entire history on every developer’s machine</strong></p>
</li>
<li><p>Allowing work to happen <strong>offline</strong></p>
</li>
<li><p>Enabling sync with any peer, remote, or server at any time</p>
</li>
<li><p>Removing a single point of data loss</p>
</li>
</ul>
<p><strong>Git follows this decentralized approach.</strong></p>
<p>Every developer has:</p>
<ul>
<li><p>The full code</p>
</li>
<li><p>The full history</p>
</li>
<li><p>Full tracking information</p>
</li>
</ul>
<p>Git runs locally, while platforms like <strong>GitHub, GitLab, and Bitbucket</strong> are <strong>hosting services built on top of Git</strong>.</p>
<p>One interesting design choice in Git is that it <strong>does not store file diffs</strong>.<br />Instead, Git stores <strong>snapshots of the repository at a point in time</strong>.<br />Each commit becomes a reference to the state of the entire repository at that moment.</p>
<blockquote>
<p>If you are interested more in this, I have linked an article explaining git internals at the end of this article.</p>
</blockquote>
<hr />
<h2 id="heading-why-git-is-used">Why Git is Used</h2>
<p>Before version control systems existed, managing projects was error-prone and difficult.</p>
<p>When VCS was introduced, it helped - but early implementations came with their own limitations.</p>
<p>The evolution roughly looks like this:</p>
<ul>
<li><p>Projects shared using pendrives, emails, or zip files</p>
</li>
<li><p>The idea of version control introduced</p>
</li>
<li><p>Multiple implementations appeared:</p>
<ul>
<li><p><strong>Local VCS</strong></p>
<ul>
<li><p>Tracking exists</p>
</li>
<li><p>No collaboration</p>
</li>
<li><p>Everything stays on one machine</p>
</li>
</ul>
</li>
<li><p><strong>Centralized VCS</strong></p>
<ul>
<li><p>Easy collaboration</p>
</li>
<li><p>Requires constant server access</p>
</li>
<li><p>Risk if the server goes down</p>
</li>
</ul>
</li>
<li><p><strong>Decentralized VCS (Git)</strong></p>
<ul>
<li><p>Full local history</p>
</li>
<li><p>Offline work</p>
</li>
<li><p>Independent collaboration</p>
</li>
<li><p>No single point of failure</p>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>Git became popular because it <strong>solved the limitations of both local and centralized systems</strong> while keeping collaboration fast and reliable.</p>
<hr />
<h2 id="heading-git-basics-and-core-terminologies">Git Basics and Core Terminologies</h2>
<p>Below are some common Git terms you’ll frequently come across.</p>
<h3 id="heading-repository-repo">Repository (Repo)</h3>
<p>A repository is: <code>Project files + .git directory</code></p>
<p>The <code>.git</code> directory is where Git stores all tracking and history information.</p>
<hr />
<h3 id="heading-working-directory">Working Directory</h3>
<p>The <strong>working directory</strong> is your actual workspace:</p>
<ul>
<li><p>Where you see files</p>
</li>
<li><p>Where you edit files</p>
</li>
<li><p>Where changes are made before being tracked</p>
</li>
</ul>
<hr />
<h3 id="heading-commit">Commit</h3>
<p>A <strong>commit</strong> represents:</p>
<ul>
<li><p>A snapshot of the code at a given time</p>
</li>
<li><p>A unique hash</p>
</li>
<li><p>A commit message</p>
</li>
</ul>
<p>A chain of commits forms a <strong>linked timeline of the project’s history</strong>.</p>
<hr />
<h3 id="heading-staging-area">Staging Area</h3>
<p>The <strong>staging area</strong> is a special cache-like area that sits between: <code>Working Directory → Repository</code></p>
<p>It allows you to:</p>
<ul>
<li><p>Select specific changes</p>
</li>
<li><p>Decide what should be included in the next commit</p>
</li>
</ul>
<hr />
<h3 id="heading-branch">Branch</h3>
<p>A branch is <strong>a pointer to a commit</strong>.</p>
<p>Using branches allows:</p>
<ul>
<li><p>Parallel work</p>
</li>
<li><p>Independent experimentation</p>
</li>
<li><p>Multiple lines of development alongside the original</p>
</li>
</ul>
<hr />
<h3 id="heading-head">HEAD</h3>
<p><code>HEAD</code> is a reference to:</p>
<ul>
<li><p>The current branch</p>
</li>
<li><p>The current commit</p>
</li>
</ul>
<p>In simple terms, it tells Git <strong>where you are right now</strong>.</p>
<hr />
<h3 id="heading-remote">Remote</h3>
<p>A remote is <strong>another copy of the repository</strong>, usually hosted on a server such as GitHub or GitLab.</p>
<hr />
<h2 id="heading-common-git-commands">Common Git Commands</h2>
<p>Below are some commonly used Git commands grouped by purpose.</p>
<hr />
<h3 id="heading-starting-amp-inspecting">Starting &amp; Inspecting</h3>
<p><strong>Initialize a repository</strong></p>
<pre><code class="lang-bash">git init
</code></pre>
<p>Creates a new <code>.git/</code> directory.</p>
<hr />
<p><strong>Check repository status</strong></p>
<pre><code class="lang-bash">git status
</code></pre>
<p>Shows:</p>
<ul>
<li><p>Changed files</p>
</li>
<li><p>Staged files</p>
</li>
<li><p>Untracked files</p>
</li>
</ul>
<hr />
<p><strong>View commit history</strong></p>
<pre><code class="lang-bash">git <span class="hljs-built_in">log</span>
</code></pre>
<hr />
<h3 id="heading-making-changes">Making Changes</h3>
<p><strong>Stage a specific file</strong></p>
<pre><code class="lang-bash">git add &lt;filename&gt;
</code></pre>
<hr />
<p><strong>Stage all changes</strong></p>
<pre><code class="lang-bash">git add .
</code></pre>
<hr />
<p><strong>Create a commit</strong></p>
<pre><code class="lang-bash">git commit -m <span class="hljs-string">"message"</span>
</code></pre>
<p>Creates a snapshot from the staged changes.</p>
<hr />
<h3 id="heading-branching">Branching</h3>
<p><strong>List branches</strong></p>
<pre><code class="lang-bash">git branch
</code></pre>
<hr />
<p><strong>Create a new branch</strong></p>
<pre><code class="lang-bash">git branch &lt;branch-name&gt;
</code></pre>
<hr />
<p><strong>Switch branches</strong></p>
<pre><code class="lang-bash">git checkout &lt;branch-name&gt;
</code></pre>
<hr />
<h3 id="heading-fixing-mistakes">Fixing Mistakes</h3>
<p><strong>Discard local changes for a file</strong></p>
<pre><code class="lang-bash">git restore &lt;filename&gt;
</code></pre>
<hr />
<p><strong>Undo last commit but keep changes staged</strong></p>
<pre><code class="lang-bash">git reset --soft HEAD~1
</code></pre>
<hr />
<p><strong>Undo last commit and discard changes</strong></p>
<pre><code class="lang-bash">git reset --hard HEAD~1
</code></pre>
<hr />
<blockquote>
<p>Below is the article in which we go through practical example to understand git internals, give it a read:</p>
<p><a target="_blank" href="https://dhruvbhartia07.hashnode.dev/how-git-works-internally-building-a-mental-model"><strong>How Git Works Internally: Building a Mental Model</strong></a></p>
</blockquote>
]]></content:encoded></item><item><title><![CDATA[How Git Works Internally: Building a Mental Model]]></title><description><![CDATA[Most Git tutorials focus on commands.This article focuses on what actually happens inside Git when we run those commands.

Before going forward with this article, you can go throgh below for better understanding
Why Version Control Exists: The Pendri...]]></description><link>https://blog.dhruvbhartia.com/how-git-works-internally-building-a-mental-model</link><guid isPermaLink="true">https://blog.dhruvbhartia.com/how-git-works-internally-building-a-mental-model</guid><category><![CDATA[#engineeringmindset]]></category><category><![CDATA[Git]]></category><category><![CDATA[Git-Internals]]></category><category><![CDATA[#howgitworks]]></category><category><![CDATA[version control]]></category><category><![CDATA[Software Engineering]]></category><category><![CDATA[developers]]></category><dc:creator><![CDATA[Dhruv Bhartia]]></dc:creator><pubDate>Fri, 16 Jan 2026 18:30:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1768665950980/36817b7f-8e84-4309-9013-ad487cf1b79a.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Most Git tutorials focus on commands.<br />This article focuses on <strong>what actually happens inside Git</strong> when we run those commands.</p>
<blockquote>
<p>Before going forward with this article, you can go throgh below for better understanding</p>
<p><a target="_blank" href="https://dhruvbhartia07.hashnode.dev/why-version-control-exists-the-pendrive-story-every-developer-has-lived?showSharer=true"><strong>Why Version Control Exists: The Pendrive Story Every Developer Has Lived</strong></a></p>
<p><a target="_blank" href="https://dhruvbhartia07.hashnode.dev/understanding-git-why-it-exists-and-how-we-use-it?showSharer=true"><strong>Understanding Git: Why It Exists and How We Use It</strong></a></p>
</blockquote>
<p>We’ll explore:</p>
<ul>
<li><p>What the <code>.git</code> folder is and why it exists</p>
</li>
<li><p>How Git stores data internally using objects</p>
</li>
<li><p>Why Git commits are called <em>snapshots</em></p>
</li>
<li><p>How Git tracks changes efficiently</p>
</li>
</ul>
<p>All examples below are based on <strong>hands-on experimentation</strong>, not theory.</p>
<hr />
<h2 id="heading-the-git-directory-the-heart-of-git">The <code>.git</code> Directory: The Heart of Git</h2>
<p>When we initialize a Git repository:</p>
<pre><code class="lang-bash">git init
</code></pre>
<p>Git creates a <code>.git/</code> directory.</p>
<pre><code class="lang-bash">/home/app <span class="hljs-comment"># ls -la</span>
drwxr-xr-x    6 root root 4096 Jan 17 12:59 .git
</code></pre>
<h3 id="heading-why-does-git-exist">Why does <code>.git</code> exist?</h3>
<ul>
<li><p><code>.git/</code> stores <strong>all information about version tracking</strong></p>
</li>
<li><p>This includes:</p>
<ul>
<li><p>commit history</p>
</li>
<li><p>branches</p>
</li>
<li><p>file snapshots</p>
</li>
<li><p>metadata</p>
</li>
</ul>
</li>
<li><p>If the <code>.git/</code> directory is lost:</p>
<ul>
<li><p>all Git history and tracking is lost</p>
</li>
<li><p>files remain, but Git has no memory of them</p>
</li>
</ul>
</li>
</ul>
<hr />
<h2 id="heading-from-working-directory-to-commit">From Working Directory to Commit</h2>
<p>Any change you make flows through these stages:</p>
<ol>
<li><p><strong>Working Directory</strong></p>
<ul>
<li>New file or modified file</li>
</ul>
</li>
<li><p><strong>Staging Area</strong></p>
<ul>
<li>Changes selected to be recorded</li>
</ul>
</li>
<li><p><strong>Commit</strong></p>
<ul>
<li>A snapshot of the project is stored permanently</li>
</ul>
</li>
</ol>
<p>At a high level:</p>
<pre><code class="lang-plaintext">Working Directory → Staging Area → Commit
</code></pre>
<p>To really understand Git, we need to <strong>zoom into what a commit actually contains</strong>.</p>
<hr />
<h2 id="heading-a-simple-repository-walkthrough">A Simple Repository Walkthrough</h2>
<h3 id="heading-initialize-a-repo">Initialize a repo</h3>
<pre><code class="lang-bash">mkdir app
<span class="hljs-built_in">cd</span> app
git init
</code></pre>
<p>Create a file:</p>
<pre><code class="lang-bash">touch app.txt
git status
</code></pre>
<p>Git shows the file as <strong>untracked</strong>.</p>
<hr />
<h3 id="heading-first-commit">First Commit</h3>
<pre><code class="lang-bash">git add app.txt
git commit -m <span class="hljs-string">"Create App file"</span>
</code></pre>
<p>This creates the <strong>first commit</strong> (root commit).</p>
<p>Checking history:</p>
<pre><code class="lang-bash">git <span class="hljs-built_in">log</span>
</code></pre>
<p>We now see a <strong>commit chain starting point</strong>.</p>
<hr />
<h2 id="heading-git-commit-history-is-a-chain">Git Commit History Is a Chain</h2>
<p>Each commit:</p>
<ul>
<li><p>Has a unique hash</p>
</li>
<li><p>Stores a reference to its <strong>parent commit</strong></p>
</li>
</ul>
<p>This forms a linked structure:</p>
<pre><code class="lang-plaintext">commit → parent → parent → ...
</code></pre>
<p>To inspect a commit internally:</p>
<pre><code class="lang-bash">git cat-file -p &lt;commit-hash&gt;
</code></pre>
<p>Example output:</p>
<pre><code class="lang-bash">tree bda94d5297b34fc5391112596c3f6b2926891352
parent 37087ac939b14f57c7b223d0903ffb5cb4d1896a
author ...
committer ...

Add Line 2 <span class="hljs-keyword">in</span> app and new Readme file
</code></pre>
<h3 id="heading-what-this-tells-us">What this tells us</h3>
<p>A commit stores:</p>
<ul>
<li><p>a reference to a <strong>tree</strong></p>
</li>
<li><p>a reference to its <strong>parent</strong></p>
</li>
<li><p>author and message</p>
</li>
</ul>
<p>So the commit itself does <strong>not store file contents directly</strong>.</p>
<hr />
<h2 id="heading-tree-objects-representing-folder-structure">Tree Objects: Representing Folder Structure</h2>
<p>Let’s inspect the tree object:</p>
<pre><code class="lang-bash">git cat-file -p &lt;tree-hash&gt;
</code></pre>
<p>Output:</p>
<pre><code class="lang-bash">100644 blob 3485b695ca9834fcdc2bf439f1c12109b8b54634    README.md
100644 blob 40f9bae6a2073fc65d8e2b618b73534a84317ad7    app.txt
</code></pre>
<p>A <strong>tree</strong>:</p>
<ul>
<li><p>represents a directory</p>
</li>
<li><p>maps filenames → blob hashes</p>
</li>
<li><p>can reference other trees (for subdirectories)</p>
</li>
</ul>
<hr />
<h2 id="heading-blob-objects-actual-file-content">Blob Objects: Actual File Content</h2>
<p>Inspecting a blob:</p>
<pre><code class="lang-bash">git cat-file -p &lt;blob-hash&gt;
</code></pre>
<p>Output:</p>
<pre><code class="lang-bash">This is line 1
This is line 2
</code></pre>
<p>A <strong>blob</strong>:</p>
<ul>
<li><p>stores <strong>only file content</strong></p>
</li>
<li><p>has no filename information</p>
</li>
<li><p>same content → same blob hash</p>
</li>
</ul>
<hr />
<h2 id="heading-why-commits-are-snapshots">Why Commits Are Snapshots</h2>
<p>After adding a new line and committing again:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">echo</span> <span class="hljs-string">"This is line 3"</span> &gt;&gt; app.txt
git commit -am <span class="hljs-string">"Add line 3 in app"</span>
</code></pre>
<p>Inspecting the new commit shows:</p>
<ul>
<li><p>a <strong>new tree</strong></p>
</li>
<li><p>a <strong>new blob for</strong> <code>app.txt</code></p>
</li>
<li><p><strong>same blob hash for</strong> <a target="_blank" href="http://README.md"><code>README.md</code></a></p>
</li>
</ul>
<p>This proves:</p>
<ul>
<li><p>Each commit represents a <strong>full snapshot</strong></p>
</li>
<li><p>Unchanged files reuse existing blobs</p>
</li>
<li><p>Git optimizes storage automatically</p>
</li>
</ul>
<blockquote>
<p>Git does not save “changes” - it saves <strong>states</strong>.</p>
</blockquote>
<hr />
<h2 id="heading-exploring-the-git-directory">Exploring the <code>.git</code> Directory</h2>
<p>Listing <code>.git/</code>:</p>
<pre><code class="lang-bash">ls .git/

output:
HEAD
objects
refs
index
logs
...
</code></pre>
<p>For internal understanding, we focus on:</p>
<ul>
<li><p><code>HEAD</code></p>
</li>
<li><p><code>refs</code></p>
</li>
<li><p><code>objects</code></p>
</li>
</ul>
<hr />
<h2 id="heading-head-and-branches">HEAD and Branches</h2>
<pre><code class="lang-bash">cat .git/HEAD

output:
ref: refs/heads/master
</code></pre>
<p><code>HEAD</code> points to:</p>
<ul>
<li><p>a branch</p>
</li>
<li><p>which points to a commit</p>
</li>
</ul>
<p>Inspect branch ref:</p>
<pre><code class="lang-bash">cat .git/refs/heads/master

output:
28c6f9787e22397050b706616d20e1c8cccbdc89
</code></pre>
<p>Creating a new branch:</p>
<pre><code class="lang-bash">git checkout -b feature
</code></pre>
<p>Now:</p>
<pre><code class="lang-bash">refs/heads/
├── master
└── feature
</code></pre>
<p>Both branches initially point to the <strong>same commit</strong>.</p>
<p>This shows:</p>
<blockquote>
<p><strong>A branch is just a file containing a commit hash.</strong></p>
</blockquote>
<hr />
<h2 id="heading-objects-directory-where-git-stores-everything">Objects Directory: Where Git Stores Everything</h2>
<pre><code class="lang-bash">ls .git/objects/

output:
20 28 34 37 40 9f bd e9 f7 info pack
</code></pre>
<p>Each folder:</p>
<ul>
<li><p>is named using the <strong>first two characters</strong> of an object hash</p>
</li>
<li><p>contains files named with the remaining characters</p>
</li>
</ul>
<p>Example:</p>
<pre><code class="lang-bash">ls .git/objects/28/
</code></pre>
<p>This object corresponds to the commit we inspected earlier using <code>git cat-file</code>.</p>
<p>So:</p>
<ul>
<li><p>blobs</p>
</li>
<li><p>trees</p>
</li>
<li><p>commits<br />  all live together in <code>objects/</code></p>
</li>
</ul>
<hr />
<h2 id="heading-how-git-tracks-changes-mental-model">How Git Tracks Changes (Mental Model)</h2>
<p>Putting it all together:</p>
<ul>
<li><p><code>git add</code></p>
<ul>
<li><p>prepares blobs</p>
</li>
<li><p>updates the staging area</p>
</li>
</ul>
</li>
<li><p><code>git commit</code></p>
<ul>
<li><p>creates a tree from staged blobs</p>
</li>
<li><p>creates a commit pointing to that tree</p>
</li>
<li><p>links to the parent commit</p>
</li>
</ul>
</li>
<li><p>Branch refs move forward</p>
</li>
<li><p>Old objects remain immutable</p>
</li>
</ul>
<hr />
<h2 id="heading-hashes-and-integrity">Hashes and Integrity</h2>
<p>Git uses hashes to:</p>
<ul>
<li><p>uniquely identify content</p>
</li>
<li><p>detect corruption</p>
</li>
<li><p>avoid duplicate storage</p>
</li>
</ul>
<p>Same content → same hash<br />Different content → different hash</p>
<hr />
<h2 id="heading-final-takeaway">Final Takeaway</h2>
<p>This exploration shows that Git is:</p>
<ul>
<li><p>not magic</p>
</li>
<li><p>not command-driven</p>
</li>
<li><p>but a <strong>content-addressed snapshot database</strong></p>
</li>
</ul>
<p>Understanding this internal model makes:</p>
<ul>
<li><p>branching intuitive</p>
</li>
<li><p>history manipulation safer</p>
</li>
<li><p>Git errors less scary</p>
</li>
</ul>
]]></content:encoded></item></channel></rss>