<?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>Forem: Satyajit Roy</title>
    <description>The latest articles on Forem by Satyajit Roy (@deadlock).</description>
    <link>https://forem.com/deadlock</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F889682%2Fb18477f5-0824-4081-9e75-5a7397aa9f0a.png</url>
      <title>Forem: Satyajit Roy</title>
      <link>https://forem.com/deadlock</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/deadlock"/>
    <language>en</language>
    <item>
      <title>[Golang] Garbage Collection in General</title>
      <dc:creator>Satyajit Roy</dc:creator>
      <pubDate>Tue, 13 Jan 2026 04:42:37 +0000</pubDate>
      <link>https://forem.com/deadlock/golang-garbage-collection-in-general-1m1f</link>
      <guid>https://forem.com/deadlock/golang-garbage-collection-in-general-1m1f</guid>
      <description>&lt;p&gt;As we all know the &lt;code&gt;golang&lt;/code&gt; is a &lt;strong&gt;garbage collected&lt;/strong&gt; language like other languages like &lt;code&gt;java&lt;/code&gt;, &lt;code&gt;python&lt;/code&gt; , &lt;code&gt;C#&lt;/code&gt; etc. &lt;strong&gt;&lt;code&gt;Golang&lt;/code&gt;&lt;/strong&gt; is a statically typed &lt;strong&gt;&lt;em&gt;garbage collected language.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What is Garbage Collection and Why it is needed
&lt;/h3&gt;

&lt;p&gt;So many articles has written about this subject. So I am going to keep that small and try to get some deeper insight about the concept.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In SML programs (and in most other programming languages), it is possible to create &lt;strong&gt;garbage&lt;/strong&gt; : allocated space that is no longer usable by the program.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When software is executed on your computer, there are two important memory location parts that it uses: &lt;strong&gt;Stack&lt;/strong&gt; and &lt;strong&gt;Heap&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkesnvv97kjp9ixvcfl08.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkesnvv97kjp9ixvcfl08.jpg" width="800" height="295"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Above code has a &lt;code&gt;RandomBox&lt;/code&gt; &lt;strong&gt;type&lt;/strong&gt; and &lt;code&gt;GenerateRandomBox()&lt;/code&gt; is a &lt;strong&gt;function&lt;/strong&gt; which returns &lt;code&gt;RandomBox&lt;/code&gt; &lt;strong&gt;type&lt;/strong&gt;. The ref has been assigned in &lt;strong&gt;stack&lt;/strong&gt; and struct data is in &lt;strong&gt;heap.&lt;/strong&gt; Golang uses &lt;strong&gt;&lt;a href="https://en.wikipedia.org/wiki/Escape_analysis" rel="noopener noreferrer"&gt;Escape Analysis&lt;/a&gt;&lt;/strong&gt; to to determine that.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft8w8qoedkpmgy4rfbqkf.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft8w8qoedkpmgy4rfbqkf.jpg" width="800" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When the reference goes away, we end up with &lt;strong&gt;Garbage&lt;/strong&gt;. This is how we get &lt;strong&gt;Garbage&lt;/strong&gt;, which requires to be clean up time to time.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;When the program memory footprint reaches a certain threshold, the whole application will be suspended, the &lt;strong&gt;Garbage Collector&lt;/strong&gt; scans all the objects assigned memory space and recycling are no longer used, after the end of this process, the user program can continue, the language also use this strategy implement garbage collection in the early days, but today’s implementation is much complicated&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Garbage collection&lt;/strong&gt; can be initiated manually or automatically depending on the programming language you are using. Every program &lt;code&gt;compiler&lt;/code&gt; or &lt;code&gt;interpreter&lt;/code&gt; uses a specific algorithm to perform &lt;strong&gt;Garbage collection&lt;/strong&gt;. &lt;strong&gt;Garbage collection&lt;/strong&gt; in a &lt;code&gt;compiled&lt;/code&gt; language works the same way as in an &lt;code&gt;interpreted&lt;/code&gt; language.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Golang&lt;/code&gt; use &lt;strong&gt;&lt;a href="https://en.wikipedia.org/wiki/Tracing_garbage_collection" rel="noopener noreferrer"&gt;Tracing garbage&lt;/a&gt;&lt;/strong&gt; collectors even though their code is usually compiled to machine code ahead-of-time. Go uses a &lt;strong&gt;concurrent mark and sweep garbage collector&lt;/strong&gt; algorithm.&lt;/p&gt;

&lt;h3&gt;
  
  
  What happens in Garbage Collection Process
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;Go&lt;/code&gt;’s &lt;strong&gt;garbage collector&lt;/strong&gt; is called &lt;em&gt;&lt;strong&gt;concurrent&lt;/strong&gt;&lt;/em&gt; because it can safely run in parallel with the main program. When compiler decides that this is the time to run &lt;strong&gt;garbage collection&lt;/strong&gt; based on some &lt;em&gt;&lt;strong&gt;condition&lt;/strong&gt;&lt;/em&gt; (discussed below), this is what it follows&lt;/p&gt;

&lt;h4&gt;
  
  
  Mark Setup
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;which means compiler try to stops everything, literally called &lt;strong&gt;stop the world&lt;/strong&gt; step. Nothing gets done in your application at this time.&lt;/li&gt;
&lt;li&gt;First it does is to enable &lt;strong&gt;write barrier&lt;/strong&gt; which mean nothing get written in memory when this barrier is on &lt;em&gt;(Stop all go-routines)&lt;/em&gt;. Compiler has to perform this to make sure that your application is not losing any data.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj9x8g4ffkm6jkoqelqud.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj9x8g4ffkm6jkoqelqud.png" width="800" height="388"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Once the &lt;strong&gt;STW&lt;/strong&gt; is performed and the &lt;strong&gt;write barrier&lt;/strong&gt; is on, collector moves on to next phase.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Marking
&lt;/h4&gt;

&lt;p&gt;In this phase the following happens&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Inspect &lt;strong&gt;&lt;code&gt;stacks&lt;/code&gt;&lt;/strong&gt; to find the root pointer in &lt;strong&gt;&lt;code&gt;heap&lt;/code&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Traverse the &lt;strong&gt;&lt;code&gt;heap&lt;/code&gt;&lt;/strong&gt; and see if they are still in use&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Collector&lt;/strong&gt; also uses &lt;strong&gt;go-routine&lt;/strong&gt; like us and it takes &lt;strong&gt;25%&lt;/strong&gt; of your available &lt;strong&gt;go-routines&lt;/strong&gt; and assign them to itself. Means based on our previous example, 1 thread will be dedicated to &lt;strong&gt;collector.&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Now, if the collect finds out that it might go out of memory while performing this task, because some other &lt;code&gt;go-routine&lt;/code&gt; is allocating more then it can mark. So it will choose that &lt;code&gt;go-routine&lt;/code&gt; and ask it to help with marking. This process is called &lt;strong&gt;Mark Assist&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq814v9oivgp38030ru59.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq814v9oivgp38030ru59.png" width="800" height="236"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Mark Termination
&lt;/h4&gt;

&lt;p&gt;Here &lt;strong&gt;collector&lt;/strong&gt; will again perform the &lt;strong&gt;STW&lt;/strong&gt;, turn the &lt;strong&gt;write barrier off&lt;/strong&gt;, perform some clean-up and calculate the next &lt;strong&gt;Garbage collection&lt;/strong&gt; schedule&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Note:&lt;/strong&gt;&lt;/em&gt; The goal is to keep the &lt;strong&gt;STW&lt;/strong&gt; down or within the &lt;strong&gt;100ms&lt;/strong&gt; on every collection it needs to perform&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;One the &lt;strong&gt;Mark Termination&lt;/strong&gt; process is complete &lt;em&gt;(STW and Write Barrier is Off)&lt;/em&gt;, application start working again with all the &lt;strong&gt;OS Threads&lt;/strong&gt; available.&lt;/p&gt;

&lt;p&gt;This is what happens every time the collection happens, you may ask that yes, it did the marking by identifying the dangling values, however, it didn’t clean up them. That part is called &lt;strong&gt;Sweeping&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Myth Buster&lt;/strong&gt;&lt;/em&gt;: &lt;strong&gt;Sweeping&lt;/strong&gt; is not part of &lt;strong&gt;Garbage Collection&lt;/strong&gt;, it happens &lt;strong&gt;outside&lt;/strong&gt; of collection process.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Sweeping
&lt;/h3&gt;

&lt;p&gt;This is process where we claim the non-marked memory allocations. We need to get them back, thats the whole purpose of &lt;strong&gt;Garbage Collection&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Claiming the unused locations happens when a new allocation happens. So, technically latency for &lt;strong&gt;sweeping&lt;/strong&gt; is not added to &lt;strong&gt;garbage collection.&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqvxb5vrjkztqo0j49kmy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqvxb5vrjkztqo0j49kmy.gif" width="972" height="514"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Garbage Collection Triggers
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The first metric the &lt;strong&gt;garbage collector&lt;/strong&gt; will watch is the growth of the &lt;code&gt;heap&lt;/code&gt;. By default, it will run when the &lt;em&gt;&lt;strong&gt;heap doubles its size&lt;/strong&gt;&lt;/em&gt;. &lt;strong&gt;(&lt;a href="https://github.com/golang/go/blob/master/src/runtime/mgc.go#L529" rel="noopener noreferrer"&gt;code&lt;/a&gt;)&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;The second metric the &lt;strong&gt;garbage collector&lt;/strong&gt; is watching is the delay between two garbage collectors. If it has &lt;em&gt;&lt;strong&gt;not been triggered for more than two minutes&lt;/strong&gt;&lt;/em&gt;, one cycle will be forced. &lt;strong&gt;(&lt;a href="https://github.com/golang/go/blob/master/src/runtime/mgc.go#L560" rel="noopener noreferrer"&gt;code&lt;/a&gt;)&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Application memory can also trigger &lt;strong&gt;garbage collection&lt;/strong&gt; is the &lt;em&gt;&lt;strong&gt;&lt;a href="https://github.com/golang/go/blob/master/src/runtime/malloc.go#L842" rel="noopener noreferrer"&gt;&lt;code&gt;runtime.mallocgc&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt;&lt;/em&gt; function, which at runtime divides objects on the &lt;code&gt;heap&lt;/code&gt; into micro objects, small objects, and large objects by size. The creation of each of these three objects can trigger a new garbage collection cycle.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;&lt;strong&gt;Manually&lt;/strong&gt;&lt;/em&gt; triggering it by calling &lt;strong&gt;&lt;a href="https://github.com/golang/go/blob/master/src/runtime/mgc.go#L412" rel="noopener noreferrer"&gt;&lt;code&gt;gc()&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  GC Collector knobs
&lt;/h3&gt;

&lt;p&gt;Unlike &lt;code&gt;java&lt;/code&gt; it was decided that a &lt;code&gt;golang&lt;/code&gt; developer shouldn’t have to tune their &lt;strong&gt;Garbage collector&lt;/strong&gt; whenever they move to different hardware. So they only provided one tuning config called &lt;em&gt;&lt;strong&gt;&lt;a href="https://pkg.go.dev/runtime/debug#SetGCPercent" rel="noopener noreferrer"&gt;&lt;code&gt;SetGCPercentage&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt;&lt;/em&gt; or &lt;em&gt;&lt;strong&gt;&lt;a href="https://pkg.go.dev/runtime#hdr-Environment_Variables" rel="noopener noreferrer"&gt;&lt;code&gt;GOGC&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt;&lt;/em&gt; environment variable. Default for &lt;strong&gt;&lt;a href="https://pkg.go.dev/runtime#hdr-Environment_Variables" rel="noopener noreferrer"&gt;&lt;code&gt;GOGC&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt; is &lt;em&gt;&lt;strong&gt;100%&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj3gbni6oqe5lukghfb8a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj3gbni6oqe5lukghfb8a.png" width="800" height="380"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  GC Pacer
&lt;/h3&gt;

&lt;p&gt;There is &lt;strong&gt;pacer algorithm&lt;/strong&gt; trying to figure out when to start new &lt;strong&gt;collection&lt;/strong&gt;. As we know that the calculation happens when &lt;strong&gt;Mark Termination&lt;/strong&gt; phase of &lt;strong&gt;Garbage collection&lt;/strong&gt;. The &lt;strong&gt;Pacer&lt;/strong&gt; algorithm tries to calculate this and if it find that it can get more advantage of starting the collection even before the condition applies, it will do that. So take away is that the collection can even start before then the calculated time if &lt;strong&gt;pacer&lt;/strong&gt; think that it can get more benefit.&lt;/p&gt;

&lt;p&gt;Hope this blog was able to provide little more in-depth inside about the &lt;strong&gt;Garbage Collection&lt;/strong&gt; process and how it is implemented in &lt;code&gt;Golang&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Happy Learning!!
&lt;/h2&gt;

</description>
      <category>go</category>
      <category>programming</category>
    </item>
    <item>
      <title>Git Selective Ignore: Because Sometimes You Need to Keep Secrets from Git (But Not From Yourself)</title>
      <dc:creator>Satyajit Roy</dc:creator>
      <pubDate>Tue, 13 Jan 2026 04:05:45 +0000</pubDate>
      <link>https://forem.com/deadlock/git-selective-ignore-because-sometimes-you-need-to-keep-secrets-from-git-but-not-from-yourself-37a7</link>
      <guid>https://forem.com/deadlock/git-selective-ignore-because-sometimes-you-need-to-keep-secrets-from-git-but-not-from-yourself-37a7</guid>
      <description>&lt;h1&gt;
  
  
  Git Selective Ignore: Because Sometimes You Need to Keep Secrets from Git (But Not From Yourself)
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;Or: How I Learned to Stop Worrying and Love Committing Without Fear&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Picture this:&lt;/strong&gt; It's 2 AM, you're deep in the coding zone, your coffee has gone cold (again), and you've just figured out why your API integration wasn't working. You quickly hardcode that API key to test it out—just temporarily, of course. The fix works! You're ecstatic. You commit your changes with a triumphant message: "Fixed the thing that was broken!"&lt;/p&gt;

&lt;p&gt;Fast forward to 9 AM the next day. Your security team is having what can only be described as a "spirited discussion" about API keys appearing in your Git history. Your coffee is cold again, but this time it's because your blood has turned to ice.&lt;/p&gt;

&lt;p&gt;Sound familiar? Welcome to the club. We have t-shirts, but ironically, we can't put the design in our Git repo because it has our logo's secret color codes in it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Git Philosophy: Everything Is Sacred (Even Your Mistakes)
&lt;/h2&gt;

&lt;p&gt;Git operates on a beautiful but sometimes inconvenient principle: &lt;strong&gt;everything matters&lt;/strong&gt;. When Linus Torvalds created &lt;code&gt;Git&lt;/code&gt; in 2005 &lt;em&gt;(in just 10 days, because apparently some people are just built different)&lt;/em&gt;, he designed it around the idea that every character in your codebase tells a story. Git treats files as atomic units—either the whole file is tracked, or it isn't.&lt;/p&gt;

&lt;p&gt;This philosophy has served us well. Git's immutable history and complete file tracking have prevented countless disasters. But it also means that when you accidentally commit &lt;code&gt;API_KEY = "sk_live_definitely_not_my_real_key_12345"&lt;/code&gt;, Git faithfully preserves that mistake for all eternity, like a digital time capsule of your poor judgment.&lt;/p&gt;

&lt;p&gt;The traditional &lt;code&gt;.gitignore&lt;/code&gt; file is fantastic for what it does—ignoring entire files or directories. Need to keep your &lt;code&gt;node_modules&lt;/code&gt; out of the repo? Perfect. Don't want your IDE settings cluttering up the project? Easy. But try telling &lt;code&gt;.gitignore&lt;/code&gt; to ignore just line 42 of &lt;code&gt;config.py&lt;/code&gt; while keeping the rest of the file, and it'll give you the digital equivalent of a blank stare.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enter the Real World: Where Perfect Theory Meets Messy Reality
&lt;/h2&gt;

&lt;p&gt;Here's the thing about development: we live in a world of temporary hacks that become permanent features, debug statements that somehow make it to production, and test configurations that work so well locally that we forget they contain production credentials.&lt;/p&gt;

&lt;h3&gt;
  
  
  Consider these common scenarios:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Debug Block&lt;/strong&gt;: Those &lt;code&gt;console.log&lt;/code&gt; statements that helped you figure out why the async function was returning undefined, but now clutter your clean, professional codebase.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Local Config&lt;/strong&gt;: Database connection strings, API endpoints, and feature flags that need to be different for local development but shouldn't make their way into the shared repository.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Temporary Experiment&lt;/strong&gt;: That experimental algorithm you're testing, complete with hardcoded values and performance logging, sitting right in the middle of your otherwise pristine production code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Security Nightmare&lt;/strong&gt;: API keys, tokens, passwords, and other credentials that somehow always seem to sneak into codebases despite our best intentions.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Traditional Solutions: A Comedy of Errors
&lt;/h2&gt;

&lt;p&gt;Let's look at how we typically handle these situations:&lt;/p&gt;

&lt;h3&gt;
  
  
  Option 1: The Paranoid Approach
&lt;/h3&gt;

&lt;p&gt;You meticulously remove every sensitive line before committing, then carefully add them back after. This works great until you forget to add something back, spend three hours debugging why your app won't start, and realize you removed the line that sets up the database connection.&lt;/p&gt;

&lt;h3&gt;
  
  
  Option 2: The Environment Variable Dance
&lt;/h3&gt;

&lt;p&gt;You move everything to environment variables. This is actually good practice, but now your local setup requires a &lt;code&gt;.env&lt;/code&gt; file with 47 different variables, and new developers need a PhD in configuration management just to run the project locally.&lt;/p&gt;

&lt;h3&gt;
  
  
  Option 3: The Separate Config Files
&lt;/h3&gt;

&lt;p&gt;You keep sensitive configs in separate files and gitignore those files entirely. This works until you need to share the structure of the config with your team, or until someone accidentally deletes the local config file and has no template to recreate it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Option 4: The Git Surgery
&lt;/h3&gt;

&lt;p&gt;You realize you've committed something sensitive and spend the next hour learning about &lt;code&gt;git filter-branch&lt;/code&gt; and &lt;code&gt;BFG Repo-Cleaner&lt;/code&gt;. By the time you're done, you've rewritten half your Git history, broken everyone else's local repos, and you're pretty sure you've violated several laws of physics.&lt;/p&gt;

&lt;h2&gt;
  
  
  Git Selective Ignore: A Surgical Solution
&lt;/h2&gt;

&lt;p&gt;This is where &lt;code&gt;git-selective-ignore&lt;/code&gt; comes in. Think of it as a precision instrument in a world of sledgehammers.&lt;/p&gt;

&lt;p&gt;
  &lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fkodelint%2Fblog-images%2Fmain%2Fcommon%2F01-git-selecting-ignore.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fkodelint%2Fblog-images%2Fmain%2Fcommon%2F01-git-selecting-ignore.png" alt="git-selective-ignore" width="800" height="533"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;Instead of treating files as atomic units, this tool lets you specify exactly which parts of a file should be ignored during commits. It’s like having a conversation with Git:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;span&amp;gt;You&amp;lt;/span&amp;gt;
&amp;lt;span&amp;gt;"Hey Git, commit this file, but ignore lines 13-16, and also any line that contains 'API_KEY', and oh, while you're at it, skip that debug block between the comments."&amp;lt;/span&amp;gt;


&amp;lt;span&amp;gt;Git&amp;lt;/span&amp;gt;
&amp;lt;span&amp;gt;"That's not how I—"&amp;lt;/span&amp;gt;


&amp;lt;span&amp;gt;Tool&amp;lt;/span&amp;gt;
&amp;lt;span&amp;gt;"I got this. &amp;lt;em&amp;gt;Git&amp;lt;/em&amp;gt;, just commit what they want you to commit. Trust me."&amp;lt;/span&amp;gt;


&amp;lt;span&amp;gt;Git&amp;lt;/span&amp;gt;
&amp;lt;span&amp;gt;"...okay, but this feels weird."&amp;lt;/span&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  How It Actually Works (The Magic Behind the Curtain)
&lt;/h2&gt;

&lt;p&gt;The tool operates using Git hooks—specifically &lt;code&gt;pre-commit&lt;/code&gt; and &lt;code&gt;post-commit&lt;/code&gt; hooks. Here's the elegant dance it performs:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Pre-commit&lt;/strong&gt;: Before Git commits your changes, the tool scans your staged files, creates temporary clean versions with the specified content removed, and stages these sanitized versions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Commit&lt;/strong&gt;: Git commits the clean versions to history.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Post-commit&lt;/strong&gt;: The tool restores your original files, so your working directory contains all your local configs, debug statements, and temporary code.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It's like having a butler who tidies up your room before guests arrive, then puts everything back exactly where you left it after they leave.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real-World Example: The API Key Tango
&lt;/h2&gt;

&lt;p&gt;Let's say you have this in your &lt;code&gt;main.rs&lt;/code&gt; and &lt;code&gt;lib.rs&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Starting application..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// DEBUG BLOCK START&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Debug: Application started in debug mode"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// DEBUG BLOCK END&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;API_KEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"sk_live_1234567890abcdef"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Using API key: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;API_KEY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="cm"&gt;/* Temporary lines for testing - remove before prod */&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;temp_feature&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"experimental_feature_xyz"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Testing temporary feature: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;temp_feature&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="cm"&gt;/* End temporary section */&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;SECRET&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Some secret value"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"SECRET configured"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Application completed successfully"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Another Test"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;GITHUB_TOKEN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"github_fake_token_093790841-831-8lncdlwnelkqix12=-1x;xm;m"&lt;/span&gt;

    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{} &amp;lt;- My GitHub Token"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;GITHUB_TOKEN&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;API_KEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;env&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;'API_KEY&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="nn"&gt;env&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;'API_KEY&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"The value of APP_KEY is: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;API_KEY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nd"&gt;eprintln!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Error getting environment variable {}: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;'API_KEY&lt;/span&gt;'&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With traditional &lt;code&gt;Git&lt;/code&gt;, you have two choices:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Commit everything (including secrets) 😬😬😬&lt;/li&gt;
&lt;li&gt;Manually clean it up before every commit 🫩🫩🫩&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;With &lt;code&gt;git-selective-ignore&lt;/code&gt;, you set up your patterns once 🕺🏽 💃🏻:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Ignore any lines containing these sensitive terms&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; git-selective-ignore add all API_KEY &lt;span class="nt"&gt;--pattern-type&lt;/span&gt; line-regex
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; git-selective-ignore add all SECRET &lt;span class="nt"&gt;--pattern-type&lt;/span&gt; line-regex

&lt;span class="c"&gt;# Ignore debug blocks&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; git-selective-ignore add all &lt;span class="s2"&gt;"// DEBUG BLOCK START ||| // DEBUG BLOCK END"&lt;/span&gt; &lt;span class="nt"&gt;--pattern-type&lt;/span&gt; block-start-end

&lt;span class="c"&gt;# Ignore specific line ranges for temporary code&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; git-selective-ignore add src/main.rs 13-16 &lt;span class="nt"&gt;--pattern-type&lt;/span&gt; line-range
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now when you commit, Git's history will only contain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Starting application..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Using API key: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;API_KEY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"SECRET configured"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Application completed successfully"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But your local file remains unchanged, so you can keep working with all your debug statements and test configurations intact.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Approach Works Better
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Compared to Manual Cleanup
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No more forgetting&lt;/strong&gt;: You don't have to remember what to remove and add back&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No broken local environments&lt;/strong&gt;: Your working directory always contains what you need&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consistent team experience&lt;/strong&gt;: Everyone gets the same sanitized commits&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Compared to Environment Variables
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Faster iteration&lt;/strong&gt;: No need to restart processes when changing test values&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Better debugging&lt;/strong&gt;: You can see actual values in your code while developing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Simpler onboarding&lt;/strong&gt;: New developers can run the project with sensible defaults&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Compared to Separate Config Files
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No structural divergence&lt;/strong&gt;: The team sees the shape of your configuration&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No lost configs&lt;/strong&gt;: Your local setup is preserved in your working directory&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Version control benefits&lt;/strong&gt;: You can still track changes to the configuration structure&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Advanced Patterns: Getting Surgical
&lt;/h2&gt;

&lt;p&gt;The tool supports several pattern types for different use cases:&lt;/p&gt;

&lt;h3&gt;
  
  
  Line Regex (for scattered sensitive data)
&lt;/h3&gt;

&lt;p&gt;Perfect for API keys, passwords, or debug statements scattered throughout your codebase:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; git-selective-ignore add all &lt;span class="s2"&gt;"console&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="s2"&gt;log.*debug"&lt;/span&gt; &lt;span class="nt"&gt;--pattern-type&lt;/span&gt; line-regex
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Line Ranges (for temporary code blocks)
&lt;/h3&gt;

&lt;p&gt;When you know exactly which lines contain temporary code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; git-selective-ignore add src/config.py 45-52 &lt;span class="nt"&gt;--pattern-type&lt;/span&gt; line-range
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Block Start/End (for structured temporary sections)
&lt;/h3&gt;

&lt;p&gt;When you use comments to mark temporary code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; git-selective-ignore add all &lt;span class="s2"&gt;"// TODO: REMOVE ||| // END TODO"&lt;/span&gt; &lt;span class="nt"&gt;--pattern-type&lt;/span&gt; block-start-end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Philosophy Shift: From Binary to Granular
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;git-selective-ignore&lt;/code&gt; represents a philosophical shift in how we think about version control. Instead of the binary choice of "track this file or don't," we get granular control over what parts of our development process should be preserved in history.&lt;/p&gt;

&lt;p&gt;This isn't about hiding poor practices—it's about recognizing that the code we need to develop effectively isn't always the same as the code we want to preserve historically. It's the difference between your private workshop (messy, full of tools and work-in-progress) and the finished product you show to the world.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started: Your First Steps into Selective Ignoring
&lt;/h2&gt;

&lt;p&gt;Installation is straightforward. You can use their &lt;a href="https://github.com/kodelint/setup-devbox" rel="noopener noreferrer"&gt;setup-devbox&lt;/a&gt; tool, download from releases, or build from source:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Build from source&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; git clone https://github.com/kodelint/git-selective-ignore.git
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;git-selective-ignore
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; cargo &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--path&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then in any repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Initialize selective ignore&lt;/span&gt;
git-selective-ignore init

&lt;span class="c"&gt;# Install the Git hooks&lt;/span&gt;
git-selective-ignore install-hooks

&lt;span class="c"&gt;# Add your first pattern&lt;/span&gt;
git-selective-ignore add all &lt;span class="s2"&gt;"API_KEY"&lt;/span&gt; &lt;span class="nt"&gt;--pattern-type&lt;/span&gt; line-regex

&lt;span class="c"&gt;# Check what would be ignored&lt;/span&gt;
git-selective-ignore status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The tool stores its configuration in &lt;code&gt;.git/selective-ignore.toml&lt;/code&gt;, so each repository can have its own rules without affecting others.&lt;/p&gt;

&lt;p&gt;You can also see the violations in the code base with &lt;code&gt;status&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; git-selective-ignore status
✓ Configuration is valid.
   ├─ Line Range Pattern &lt;span class="s1"&gt;'13-16'&lt;/span&gt;: 4 line&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; matched
   │  └─ Lines 13-16
   ├─ Regex Pattern &lt;span class="s1"&gt;'API_KEY'&lt;/span&gt;: 1 line&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; matched
   │  └─ Line 10
   ├─ Regex Pattern &lt;span class="s1"&gt;'GITHUB_TOKEN'&lt;/span&gt;: 1 line&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; matched
   │  └─ Line 20
   ├─ Block Pattern &lt;span class="s1"&gt;'// DEBUG BLOCK START ||| // DEBUG BLOCK END'&lt;/span&gt;: 3 line&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; matched
   │  └─ Lines 6-8
   ├─ Regex Pattern &lt;span class="s1"&gt;'SECRET'&lt;/span&gt;: 1 line&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; matched
   │  └─ Line 18
   └─ Summary: 10 line&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; ignored, 17 line&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; remaining &lt;span class="o"&gt;(&lt;/span&gt;of 27 total&lt;span class="o"&gt;)&lt;/span&gt;
   ├─ Regex Pattern &lt;span class="s1"&gt;'GITHUB_TOKEN'&lt;/span&gt;: 1 line&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; matched
   │  └─ Line 7
   └─ Summary: 1 line&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; ignored, 18 line&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; remaining &lt;span class="o"&gt;(&lt;/span&gt;of 19 total&lt;span class="o"&gt;)&lt;/span&gt;
📊 Git Selective Ignore Status Report
&lt;span class="o"&gt;=====================================&lt;/span&gt;
🎯 Specifically Configured Files:
🟡 src/main.rs &lt;span class="o"&gt;(&lt;/span&gt;8 patterns, 10/27 lines ignored, 37.0%&lt;span class="o"&gt;)&lt;/span&gt;

🌐 Files Affected by Global &lt;span class="s1"&gt;'ALL'&lt;/span&gt; Patterns:
🟡 src/lib.rs &lt;span class="o"&gt;(&lt;/span&gt;6 patterns, 1/19 lines ignored, 5.3%&lt;span class="o"&gt;)&lt;/span&gt;

📈 Summary:
  Total files: 2
  Total patterns: 8
  Total ignored lines: 11
  Files with issues: 2

📋 Breakdown:
  Specifically configured files: 1
  Files affected by &lt;span class="s1"&gt;'ALL'&lt;/span&gt; patterns only: 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use &lt;code&gt;list&lt;/code&gt; to see what Ignore Patterns are installed&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; git-selective-ignore list
✓ Configuration is valid.

📁 File: all
  🔍 ID: 78ed02f4-db7c-4921-b565-5e8986f19705 | Type: LineRegex | Pattern: API_KEY
  🔍 ID: 7fb165d1-bab6-4c79-a13b-51f2f29a88e9 | Type: LineRegex | Pattern: APP_KEY
  🔍 ID: 02b17597-bb85-428c-be56-3d0cd4a3c44b | Type: LineRegex | Pattern: GITHUB_TOKEN
  🔍 ID: 76447f06-dd03-4c3b-b27a-b611579e9cb8 | Type: BlockStartEnd | Pattern: // DEBUG BLOCK START &lt;span class="o"&gt;||&lt;/span&gt;| // DEBUG BLOCK END
  🔍 ID: 48f984d1-dd90-4984-99d6-ae6c63c591d6 | Type: LineRegex | Pattern: SECRET
  🔍 ID: b9a54bc2-048d-4fa0-b6ff-dc66aff6e706 | Type: LineRegex | Pattern: password

📁 File: src/main.rs
  🔍 ID: 31ca2ff0-90d8-47ea-90db-413cedf09bcf | Type: LineRange | Pattern: 13-16
  🔍 ID: a941d428-87ed-4378-898d-d5156723dfd0 | Type: BlockStartEnd | Pattern: /&lt;span class="k"&gt;*&lt;/span&gt; TEMP_CODE_START &lt;span class="k"&gt;*&lt;/span&gt;/ &lt;span class="o"&gt;||&lt;/span&gt;| /&lt;span class="k"&gt;*&lt;/span&gt; TEMP_CODE_END &lt;span class="k"&gt;*&lt;/span&gt;/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  A Word of Caution: With Great Power...
&lt;/h2&gt;

&lt;p&gt;Like any powerful tool, &lt;code&gt;git-selective-ignore&lt;/code&gt; should be used thoughtfully. It's not a license to be sloppy with sensitive data, it's a safety net for the inevitable times when we are human.&lt;/p&gt;

&lt;h4&gt;
  
  
  Remember:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Security is still your responsibility&lt;/strong&gt;: This tool helps prevent accidental commits, but you should still follow security best practices&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Team coordination matters&lt;/strong&gt;: Make sure your team knows which patterns are in place&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test your patterns&lt;/strong&gt;: Use the &lt;code&gt;status&lt;/code&gt; command to verify your patterns work as expected&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Future of Granular Version Control
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;git-selective-ignore&lt;/code&gt; points toward a future where version control systems understand that not everything in our working directory needs to be preserved for posterity. It's a tool that acknowledges the messy reality of software development while maintaining the clean history that makes Git so valuable.&lt;/p&gt;

&lt;p&gt;In a world where we're constantly told to "shift left" on security and best practices, tools like this help us maintain good hygiene without sacrificing development velocity. We can iterate quickly, debug effectively, and experiment freely, all while ensuring our Git history remains clean and secure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion: Sleep Better at Night
&lt;/h2&gt;

&lt;p&gt;The next time you're coding at 2 AM and need to hardcode an API key for testing, you can do so without the nagging worry that you'll forget to clean it up. The next time you want to add verbose debug logging to figure out a tricky bug, you can do it without cluttering your team's commit history.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git-selective-ignore&lt;/code&gt; gives you the freedom to develop the way you need to while maintaining the professional, secure codebase your team depends on. It's not just a tool, it's peace of mind.&lt;/p&gt;

&lt;p&gt;And your security team? They'll sleep better too, knowing that those 2 AM coding sessions are far less likely to result in morning meetings about exposed credentials.&lt;/p&gt;

&lt;p&gt;Now if you'll excuse me, I need to go commit some code. Don't worry, I've got selective ignore set up for my embarrassing variable names.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Ready to try git-selective-ignore? Check it out on &lt;a href="https://github.com/kodelint/git-selective-ignore" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; and start committing with confidence.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>rust</category>
      <category>git</category>
      <category>productivity</category>
      <category>cli</category>
    </item>
    <item>
      <title>Git Selective Ignore: Because Sometimes You Need to Keep Secrets from Git (But Not From Yourself)</title>
      <dc:creator>Satyajit Roy</dc:creator>
      <pubDate>Tue, 13 Jan 2026 03:53:19 +0000</pubDate>
      <link>https://forem.com/deadlock/git-selective-ignore-because-sometimes-you-need-to-keep-secrets-from-git-but-not-from-yourself-1cc4</link>
      <guid>https://forem.com/deadlock/git-selective-ignore-because-sometimes-you-need-to-keep-secrets-from-git-but-not-from-yourself-1cc4</guid>
      <description>&lt;h1&gt;
  
  
  Git Selective Ignore: Because Sometimes You Need to Keep Secrets from Git (But Not From Yourself)
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;Or: How I Learned to Stop Worrying and Love Committing Without Fear&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Picture this:&lt;/strong&gt; It's 2 AM, you're deep in the coding zone, your coffee has gone cold (again), and you've just figured out why your API integration wasn't working. You quickly hardcode that API key to test it out—just temporarily, of course. The fix works! You're ecstatic. You commit your changes with a triumphant message: "Fixed the thing that was broken!"&lt;/p&gt;

&lt;p&gt;Fast forward to 9 AM the next day. Your security team is having what can only be described as a "spirited discussion" about API keys appearing in your Git history. Your coffee is cold again, but this time it's because your blood has turned to ice.&lt;/p&gt;

&lt;p&gt;Sound familiar? Welcome to the club. We have t-shirts, but ironically, we can't put the design in our Git repo because it has our logo's secret color codes in it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Git Philosophy: Everything Is Sacred (Even Your Mistakes)
&lt;/h2&gt;

&lt;p&gt;Git operates on a beautiful but sometimes inconvenient principle: &lt;strong&gt;everything matters&lt;/strong&gt;. When Linus Torvalds created &lt;code&gt;Git&lt;/code&gt; in 2005 &lt;em&gt;(in just 10 days, because apparently some people are just built different)&lt;/em&gt;, he designed it around the idea that every character in your codebase tells a story. Git treats files as atomic units—either the whole file is tracked, or it isn't.&lt;/p&gt;

&lt;p&gt;This philosophy has served us well. Git's immutable history and complete file tracking have prevented countless disasters. But it also means that when you accidentally commit &lt;code&gt;API_KEY = "sk_live_definitely_not_my_real_key_12345"&lt;/code&gt;, Git faithfully preserves that mistake for all eternity, like a digital time capsule of your poor judgment.&lt;/p&gt;

&lt;p&gt;The traditional &lt;code&gt;.gitignore&lt;/code&gt; file is fantastic for what it does—ignoring entire files or directories. Need to keep your &lt;code&gt;node_modules&lt;/code&gt; out of the repo? Perfect. Don't want your IDE settings cluttering up the project? Easy. But try telling &lt;code&gt;.gitignore&lt;/code&gt; to ignore just line 42 of &lt;code&gt;config.py&lt;/code&gt; while keeping the rest of the file, and it'll give you the digital equivalent of a blank stare.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enter the Real World: Where Perfect Theory Meets Messy Reality
&lt;/h2&gt;

&lt;p&gt;Here's the thing about development: we live in a world of temporary hacks that become permanent features, debug statements that somehow make it to production, and test configurations that work so well locally that we forget they contain production credentials.&lt;/p&gt;

&lt;h3&gt;
  
  
  Consider these common scenarios:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Debug Block&lt;/strong&gt;: Those &lt;code&gt;console.log&lt;/code&gt; statements that helped you figure out why the async function was returning undefined, but now clutter your clean, professional codebase.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Local Config&lt;/strong&gt;: Database connection strings, API endpoints, and feature flags that need to be different for local development but shouldn't make their way into the shared repository.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Temporary Experiment&lt;/strong&gt;: That experimental algorithm you're testing, complete with hardcoded values and performance logging, sitting right in the middle of your otherwise pristine production code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Security Nightmare&lt;/strong&gt;: API keys, tokens, passwords, and other credentials that somehow always seem to sneak into codebases despite our best intentions.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Traditional Solutions: A Comedy of Errors
&lt;/h2&gt;

&lt;p&gt;Let's look at how we typically handle these situations:&lt;/p&gt;

&lt;h3&gt;
  
  
  Option 1: The Paranoid Approach
&lt;/h3&gt;

&lt;p&gt;You meticulously remove every sensitive line before committing, then carefully add them back after. This works great until you forget to add something back, spend three hours debugging why your app won't start, and realize you removed the line that sets up the database connection.&lt;/p&gt;

&lt;h3&gt;
  
  
  Option 2: The Environment Variable Dance
&lt;/h3&gt;

&lt;p&gt;You move everything to environment variables. This is actually good practice, but now your local setup requires a &lt;code&gt;.env&lt;/code&gt; file with 47 different variables, and new developers need a PhD in configuration management just to run the project locally.&lt;/p&gt;

&lt;h3&gt;
  
  
  Option 3: The Separate Config Files
&lt;/h3&gt;

&lt;p&gt;You keep sensitive configs in separate files and gitignore those files entirely. This works until you need to share the structure of the config with your team, or until someone accidentally deletes the local config file and has no template to recreate it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Option 4: The Git Surgery
&lt;/h3&gt;

&lt;p&gt;You realize you've committed something sensitive and spend the next hour learning about &lt;code&gt;git filter-branch&lt;/code&gt; and &lt;code&gt;BFG Repo-Cleaner&lt;/code&gt;. By the time you're done, you've rewritten half your Git history, broken everyone else's local repos, and you're pretty sure you've violated several laws of physics.&lt;/p&gt;

&lt;h2&gt;
  
  
  Git Selective Ignore: A Surgical Solution
&lt;/h2&gt;

&lt;p&gt;This is where &lt;code&gt;git-selective-ignore&lt;/code&gt; comes in. Think of it as a precision instrument in a world of sledgehammers.&lt;/p&gt;

&lt;p&gt;
  &lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fkodelint%2Fblog-images%2Fblob%2Fmain%2Fcommon%2F01-git-selecting-ignore.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fkodelint%2Fblog-images%2Fblob%2Fmain%2Fcommon%2F01-git-selecting-ignore.png" alt="git-selective-ignore" width="" height=""&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;Instead of treating files as atomic units, this tool lets you specify exactly which parts of a file should be ignored during commits. It's like having a conversation with Git:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You&lt;/strong&gt;: &lt;em&gt;"Hey Git, commit this file, but ignore lines 13-16, and also any line that contains 'API_KEY', and oh, while you're at it, skip that debug block between the comments."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Git&lt;/strong&gt;: &lt;em&gt;"That's not how I—"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;git-selective-ignore&lt;/strong&gt;: &lt;em&gt;"I got this. &lt;code&gt;Git&lt;/code&gt;, just commit what they want you to commit. Trust me."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Git&lt;/strong&gt;: "...okay, but this feels weird."&lt;/p&gt;

&lt;h2&gt;
  
  
  How It Actually Works (The Magic Behind the Curtain)
&lt;/h2&gt;

&lt;p&gt;The tool operates using Git hooks—specifically &lt;code&gt;pre-commit&lt;/code&gt; and &lt;code&gt;post-commit&lt;/code&gt; hooks. Here's the elegant dance it performs:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Pre-commit&lt;/strong&gt;: Before Git commits your changes, the tool scans your staged files, creates temporary clean versions with the specified content removed, and stages these sanitized versions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Commit&lt;/strong&gt;: Git commits the clean versions to history.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Post-commit&lt;/strong&gt;: The tool restores your original files, so your working directory contains all your local configs, debug statements, and temporary code.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It's like having a butler who tidies up your room before guests arrive, then puts everything back exactly where you left it after they leave.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real-World Example: The API Key Tango
&lt;/h2&gt;

&lt;p&gt;Let's say you have this in your &lt;code&gt;main.rs&lt;/code&gt; and &lt;code&gt;lib.rs&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Starting application..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// DEBUG BLOCK START&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Debug: Application started in debug mode"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// DEBUG BLOCK END&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;API_KEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"sk_live_1234567890abcdef"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Using API key: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;API_KEY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="cm"&gt;/* Temporary lines for testing - remove before prod */&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;temp_feature&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"experimental_feature_xyz"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Testing temporary feature: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;temp_feature&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="cm"&gt;/* End temporary section */&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;SECRET&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Some secret value"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"SECRET configured"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Application completed successfully"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Another Test"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;GITHUB_TOKEN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"github_fake_token_093790841-831-8lncdlwnelkqix12=-1x;xm;m"&lt;/span&gt;

    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{} &amp;lt;- My GitHub Token"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;GITHUB_TOKEN&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;API_KEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;env&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;'API_KEY&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="nn"&gt;env&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;'API_KEY&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"The value of APP_KEY is: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;API_KEY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nd"&gt;eprintln!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Error getting environment variable {}: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;'API_KEY&lt;/span&gt;'&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With traditional &lt;code&gt;Git&lt;/code&gt;, you have two choices:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Commit everything (including secrets) 😬😬😬&lt;/li&gt;
&lt;li&gt;Manually clean it up before every commit 🫩🫩🫩&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;With &lt;code&gt;git-selective-ignore&lt;/code&gt;, you set up your patterns once 🕺🏽 💃🏻:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Ignore any lines containing these sensitive terms&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; git-selective-ignore add all API_KEY &lt;span class="nt"&gt;--pattern-type&lt;/span&gt; line-regex
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; git-selective-ignore add all SECRET &lt;span class="nt"&gt;--pattern-type&lt;/span&gt; line-regex

&lt;span class="c"&gt;# Ignore debug blocks&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; git-selective-ignore add all &lt;span class="s2"&gt;"// DEBUG BLOCK START ||| // DEBUG BLOCK END"&lt;/span&gt; &lt;span class="nt"&gt;--pattern-type&lt;/span&gt; block-start-end

&lt;span class="c"&gt;# Ignore specific line ranges for temporary code&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; git-selective-ignore add src/main.rs 13-16 &lt;span class="nt"&gt;--pattern-type&lt;/span&gt; line-range
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now when you commit, Git's history will only contain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Starting application..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Using API key: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;API_KEY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"SECRET configured"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Application completed successfully"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But your local file remains unchanged, so you can keep working with all your debug statements and test configurations intact.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Approach Works Better
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Compared to Manual Cleanup
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No more forgetting&lt;/strong&gt;: You don't have to remember what to remove and add back&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No broken local environments&lt;/strong&gt;: Your working directory always contains what you need&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consistent team experience&lt;/strong&gt;: Everyone gets the same sanitized commits&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Compared to Environment Variables
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Faster iteration&lt;/strong&gt;: No need to restart processes when changing test values&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Better debugging&lt;/strong&gt;: You can see actual values in your code while developing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Simpler onboarding&lt;/strong&gt;: New developers can run the project with sensible defaults&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Compared to Separate Config Files
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No structural divergence&lt;/strong&gt;: The team sees the shape of your configuration&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No lost configs&lt;/strong&gt;: Your local setup is preserved in your working directory&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Version control benefits&lt;/strong&gt;: You can still track changes to the configuration structure&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Advanced Patterns: Getting Surgical
&lt;/h2&gt;

&lt;p&gt;The tool supports several pattern types for different use cases:&lt;/p&gt;

&lt;h3&gt;
  
  
  Line Regex (for scattered sensitive data)
&lt;/h3&gt;

&lt;p&gt;Perfect for API keys, passwords, or debug statements scattered throughout your codebase:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; git-selective-ignore add all &lt;span class="s2"&gt;"console&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="s2"&gt;log.*debug"&lt;/span&gt; &lt;span class="nt"&gt;--pattern-type&lt;/span&gt; line-regex
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Line Ranges (for temporary code blocks)
&lt;/h3&gt;

&lt;p&gt;When you know exactly which lines contain temporary code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; git-selective-ignore add src/config.py 45-52 &lt;span class="nt"&gt;--pattern-type&lt;/span&gt; line-range
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Block Start/End (for structured temporary sections)
&lt;/h3&gt;

&lt;p&gt;When you use comments to mark temporary code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; git-selective-ignore add all &lt;span class="s2"&gt;"// TODO: REMOVE ||| // END TODO"&lt;/span&gt; &lt;span class="nt"&gt;--pattern-type&lt;/span&gt; block-start-end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Philosophy Shift: From Binary to Granular
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;git-selective-ignore&lt;/code&gt; represents a philosophical shift in how we think about version control. Instead of the binary choice of "track this file or don't," we get granular control over what parts of our development process should be preserved in history.&lt;/p&gt;

&lt;p&gt;This isn't about hiding poor practices—it's about recognizing that the code we need to develop effectively isn't always the same as the code we want to preserve historically. It's the difference between your private workshop (messy, full of tools and work-in-progress) and the finished product you show to the world.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started: Your First Steps into Selective Ignoring
&lt;/h2&gt;

&lt;p&gt;Installation is straightforward. You can use their &lt;a href="https://github.com/kodelint/setup-devbox" rel="noopener noreferrer"&gt;setup-devbox&lt;/a&gt; tool, download from releases, or build from source:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Build from source&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; git clone https://github.com/kodelint/git-selective-ignore.git
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;git-selective-ignore
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; cargo &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--path&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then in any repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Initialize selective ignore&lt;/span&gt;
git-selective-ignore init

&lt;span class="c"&gt;# Install the Git hooks&lt;/span&gt;
git-selective-ignore install-hooks

&lt;span class="c"&gt;# Add your first pattern&lt;/span&gt;
git-selective-ignore add all &lt;span class="s2"&gt;"API_KEY"&lt;/span&gt; &lt;span class="nt"&gt;--pattern-type&lt;/span&gt; line-regex

&lt;span class="c"&gt;# Check what would be ignored&lt;/span&gt;
git-selective-ignore status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The tool stores its configuration in &lt;code&gt;.git/selective-ignore.toml&lt;/code&gt;, so each repository can have its own rules without affecting others.&lt;/p&gt;

&lt;p&gt;You can also see the violations in the code base with &lt;code&gt;status&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; git-selective-ignore status
✓ Configuration is valid.
   ├─ Line Range Pattern &lt;span class="s1"&gt;'13-16'&lt;/span&gt;: 4 line&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; matched
   │  └─ Lines 13-16
   ├─ Regex Pattern &lt;span class="s1"&gt;'API_KEY'&lt;/span&gt;: 1 line&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; matched
   │  └─ Line 10
   ├─ Regex Pattern &lt;span class="s1"&gt;'GITHUB_TOKEN'&lt;/span&gt;: 1 line&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; matched
   │  └─ Line 20
   ├─ Block Pattern &lt;span class="s1"&gt;'// DEBUG BLOCK START ||| // DEBUG BLOCK END'&lt;/span&gt;: 3 line&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; matched
   │  └─ Lines 6-8
   ├─ Regex Pattern &lt;span class="s1"&gt;'SECRET'&lt;/span&gt;: 1 line&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; matched
   │  └─ Line 18
   └─ Summary: 10 line&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; ignored, 17 line&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; remaining &lt;span class="o"&gt;(&lt;/span&gt;of 27 total&lt;span class="o"&gt;)&lt;/span&gt;
   ├─ Regex Pattern &lt;span class="s1"&gt;'GITHUB_TOKEN'&lt;/span&gt;: 1 line&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; matched
   │  └─ Line 7
   └─ Summary: 1 line&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; ignored, 18 line&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; remaining &lt;span class="o"&gt;(&lt;/span&gt;of 19 total&lt;span class="o"&gt;)&lt;/span&gt;
📊 Git Selective Ignore Status Report
&lt;span class="o"&gt;=====================================&lt;/span&gt;
🎯 Specifically Configured Files:
🟡 src/main.rs &lt;span class="o"&gt;(&lt;/span&gt;8 patterns, 10/27 lines ignored, 37.0%&lt;span class="o"&gt;)&lt;/span&gt;

🌐 Files Affected by Global &lt;span class="s1"&gt;'ALL'&lt;/span&gt; Patterns:
🟡 src/lib.rs &lt;span class="o"&gt;(&lt;/span&gt;6 patterns, 1/19 lines ignored, 5.3%&lt;span class="o"&gt;)&lt;/span&gt;

📈 Summary:
  Total files: 2
  Total patterns: 8
  Total ignored lines: 11
  Files with issues: 2

📋 Breakdown:
  Specifically configured files: 1
  Files affected by &lt;span class="s1"&gt;'ALL'&lt;/span&gt; patterns only: 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use &lt;code&gt;list&lt;/code&gt; to see what Ignore Patterns are installed&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; git-selective-ignore list
✓ Configuration is valid.

📁 File: all
  🔍 ID: 78ed02f4-db7c-4921-b565-5e8986f19705 | Type: LineRegex | Pattern: API_KEY
  🔍 ID: 7fb165d1-bab6-4c79-a13b-51f2f29a88e9 | Type: LineRegex | Pattern: APP_KEY
  🔍 ID: 02b17597-bb85-428c-be56-3d0cd4a3c44b | Type: LineRegex | Pattern: GITHUB_TOKEN
  🔍 ID: 76447f06-dd03-4c3b-b27a-b611579e9cb8 | Type: BlockStartEnd | Pattern: // DEBUG BLOCK START &lt;span class="o"&gt;||&lt;/span&gt;| // DEBUG BLOCK END
  🔍 ID: 48f984d1-dd90-4984-99d6-ae6c63c591d6 | Type: LineRegex | Pattern: SECRET
  🔍 ID: b9a54bc2-048d-4fa0-b6ff-dc66aff6e706 | Type: LineRegex | Pattern: password

📁 File: src/main.rs
  🔍 ID: 31ca2ff0-90d8-47ea-90db-413cedf09bcf | Type: LineRange | Pattern: 13-16
  🔍 ID: a941d428-87ed-4378-898d-d5156723dfd0 | Type: BlockStartEnd | Pattern: /&lt;span class="k"&gt;*&lt;/span&gt; TEMP_CODE_START &lt;span class="k"&gt;*&lt;/span&gt;/ &lt;span class="o"&gt;||&lt;/span&gt;| /&lt;span class="k"&gt;*&lt;/span&gt; TEMP_CODE_END &lt;span class="k"&gt;*&lt;/span&gt;/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  A Word of Caution: With Great Power...
&lt;/h2&gt;

&lt;p&gt;Like any powerful tool, &lt;code&gt;git-selective-ignore&lt;/code&gt; should be used thoughtfully. It's not a license to be sloppy with sensitive data, it's a safety net for the inevitable times when we are human.&lt;/p&gt;

&lt;h4&gt;
  
  
  Remember:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Security is still your responsibility&lt;/strong&gt;: This tool helps prevent accidental commits, but you should still follow security best practices&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Team coordination matters&lt;/strong&gt;: Make sure your team knows which patterns are in place&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test your patterns&lt;/strong&gt;: Use the &lt;code&gt;status&lt;/code&gt; command to verify your patterns work as expected&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Future of Granular Version Control
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;git-selective-ignore&lt;/code&gt; points toward a future where version control systems understand that not everything in our working directory needs to be preserved for posterity. It's a tool that acknowledges the messy reality of software development while maintaining the clean history that makes Git so valuable.&lt;/p&gt;

&lt;p&gt;In a world where we're constantly told to "shift left" on security and best practices, tools like this help us maintain good hygiene without sacrificing development velocity. We can iterate quickly, debug effectively, and experiment freely, all while ensuring our Git history remains clean and secure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion: Sleep Better at Night
&lt;/h2&gt;

&lt;p&gt;The next time you're coding at 2 AM and need to hardcode an API key for testing, you can do so without the nagging worry that you'll forget to clean it up. The next time you want to add verbose debug logging to figure out a tricky bug, you can do it without cluttering your team's commit history.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git-selective-ignore&lt;/code&gt; gives you the freedom to develop the way you need to while maintaining the professional, secure codebase your team depends on. It's not just a tool, it's peace of mind.&lt;/p&gt;

&lt;p&gt;And your security team? They'll sleep better too, knowing that those 2 AM coding sessions are far less likely to result in morning meetings about exposed credentials.&lt;/p&gt;

&lt;p&gt;Now if you'll excuse me, I need to go commit some code. Don't worry, I've got selective ignore set up for my embarrassing variable names.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Ready to try git-selective-ignore? Check it out on &lt;a href="https://github.com/kodelint/git-selective-ignore" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; and start committing with confidence.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>rust</category>
      <category>git</category>
      <category>productivity</category>
      <category>cli</category>
    </item>
    <item>
      <title>Git Selective Ignore: Because Sometimes You Need to Keep Secrets from Git (But Not From Yourself)</title>
      <dc:creator>Satyajit Roy</dc:creator>
      <pubDate>Tue, 13 Jan 2026 02:55:54 +0000</pubDate>
      <link>https://forem.com/deadlock/git-selective-ignore-because-sometimes-you-need-to-keep-secrets-from-git-but-not-from-yourself-al8</link>
      <guid>https://forem.com/deadlock/git-selective-ignore-because-sometimes-you-need-to-keep-secrets-from-git-but-not-from-yourself-al8</guid>
      <description>&lt;h1&gt;
  
  
  Git Selective Ignore: Because Sometimes You Need to Keep Secrets from Git (But Not From Yourself)
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;Or: How I Learned to Stop Worrying and Love Committing Without Fear&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Picture this:&lt;/strong&gt; It's &lt;strong&gt;2 AM&lt;/strong&gt;, you're deep in the coding zone, your coffee has gone cold (again), and you've just figured out why your API integration wasn't working. You quickly hardcode that API key to test it out—just temporarily, of course. The fix works! You're ecstatic. You commit your changes with a triumphant message: "Fixed the thing that was broken!"&lt;/p&gt;

&lt;p&gt;Fast forward to &lt;strong&gt;9 AM&lt;/strong&gt; the next day. Your security team is having what can only be described as a "spirited discussion" about API keys appearing in your Git history. Your coffee is cold again, but this time it's because your blood has turned to ice.&lt;/p&gt;

&lt;p&gt;Sound familiar? Welcome to the club. We have t-shirts, but ironically, we can't put the design in our Git repo because it has our logo's secret color codes in it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Git Philosophy: Everything Is Sacred (Even Your Mistakes)
&lt;/h2&gt;

&lt;p&gt;Git operates on a beautiful but sometimes inconvenient principle: &lt;strong&gt;everything matters&lt;/strong&gt;. When Linus Torvalds created &lt;code&gt;Git&lt;/code&gt; in 2005 &lt;em&gt;(in just 10 days, because apparently some people are just built different)&lt;/em&gt;, he designed it around the idea that every character in your codebase tells a story. Git treats files as atomic units—either the whole file is tracked, or it isn't.&lt;/p&gt;

&lt;p&gt;This philosophy has served us well. Git's immutable history and complete file tracking have prevented countless disasters. But it also means that when you accidentally commit &lt;code&gt;API_KEY = "sk_live_definitely_not_my_real_key_12345"&lt;/code&gt;, Git faithfully preserves that mistake for all eternity, like a digital time capsule of your poor judgment.&lt;/p&gt;

&lt;p&gt;The traditional &lt;code&gt;.gitignore&lt;/code&gt; file is fantastic for what it does—ignoring entire files or directories. Need to keep your &lt;code&gt;node_modules&lt;/code&gt; out of the repo? Perfect. Don't want your IDE settings cluttering up the project? Easy. But try telling &lt;code&gt;.gitignore&lt;/code&gt; to ignore just line 42 of &lt;code&gt;config.py&lt;/code&gt; while keeping the rest of the file, and it'll give you the digital equivalent of a blank stare.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enter the Real World: Where Perfect Theory Meets Messy Reality
&lt;/h2&gt;

&lt;p&gt;Here's the thing about development: we live in a world of temporary hacks that become permanent features, debug statements that somehow make it to production, and test configurations that work so well locally that we forget they contain production credentials.&lt;/p&gt;

&lt;h3&gt;
  
  
  Consider these common scenarios:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Debug Block&lt;/strong&gt;: Those &lt;code&gt;console.log&lt;/code&gt; statements that helped you figure out why the async function was returning undefined, but now clutter your clean, professional codebase.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Local Config&lt;/strong&gt;: Database connection strings, API endpoints, and feature flags that need to be different for local development but shouldn't make their way into the shared repository.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Temporary Experiment&lt;/strong&gt;: That experimental algorithm you're testing, complete with hardcoded values and performance logging, sitting right in the middle of your otherwise pristine production code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Security Nightmare&lt;/strong&gt;: API keys, tokens, passwords, and other credentials that somehow always seem to sneak into codebases despite our best intentions.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Traditional Solutions: A Comedy of Errors
&lt;/h2&gt;

&lt;p&gt;Let's look at how we typically handle these situations:&lt;/p&gt;

&lt;h3&gt;
  
  
  Option 1: The Paranoid Approach
&lt;/h3&gt;

&lt;p&gt;You meticulously remove every sensitive line before committing, then carefully add them back after. This works great until you forget to add something back, spend three hours debugging why your app won't start, and realize you removed the line that sets up the database connection.&lt;/p&gt;

&lt;h3&gt;
  
  
  Option 2: The Environment Variable Dance
&lt;/h3&gt;

&lt;p&gt;You move everything to environment variables. This is actually good practice, but now your local setup requires a &lt;code&gt;.env&lt;/code&gt; file with 47 different variables, and new developers need a PhD in configuration management just to run the project locally.&lt;/p&gt;

&lt;h3&gt;
  
  
  Option 3: The Separate Config Files
&lt;/h3&gt;

&lt;p&gt;You keep sensitive configs in separate files and gitignore those files entirely. This works until you need to share the structure of the config with your team, or until someone accidentally deletes the local config file and has no template to recreate it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Option 4: The Git Surgery
&lt;/h3&gt;

&lt;p&gt;You realize you've committed something sensitive and spend the next hour learning about &lt;code&gt;git filter-branch&lt;/code&gt; and &lt;code&gt;BFG Repo-Cleaner&lt;/code&gt;. By the time you're done, you've rewritten half your Git history, broken everyone else's local repos, and you're pretty sure you've violated several laws of physics.&lt;/p&gt;

&lt;h2&gt;
  
  
  Git Selective Ignore: A Surgical Solution
&lt;/h2&gt;

&lt;p&gt;This is where &lt;code&gt;git-selective-ignore&lt;/code&gt; comes in. Think of it as a precision instrument in a world of sledgehammers.&lt;/p&gt;

&lt;p&gt;
  &lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fkodelint%2Fblog-images%2Fblob%2Fmain%2Fcommon%2F01-git-selecting-ignore.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fkodelint%2Fblog-images%2Fblob%2Fmain%2Fcommon%2F01-git-selecting-ignore.png" alt="git-selective-ignore" width="" height=""&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;Instead of treating files as atomic units, this tool lets you specify exactly which parts of a file should be ignored during commits. It's like having a conversation with Git:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You&lt;/strong&gt;: &lt;em&gt;"Hey Git, commit this file, but ignore lines 13-16, and also any line that contains 'API_KEY', and oh, while you're at it, skip that debug block between the comments."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Git&lt;/strong&gt;: &lt;em&gt;"That's not how I—"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;git-selective-ignore&lt;/strong&gt;: &lt;em&gt;"I got this. &lt;code&gt;Git&lt;/code&gt;, just commit what they want you to commit. Trust me."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Git&lt;/strong&gt;: "...okay, but this feels weird."&lt;/p&gt;

&lt;h2&gt;
  
  
  How It Actually Works (The Magic Behind the Curtain)
&lt;/h2&gt;

&lt;p&gt;The tool operates using Git hooks—specifically &lt;code&gt;pre-commit&lt;/code&gt; and &lt;code&gt;post-commit&lt;/code&gt; hooks. Here's the elegant dance it performs:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Pre-commit&lt;/strong&gt;: Before Git commits your changes, the tool scans your staged files, creates temporary clean versions with the specified content removed, and stages these sanitized versions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Commit&lt;/strong&gt;: Git commits the clean versions to history.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Post-commit&lt;/strong&gt;: The tool restores your original files, so your working directory contains all your local configs, debug statements, and temporary code.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It's like having a butler who tidies up your room before guests arrive, then puts everything back exactly where you left it after they leave.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real-World Example: The API Key Tango
&lt;/h2&gt;

&lt;p&gt;Let's say you have this in your &lt;code&gt;main.rs&lt;/code&gt; and &lt;code&gt;lib.rs&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Starting application..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// DEBUG BLOCK START&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Debug: Application started in debug mode"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// DEBUG BLOCK END&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;API_KEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"sk_live_1234567890abcdef"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Using API key: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;API_KEY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="cm"&gt;/* Temporary lines for testing - remove before prod */&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;temp_feature&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"experimental_feature_xyz"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Testing temporary feature: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;temp_feature&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="cm"&gt;/* End temporary section */&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;SECRET&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Some secret value"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"SECRET configured"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Application completed successfully"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Another Test"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;GITHUB_TOKEN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"github_fake_token_093790841-831-8lncdlwnelkqix12=-1x;xm;m"&lt;/span&gt;

    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{} &amp;lt;- My GitHub Token"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;GITHUB_TOKEN&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;API_KEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;env&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;'API_KEY&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="nn"&gt;env&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;'API_KEY&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"The value of APP_KEY is: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;API_KEY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nd"&gt;eprintln!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Error getting environment variable {}: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;'API_KEY&lt;/span&gt;'&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With traditional &lt;code&gt;Git&lt;/code&gt;, you have two choices:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Commit everything (including secrets) 😬😬😬&lt;/li&gt;
&lt;li&gt;Manually clean it up before every commit 🫩🫩🫩&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;With &lt;code&gt;git-selective-ignore&lt;/code&gt;, you set up your patterns once 🕺🏽 💃🏻:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Ignore any lines containing these sensitive terms&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; git-selective-ignore add all API_KEY &lt;span class="nt"&gt;--pattern-type&lt;/span&gt; line-regex
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; git-selective-ignore add all SECRET &lt;span class="nt"&gt;--pattern-type&lt;/span&gt; line-regex

&lt;span class="c"&gt;# Ignore debug blocks&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; git-selective-ignore add all &lt;span class="s2"&gt;"// DEBUG BLOCK START ||| // DEBUG BLOCK END"&lt;/span&gt; &lt;span class="nt"&gt;--pattern-type&lt;/span&gt; block-start-end

&lt;span class="c"&gt;# Ignore specific line ranges for temporary code&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; git-selective-ignore add src/main.rs 13-16 &lt;span class="nt"&gt;--pattern-type&lt;/span&gt; line-range
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now when you commit, Git's history will only contain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Starting application..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Using API key: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;API_KEY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"SECRET configured"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Application completed successfully"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But your local file remains unchanged, so you can keep working with all your debug statements and test configurations intact.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Approach Works Better
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Compared to Manual Cleanup
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No more forgetting&lt;/strong&gt;: You don't have to remember what to remove and add back&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No broken local environments&lt;/strong&gt;: Your working directory always contains what you need&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consistent team experience&lt;/strong&gt;: Everyone gets the same sanitized commits&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Compared to Environment Variables
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Faster iteration&lt;/strong&gt;: No need to restart processes when changing test values&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Better debugging&lt;/strong&gt;: You can see actual values in your code while developing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Simpler onboarding&lt;/strong&gt;: New developers can run the project with sensible defaults&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Compared to Separate Config Files
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No structural divergence&lt;/strong&gt;: The team sees the shape of your configuration&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No lost configs&lt;/strong&gt;: Your local setup is preserved in your working directory&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Version control benefits&lt;/strong&gt;: You can still track changes to the configuration structure&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Advanced Patterns: Getting Surgical
&lt;/h2&gt;

&lt;p&gt;The tool supports several pattern types for different use cases:&lt;/p&gt;

&lt;h3&gt;
  
  
  Line Regex (for scattered sensitive data)
&lt;/h3&gt;

&lt;p&gt;Perfect for API keys, passwords, or debug statements scattered throughout your codebase:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; git-selective-ignore add all &lt;span class="s2"&gt;"console&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="s2"&gt;log.*debug"&lt;/span&gt; &lt;span class="nt"&gt;--pattern-type&lt;/span&gt; line-regex
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Line Ranges (for temporary code blocks)
&lt;/h3&gt;

&lt;p&gt;When you know exactly which lines contain temporary code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; git-selective-ignore add src/config.py 45-52 &lt;span class="nt"&gt;--pattern-type&lt;/span&gt; line-range
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Block Start/End (for structured temporary sections)
&lt;/h3&gt;

&lt;p&gt;When you use comments to mark temporary code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; git-selective-ignore add all &lt;span class="s2"&gt;"// TODO: REMOVE ||| // END TODO"&lt;/span&gt; &lt;span class="nt"&gt;--pattern-type&lt;/span&gt; block-start-end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Philosophy Shift: From Binary to Granular
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;git-selective-ignore&lt;/code&gt; represents a philosophical shift in how we think about version control. Instead of the binary choice of "track this file or don't," we get granular control over what parts of our development process should be preserved in history.&lt;/p&gt;

&lt;p&gt;This isn't about hiding poor practices—it's about recognizing that the code we need to develop effectively isn't always the same as the code we want to preserve historically. It's the difference between your private workshop (messy, full of tools and work-in-progress) and the finished product you show to the world.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started: Your First Steps into Selective Ignoring
&lt;/h2&gt;

&lt;p&gt;Installation is straightforward. You can use their &lt;a href="https://github.com/kodelint/setup-devbox" rel="noopener noreferrer"&gt;setup-devbox&lt;/a&gt; tool, download from releases, or build from source:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Build from source&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; git clone https://github.com/kodelint/git-selective-ignore.git
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;git-selective-ignore
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; cargo &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--path&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then in any repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Initialize selective ignore&lt;/span&gt;
git-selective-ignore init

&lt;span class="c"&gt;# Install the Git hooks&lt;/span&gt;
git-selective-ignore install-hooks

&lt;span class="c"&gt;# Add your first pattern&lt;/span&gt;
git-selective-ignore add all &lt;span class="s2"&gt;"API_KEY"&lt;/span&gt; &lt;span class="nt"&gt;--pattern-type&lt;/span&gt; line-regex

&lt;span class="c"&gt;# Check what would be ignored&lt;/span&gt;
git-selective-ignore status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The tool stores its configuration in &lt;code&gt;.git/selective-ignore.toml&lt;/code&gt;, so each repository can have its own rules without affecting others.&lt;/p&gt;

&lt;p&gt;You can also see the violations in the code base with &lt;code&gt;status&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; git-selective-ignore status
✓ Configuration is valid.
   ├─ Line Range Pattern &lt;span class="s1"&gt;'13-16'&lt;/span&gt;: 4 line&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; matched
   │  └─ Lines 13-16
   ├─ Regex Pattern &lt;span class="s1"&gt;'API_KEY'&lt;/span&gt;: 1 line&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; matched
   │  └─ Line 10
   ├─ Regex Pattern &lt;span class="s1"&gt;'GITHUB_TOKEN'&lt;/span&gt;: 1 line&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; matched
   │  └─ Line 20
   ├─ Block Pattern &lt;span class="s1"&gt;'// DEBUG BLOCK START ||| // DEBUG BLOCK END'&lt;/span&gt;: 3 line&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; matched
   │  └─ Lines 6-8
   ├─ Regex Pattern &lt;span class="s1"&gt;'SECRET'&lt;/span&gt;: 1 line&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; matched
   │  └─ Line 18
   └─ Summary: 10 line&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; ignored, 17 line&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; remaining &lt;span class="o"&gt;(&lt;/span&gt;of 27 total&lt;span class="o"&gt;)&lt;/span&gt;
   ├─ Regex Pattern &lt;span class="s1"&gt;'GITHUB_TOKEN'&lt;/span&gt;: 1 line&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; matched
   │  └─ Line 7
   └─ Summary: 1 line&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; ignored, 18 line&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; remaining &lt;span class="o"&gt;(&lt;/span&gt;of 19 total&lt;span class="o"&gt;)&lt;/span&gt;
📊 Git Selective Ignore Status Report
&lt;span class="o"&gt;=====================================&lt;/span&gt;
🎯 Specifically Configured Files:
🟡 src/main.rs &lt;span class="o"&gt;(&lt;/span&gt;8 patterns, 10/27 lines ignored, 37.0%&lt;span class="o"&gt;)&lt;/span&gt;

🌐 Files Affected by Global &lt;span class="s1"&gt;'ALL'&lt;/span&gt; Patterns:
🟡 src/lib.rs &lt;span class="o"&gt;(&lt;/span&gt;6 patterns, 1/19 lines ignored, 5.3%&lt;span class="o"&gt;)&lt;/span&gt;

📈 Summary:
  Total files: 2
  Total patterns: 8
  Total ignored lines: 11
  Files with issues: 2

📋 Breakdown:
  Specifically configured files: 1
  Files affected by &lt;span class="s1"&gt;'ALL'&lt;/span&gt; patterns only: 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use &lt;code&gt;list&lt;/code&gt; to see what Ignore Patterns are installed&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; git-selective-ignore list
✓ Configuration is valid.

📁 File: all
  🔍 ID: 78ed02f4-db7c-4921-b565-5e8986f19705 | Type: LineRegex | Pattern: API_KEY
  🔍 ID: 7fb165d1-bab6-4c79-a13b-51f2f29a88e9 | Type: LineRegex | Pattern: APP_KEY
  🔍 ID: 02b17597-bb85-428c-be56-3d0cd4a3c44b | Type: LineRegex | Pattern: GITHUB_TOKEN
  🔍 ID: 76447f06-dd03-4c3b-b27a-b611579e9cb8 | Type: BlockStartEnd | Pattern: // DEBUG BLOCK START &lt;span class="o"&gt;||&lt;/span&gt;| // DEBUG BLOCK END
  🔍 ID: 48f984d1-dd90-4984-99d6-ae6c63c591d6 | Type: LineRegex | Pattern: SECRET
  🔍 ID: b9a54bc2-048d-4fa0-b6ff-dc66aff6e706 | Type: LineRegex | Pattern: password

📁 File: src/main.rs
  🔍 ID: 31ca2ff0-90d8-47ea-90db-413cedf09bcf | Type: LineRange | Pattern: 13-16
  🔍 ID: a941d428-87ed-4378-898d-d5156723dfd0 | Type: BlockStartEnd | Pattern: /&lt;span class="k"&gt;*&lt;/span&gt; TEMP_CODE_START &lt;span class="k"&gt;*&lt;/span&gt;/ &lt;span class="o"&gt;||&lt;/span&gt;| /&lt;span class="k"&gt;*&lt;/span&gt; TEMP_CODE_END &lt;span class="k"&gt;*&lt;/span&gt;/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  A Word of Caution: With Great Power...
&lt;/h2&gt;

&lt;p&gt;Like any powerful tool, &lt;code&gt;git-selective-ignore&lt;/code&gt; should be used thoughtfully. It's not a license to be sloppy with sensitive data, it's a safety net for the inevitable times when we are human.&lt;/p&gt;

&lt;h4&gt;
  
  
  Remember:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Security is still your responsibility&lt;/strong&gt;: This tool helps prevent accidental commits, but you should still follow security best practices&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Team coordination matters&lt;/strong&gt;: Make sure your team knows which patterns are in place&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test your patterns&lt;/strong&gt;: Use the &lt;code&gt;status&lt;/code&gt; command to verify your patterns work as expected&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Future of Granular Version Control
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;git-selective-ignore&lt;/code&gt; points toward a future where version control systems understand that not everything in our working directory needs to be preserved for posterity. It's a tool that acknowledges the messy reality of software development while maintaining the clean history that makes Git so valuable.&lt;/p&gt;

&lt;p&gt;In a world where we're constantly told to "shift left" on security and best practices, tools like this help us maintain good hygiene without sacrificing development velocity. We can iterate quickly, debug effectively, and experiment freely, all while ensuring our Git history remains clean and secure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion: Sleep Better at Night
&lt;/h2&gt;

&lt;p&gt;The next time you're coding at 2 AM and need to hardcode an API key for testing, you can do so without the nagging worry that you'll forget to clean it up. The next time you want to add verbose debug logging to figure out a tricky bug, you can do it without cluttering your team's commit history.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git-selective-ignore&lt;/code&gt; gives you the freedom to develop the way you need to while maintaining the professional, secure codebase your team depends on. It's not just a tool, it's peace of mind.&lt;/p&gt;

&lt;p&gt;And your security team? They'll sleep better too, knowing that those 2 AM coding sessions are far less likely to result in morning meetings about exposed credentials.&lt;/p&gt;

&lt;p&gt;Now if you'll excuse me, I need to go commit some code. Don't worry, I've got selective ignore set up for my embarrassing variable names.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Ready to try git-selective-ignore? Check it out on &lt;a href="https://github.com/kodelint/git-selective-ignore" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; and start committing with confidence.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>rust</category>
      <category>git</category>
      <category>productivity</category>
      <category>cli</category>
    </item>
    <item>
      <title>Rust - Struct, Generics</title>
      <dc:creator>Satyajit Roy</dc:creator>
      <pubDate>Tue, 13 Jan 2026 02:51:41 +0000</pubDate>
      <link>https://forem.com/deadlock/rust-struct-generics-4a97</link>
      <guid>https://forem.com/deadlock/rust-struct-generics-4a97</guid>
      <description>&lt;p&gt;Let’s talk about the some custom &lt;strong&gt;data types&lt;/strong&gt; in &lt;strong&gt;Rust&lt;/strong&gt; like &lt;code&gt;struct&lt;/code&gt; and &lt;code&gt;emuns&lt;/code&gt; . We all know why need &lt;strong&gt;custom data type&lt;/strong&gt;, like any other language regular data type may not suffice the need and hence we have custom data types.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0va34xdtduughxbbsqpa.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0va34xdtduughxbbsqpa.jpg" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Structs, How to use them in &lt;code&gt;Rust&lt;/code&gt; ?
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Structure&lt;/strong&gt;, &lt;code&gt;struct&lt;/code&gt; in short, are very similar to &lt;code&gt;tuple&lt;/code&gt; . &lt;strong&gt;Tuple&lt;/strong&gt; are used to store related items with mixed data type in &lt;strong&gt;Order&lt;/strong&gt;. Now if the use case is to have large number of elements and the &lt;strong&gt;Order&lt;/strong&gt; is not obvious then it could be difficult to identify them out of Tuples&lt;/p&gt;

&lt;p&gt;So you can see that if number of elements are larger than normal then it becomes very difficult to keep track of the order and that’s when we use &lt;strong&gt;&lt;code&gt;struct&lt;/code&gt;&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;a_tuple&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Rust"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"the first element of tuple [a_tuple] is {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a_tuple&lt;/span&gt;&lt;span class="na"&gt;.0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"the last element of tuple [a_tuple] is {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a_tuple&lt;/span&gt;&lt;span class="na"&gt;.1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;a_tuple&lt;/span&gt;&lt;span class="na"&gt;.0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;a_tuple&lt;/span&gt;&lt;span class="na"&gt;.1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Rustic"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"the first element of tuple [a_tuple] after modification is {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a_tuple&lt;/span&gt;&lt;span class="na"&gt;.0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"the last element of tuple [a_tuple] after modification is {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a_tuple&lt;/span&gt;&lt;span class="na"&gt;.1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;💡 Memory Insight&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Struct&lt;/strong&gt;&lt;/em&gt; data are usually stored in &lt;strong&gt;stack&lt;/strong&gt; given it contain &lt;strong&gt;stack&lt;/strong&gt; only data types like &lt;em&gt;numbers&lt;/em&gt;. To store &lt;em&gt;Struct&lt;/em&gt; in &lt;strong&gt;heap&lt;/strong&gt; you have specifically mentioned that. Also, if your &lt;em&gt;&lt;strong&gt;Struct&lt;/strong&gt;&lt;/em&gt; contain &lt;strong&gt;heap&lt;/strong&gt; data types like &lt;code&gt;String&lt;/code&gt; then it will be stored in &lt;strong&gt;heap&lt;/strong&gt; and reference, associated data of the &lt;strong&gt;heap&lt;/strong&gt; data will be stored in &lt;strong&gt;stack&lt;/strong&gt;. So, when your &lt;em&gt;&lt;strong&gt;Struct&lt;/strong&gt;&lt;/em&gt; instance goes &lt;strong&gt;out of scope&lt;/strong&gt; the associated data in &lt;strong&gt;heap&lt;/strong&gt; will be &lt;strong&gt;automatically dropped&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;the first element of tuple &lt;span class="o"&gt;[&lt;/span&gt;a_tuple] is 1
the last element of tuple &lt;span class="o"&gt;[&lt;/span&gt;a_tuple] is Rust
the first element of tuple &lt;span class="o"&gt;[&lt;/span&gt;a_tuple] after modification is 6
the last element of tuple &lt;span class="o"&gt;[&lt;/span&gt;a_tuple] after modification is Rustic
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Defining a &lt;code&gt;struct&lt;/code&gt; in &lt;code&gt;Rust&lt;/code&gt; is similar to &lt;code&gt;Golang&lt;/code&gt;. &lt;code&gt;Golang&lt;/code&gt; require &lt;code&gt;type&lt;/code&gt; keyword along side with &lt;code&gt;struct&lt;/code&gt; keyword&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rust&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Car&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;year&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Golang&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Car&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Name&lt;/span&gt;  &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;Model&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;Year&lt;/span&gt;  &lt;span class="kt"&gt;uint32&lt;/span&gt;
    &lt;span class="n"&gt;Price&lt;/span&gt; &lt;span class="kt"&gt;uint32&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;A &lt;code&gt;struct&lt;/code&gt; is like a &lt;code&gt;tuple&lt;/code&gt;, which allows you to package together related items with mixed data type, however you don’t need to use the &lt;strong&gt;index&lt;/strong&gt; to access the elements, instead you use the field name to access them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Struct&lt;/strong&gt; also allow us to update an &lt;code&gt;instance&lt;/code&gt; from another &lt;code&gt;instance&lt;/code&gt; and the syntax is pretty simple called &lt;strong&gt;update syntax&lt;/strong&gt;, which basically tells &lt;code&gt;complier&lt;/code&gt; if there are missing field in instance should have the same field from previous instance.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;second_car&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Car&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Tesla"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Model 3"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="n"&gt;new_car&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Any update to the first instance after the second instance initialization will not reflect in second instance.&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you see then the missing fields are &lt;code&gt;int&lt;/code&gt; datatype means they live in &lt;strong&gt;stack&lt;/strong&gt;, therefore they gets implicitly copied. However, if there were any &lt;code&gt;String&lt;/code&gt; datatype involved, it would have error time as it violates the &lt;strong&gt;ownership&lt;/strong&gt; &lt;strong&gt;rule&lt;/strong&gt; of rust . To make that work we need to use explicit &lt;strong&gt;clone&lt;/strong&gt; for copying the data from first instance, something like this &lt;strong&gt;&lt;code&gt;..new_car.clone()&lt;/code&gt;&lt;/strong&gt;. To know more about &lt;a href="https://medium.com/p/5ba45c44f986" rel="noopener noreferrer"&gt;ownership and borrowing&lt;/a&gt;. Also we have to add &lt;code&gt;trait&lt;/code&gt; as the &lt;code&gt;Car&lt;/code&gt; datatype doesn’t have the &lt;code&gt;trait&lt;/code&gt; to &lt;code&gt;Clone()&lt;/code&gt; data, so we need to derived that at the &lt;strong&gt;struct definition&lt;/strong&gt;, something like this &lt;code&gt;#[derive(Clone)]&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Struct has methods
&lt;/h3&gt;

&lt;p&gt;In Rust we can call subroutines, which are &lt;strong&gt;method&lt;/strong&gt; for the &lt;strong&gt;struct&lt;/strong&gt;. They are pretty much like a &lt;strong&gt;function&lt;/strong&gt; and defined using &lt;code&gt;fn&lt;/code&gt; key word. The difference is between &lt;strong&gt;methods&lt;/strong&gt; and &lt;strong&gt;function&lt;/strong&gt; is that &lt;strong&gt;method&lt;/strong&gt; are always within the context of the &lt;code&gt;struct&lt;/code&gt; and the first input parameter is alway the &lt;code&gt;struct&lt;/code&gt; itself.&lt;/p&gt;

&lt;p&gt;To define the &lt;strong&gt;method&lt;/strong&gt; we need to &lt;code&gt;impl&lt;/code&gt; key word &lt;em&gt;(short for implementation)&lt;/em&gt; followed by the &lt;code&gt;struct&lt;/code&gt; name&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;Car&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Method to update the price&lt;/span&gt;
    &lt;span class="c1"&gt;// &amp;amp;mut self is short for self: &amp;amp;mut Self&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;update_price&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new_price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;new_price&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Price of {} {} has increased to ${}/-"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.price&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Struct has function too
&lt;/h3&gt;

&lt;p&gt;Rust also allow us to create &lt;strong&gt;associated functions&lt;/strong&gt;, they are pretty much like &lt;code&gt;method&lt;/code&gt;, however they don’t take &lt;code&gt;&amp;amp;self&lt;/code&gt; as argument. They are mostly used to create initialize the new instance of custom datatype, like a &lt;strong&gt;constructors&lt;/strong&gt; in other object oriented languages.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;Car&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Associated Function to create new instance&lt;/span&gt;
    &lt;span class="c1"&gt;// It is like a constructor in other languages&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;new_car&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Car&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Car&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;year&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2022&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;70000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;There is something call &lt;strong&gt;Struct Tuple&lt;/strong&gt;, it is a combination of &lt;strong&gt;Struct&lt;/strong&gt; and &lt;strong&gt;Tuple&lt;/strong&gt;. In &lt;code&gt;Rust&lt;/code&gt; &lt;strong&gt;Struct Tuple’s&lt;/strong&gt; are defined similarly as &lt;strong&gt;Struct&lt;/strong&gt; but they don’t have any named field. It is usually deployed to make a custom type with mixed primary datatypes, however don’t need field to be named. Something like &lt;code&gt;struct CarFeatures(4, "electric", "falcon doors")&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So this is how the whole code looks like&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Struct Tuple&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nf"&gt;CarFeatures&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;new_car&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Car&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new_car&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Runner"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Tesla Model Y"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="c1"&gt;// Accessing fields using dot notation&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Car Name: {}, Model: {}, Year: {}, Price: ${}/-"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new_car&lt;/span&gt;&lt;span class="py"&gt;.name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new_car&lt;/span&gt;&lt;span class="py"&gt;.model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new_car&lt;/span&gt;&lt;span class="py"&gt;.year&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new_car&lt;/span&gt;&lt;span class="py"&gt;.price&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Calling the method using dot notation&lt;/span&gt;
    &lt;span class="n"&gt;new_car&lt;/span&gt;&lt;span class="nf"&gt;.update_price&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;75000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Using update syntax&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;second_car&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Car&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Beast"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Tesla Plaid"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;110000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="n"&gt;new_car&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// Need clone because Strings are heap allocated (move semantics)&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Car Name: {}, Model: {}, Year: {}, Price: ${}/-"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;second_car&lt;/span&gt;&lt;span class="py"&gt;.name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;second_car&lt;/span&gt;&lt;span class="py"&gt;.model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;second_car&lt;/span&gt;&lt;span class="py"&gt;.year&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;second_car&lt;/span&gt;&lt;span class="py"&gt;.price&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;second_car&lt;/span&gt;&lt;span class="nf"&gt;.update_price&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;135000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Car Name: Runner, Model: Tesla Model Y, Year: 2022, Price: &lt;span class="nv"&gt;$70000&lt;/span&gt;/-
Price of Tesla Model Y has increased to &lt;span class="nv"&gt;$75000&lt;/span&gt;/-
Car Name: Beast, Model: Tesla Plaid, Year: 2022, Price: &lt;span class="nv"&gt;$110000&lt;/span&gt;/-
Price of Tesla Plaid has increased to &lt;span class="nv"&gt;$135000&lt;/span&gt;/-
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Generic Types … Yay!!
&lt;/h3&gt;

&lt;p&gt;Rust is &lt;strong&gt;statically&lt;/strong&gt; type language so a defined &lt;code&gt;struct&lt;/code&gt;, &lt;code&gt;function&lt;/code&gt; or &lt;code&gt;method&lt;/code&gt; can only be used for it own defined variable data types. Which mean you might end up maintaining same code body for &lt;code&gt;struct&lt;/code&gt;, &lt;code&gt;function&lt;/code&gt; or &lt;code&gt;method&lt;/code&gt; with different data types. What if we can define &lt;code&gt;struct&lt;/code&gt;, &lt;code&gt;function&lt;/code&gt; or &lt;code&gt;method&lt;/code&gt; in such a way that we can use any data type with it. Enters…..&lt;strong&gt;Generic Type!!&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;cmp&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;PartialOrd&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;ops&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;AddAssign&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Struct with Generic Types&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Car&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;S&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;I&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;S&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;S&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;year&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;I&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;S&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;I&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Car&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;S&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;I&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AddAssign&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;Copy&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Display&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Method with Generic Types&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;update_price&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.price&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Price Updated: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.price&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Function with Generic Types&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;choose&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;PartialOrd&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;electric_per_unit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;gas_per_gallon&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;'static&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;electric_per_unit&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;gas_per_gallon&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s"&gt;"Electric"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s"&gt;"Gas"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Above we have struct &lt;code&gt;Car&lt;/code&gt; with generic type &lt;em&gt;(denoted using &lt;code&gt;&amp;lt;..&amp;gt;&lt;/code&gt;)&lt;/em&gt; &lt;code&gt;&amp;lt;S,I,T&amp;gt;&lt;/code&gt; which feeds the &lt;code&gt;type&lt;/code&gt; for struct fields. Similarly, a &lt;code&gt;impl&lt;/code&gt; block to define &lt;code&gt;new_car&lt;/code&gt; and &lt;code&gt;update_price&lt;/code&gt; &lt;strong&gt;methods&lt;/strong&gt;. They are also using generic types. Lastly, a function choose with &lt;code&gt;generics&lt;/code&gt;, used to get confirm for the right choice based on &lt;code&gt;electric_per_unit&lt;/code&gt; and &lt;code&gt;gas_per_gallon&lt;/code&gt; price constraints.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Don’t worry about the &lt;code&gt;traits&lt;/code&gt; like &lt;code&gt;std::cmp::PartialOrd&lt;/code&gt; and &lt;code&gt;std::ops::AddAssign&lt;/code&gt; for now. I will have separate blog explaining them. For now, we need them because &lt;code&gt;rust&lt;/code&gt; complier doesn’t know what kind of data types &lt;code&gt;generics&lt;/code&gt; will have to perform &lt;strong&gt;&lt;code&gt;comparison&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;addition&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Box Datatype
&lt;/h3&gt;

&lt;p&gt;One more thing I want touch is the &lt;strong&gt;Box datatype&lt;/strong&gt; in rust . &lt;strong&gt;Box&lt;/strong&gt; datatype are usually used to put the data in &lt;strong&gt;heap&lt;/strong&gt; instead of &lt;strong&gt;stack&lt;/strong&gt;. In simple words &lt;strong&gt;stack&lt;/strong&gt; are usually small in size and when you are storing data which can be large in size like a &lt;code&gt;trait&lt;/code&gt; or &lt;code&gt;struct&lt;/code&gt; &lt;em&gt;(combination of different datatypes and sizes)&lt;/em&gt;, you might want to store them in &lt;strong&gt;heap&lt;/strong&gt; and have reference of that stored in &lt;strong&gt;stack&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: If you are making the data to be &lt;strong&gt;boxed&lt;/strong&gt;, means moving it from &lt;strong&gt;stack&lt;/strong&gt; to &lt;strong&gt;heap&lt;/strong&gt; using &lt;code&gt;box datatype&lt;/code&gt;. It performs the &lt;strong&gt;move&lt;/strong&gt; operation, not &lt;strong&gt;copy&lt;/strong&gt;, so previous location in &lt;strong&gt;stack&lt;/strong&gt; gets &lt;strong&gt;de-allocated&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;car&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Car&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Model X"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;120000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="c1"&gt;// ... other fields&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"I bought Model X in 2021 for $120000, it is an electric Vehicle"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Market prediction is that Model X in 2022 will be for $140000"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"BEFORE BOXING, Car struct data size is {} bytes in Stack"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;mem&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;size_of_val&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;car&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

    &lt;span class="c1"&gt;// ... logic for price change ...&lt;/span&gt;

    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"BOXING the data....."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;boxed_car&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Box&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;car&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"AFTER BOXING, Car struct data size is {} bytes in Stack"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;mem&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;size_of_val&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;boxed_car&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Car struct data size is {} bytes in Heap, because we are using de-referencing operator `*` to access the data"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;mem&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;size_of_val&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;*&lt;/span&gt;&lt;span class="n"&gt;boxed_car&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;I bought Model X &lt;span class="k"&gt;in &lt;/span&gt;2021 &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nv"&gt;$120000&lt;/span&gt;, it is an electric Vehicle
Market prediction is that Model X &lt;span class="k"&gt;in &lt;/span&gt;2022 will be &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nv"&gt;$140000&lt;/span&gt;
BEFORE BOXING, Car struct data size is 56 bytes &lt;span class="k"&gt;in &lt;/span&gt;Stack
Price Changed: &lt;span class="k"&gt;in &lt;/span&gt;Inventory aka Stack, Now Price is &lt;span class="nv"&gt;$140000&lt;/span&gt;
BOXING the data.....
AFTER BOXING, Car struct data size is 8 bytes &lt;span class="k"&gt;in &lt;/span&gt;Stack
Car struct data size is 56 bytes &lt;span class="k"&gt;in &lt;/span&gt;Heap, because we are using de-referencing operator &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt; to access the data
DATA AFTER BOXING: Model X Price: &lt;span class="nv"&gt;$140000&lt;/span&gt; Fuel Type: electric
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see that when I used the &lt;code&gt;boxed_car&lt;/code&gt; variable as &lt;code&gt;box&lt;/code&gt; type data got moved from &lt;strong&gt;stack&lt;/strong&gt; to &lt;strong&gt;heap&lt;/strong&gt;. Now, &lt;strong&gt;stack&lt;/strong&gt; only contains the reference of the data &lt;em&gt;(hence &lt;code&gt;8&lt;/code&gt; bytes)&lt;/em&gt; and actual data is in &lt;strong&gt;heap&lt;/strong&gt; &lt;em&gt;(hence &lt;code&gt;56&lt;/code&gt; bytes)&lt;/em&gt;&lt;br&gt;
and we are using &lt;code&gt;&amp;amp;&lt;/code&gt; for the reference for the data in &lt;strong&gt;stack&lt;/strong&gt; and de-referencing operator &lt;code&gt;*&lt;/code&gt; to fetch the size of the data in &lt;strong&gt;heap&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Hope this explains some of the internal and usage of &lt;code&gt;structs&lt;/code&gt; and &lt;code&gt;generics&lt;/code&gt; in &lt;code&gt;Rust&lt;/code&gt;. I will have more write-ups coming for other important concepts of &lt;code&gt;Rust&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Happy Programming!!
&lt;/h3&gt;

</description>
      <category>rust</category>
      <category>programming</category>
    </item>
    <item>
      <title>The Matryoshka Dolls of Modern Networking: A Technical Evolution</title>
      <dc:creator>Satyajit Roy</dc:creator>
      <pubDate>Tue, 06 Jan 2026 16:58:20 +0000</pubDate>
      <link>https://forem.com/deadlock/the-matryoshka-dolls-of-modern-networking-a-technical-evolution-34c8</link>
      <guid>https://forem.com/deadlock/the-matryoshka-dolls-of-modern-networking-a-technical-evolution-34c8</guid>
      <description>&lt;h1&gt;
  
  
  The Matryoshka Dolls of Modern Networking: A Technical Evolution
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Introduction: The Internet is a Lie
&lt;/h2&gt;

&lt;p&gt;If you think the internet is a flat, happy place where your computer talks directly to a server, I have bad news for you: &lt;strong&gt;The internet is a lie&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Modern networking is fundamentally a history of deception. We want the logical freedom to move things around without the physical reality of moving cables. To achieve this, we turned to the &lt;em&gt;&lt;strong&gt;"Matryoshka Doll"&lt;/strong&gt;&lt;/em&gt; strategy (Russian nesting dolls). We take a packet, wrap it inside another packet, and sometimes when we are feeling particularly chaotic wrap that inside a third packet.&lt;/p&gt;

&lt;p&gt;It’s an illusion of infinite connectivity built on top of a physical reality that is rigid, hierarchical, and frankly, a pain in the ass to wire.&lt;/p&gt;

&lt;p&gt;Today, we are going to look at how we went from manual spreadsheets to the hyper-programmable, kernel-bypassing insanity that runs the cloud today.&lt;/p&gt;




&lt;h2&gt;
  
  
  Part 1: A Brief History of "Why We Did This"
&lt;/h2&gt;

&lt;p&gt;To understand why we complicate things with overlays, you have to understand the nightmare we were waking up from.&lt;/p&gt;

&lt;h4&gt;
  
  
  The Villain: The Number 4,096
&lt;/h4&gt;

&lt;p&gt;In the old days (pre-2010), if you wanted to separate two departments (say, HR and Engineering), you used a VLAN (Virtual Local Area Network).The IEEE 802.1Q standard gave us a &lt;code&gt;12-bit&lt;/code&gt; identifier for VLANs. If you do the math &lt;code&gt;(2^12)&lt;/code&gt;, that gives you &lt;strong&gt;4,096&lt;/strong&gt; possible segments.For a university campus? Fine. For a cloud provider trying to host 1,000,000 customers? &lt;strong&gt;Catastrophic&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# The mathematical impossibility of early cloud networking
&lt;/span&gt;&lt;span class="n"&gt;max_vlans&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4094&lt;/span&gt;
&lt;span class="n"&gt;cloud_tenants_needed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1000000&lt;/span&gt; 
&lt;span class="n"&gt;coverage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_vlans&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;cloud_tenants_needed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;We can only support &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;coverage&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;% of our customers.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;span class="c1"&gt;# Result: The CEO fires everyone.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  The $500,000 Rack Problem
&lt;/h4&gt;

&lt;p&gt;Before overlays, an IP address wasn't just a number; it was a physical location. IP &lt;code&gt;10.1.1.5&lt;/code&gt; meant "Row 4, Rack 2, Switch Port 12."&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvlmnl6y8o6epdbx49g7c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvlmnl6y8o6epdbx49g7c.png" alt="VLAN Exhaustion" width="800" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you wanted to move a Virtual Machine to a different server with a different subnet, you had to change its IP address. This broke the application. The alternative? Network engineers physically rewiring switches to extend Layer 2 domains across the data center. This resulted in "Spanning Tree" loops that would occasionally take down the entire banking sector for an afternoon.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;We needed a way to let the logical network (the VM) float above the physical network (the cables). Enter the Overlay.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Part 2: The Modern Era (What We Actually Use)
&lt;/h2&gt;

&lt;p&gt;We stopped trying to fix the physical network and decided to just hide it. Today, almost every packet you send in the cloud is encapsulated. Let's look at the two heavyweights running the world right now.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. EVPN-VXLAN: The Enterprise Workhorse
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2rczmqhyzxk7pv9wzsmo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2rczmqhyzxk7pv9wzsmo.png" alt="EVPN+VXLAN" width="800" height="436"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;&lt;strong&gt;Used by:&lt;/strong&gt; 80% of Fortune 500 Data Centers, Banks, Telecoms.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;VXLAN&lt;/code&gt; (Virtual Extensible LAN) solved the "&lt;code&gt;4,096&lt;/code&gt; problem" by giving us a 24-bit ID. That’s &lt;strong&gt;16 million&lt;/strong&gt; segments. Enough for everyone to have their own private party.&lt;/p&gt;

&lt;p&gt;But &lt;code&gt;VXLAN&lt;/code&gt; had a dumb control plane. It used "Flood and Learn" essentially shouting, "WHO HAS MAC ADDRESS &lt;code&gt;AA:BB:CC?&lt;/code&gt;" to every switch in the building.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Fix:&lt;/strong&gt; We married &lt;code&gt;VXLAN&lt;/code&gt; to &lt;code&gt;BGP EVPN&lt;/code&gt;. Instead of shouting, switches now whisper to each other using BGP (the protocol that runs the internet).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Switch A&lt;/strong&gt;: "Hey, just so you know, I am hosting the HR Web Server now."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Switch B&lt;/strong&gt;: "Cool, I'll update my routing table. Thanks."&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This eliminated the flooding and made the network stable enough for JP Morgan to trade billions of dollars on it.&lt;/p&gt;
&lt;h3&gt;
  
  
  2. Geneve + eBPF: The Cool Cloud Kids
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu5zjhvze062sgqfudoe0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu5zjhvze062sgqfudoe0.png" alt="Geneve + eBPF" width="800" height="436"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;&lt;strong&gt;Used by:&lt;/strong&gt; Kubernetes (Cilium), AWS (Nitro), Service Meshes.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;VXLAN is great, but its header is fixed. You can't add notes to it. Modern cloud apps need to say things like, &lt;em&gt;"This packet is from the Frontend, it has a Security Clearance of Level 5, and it prefers to avoid the slow router."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Fix:&lt;/strong&gt; Enter &lt;strong&gt;Geneve&lt;/strong&gt; (Generic Network Virtualization Encapsulation). It has a variable-length header, meaning we can shove metadata into the packet itself. Combined with &lt;strong&gt;eBPF&lt;/strong&gt; (extended Berkeley Packet Filter), we can now program the Linux kernel to read these headers and make decisions before the packet even hits the heavy parts of the Operating System.&lt;/p&gt;
&lt;h3&gt;
  
  
  3. AWS Nitro (The Hardware Way)
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fan32x586bdebnnoz4vgg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fan32x586bdebnnoz4vgg.png" width="800" height="427"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;&lt;strong&gt;Used by:&lt;/strong&gt; AWS (obviously), and copied by everyone else (IPUs/DPUs).&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;While Spotify and Kubernetes developers were busy optimizing software with eBPF to save CPU cycles, Amazon took a different approach: &lt;strong&gt;They just built better hardware&lt;/strong&gt;. The &lt;strong&gt;AWS Nitro System&lt;/strong&gt; solves the "Matryoshka Tax" by cheating.&lt;/p&gt;
&lt;h4&gt;
  
  
  &lt;strong&gt;How It Works:&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Amazon realized that if the main CPU has to spend 20% of its time wrapping packets in Geneve headers, the customer gets angry because they are paying for a 100% CPU and getting 80%. So, they physically ripped the virtualization logic off the motherboard and put it on a separate card (the Nitro Card).  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Main CPU:&lt;/strong&gt; Does nothing but run your code
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Nitro Card:&lt;/strong&gt; Handles the VPC networking, encryption, storage, and security groups.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Impact:&lt;/strong&gt; You get "Bare Metal" performance on a virtual machine. The encapsulation still happens—the Matryoshka doll is still there but it’s being assembled by a dedicated robot (ASIC) on the side, not by your main CPU.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Why AWS Loves Geneve:&lt;/strong&gt; AWS switched from VXLAN to Geneve specifically for this hardware. The flexible "Type-Length-Value" (TLV) headers allow the Nitro card to inject metadata that VXLAN couldn't handle, such as:&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flow Cookies:&lt;/strong&gt; To ensure your session doesn't break when a load balancer scales.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;VPC IDs:&lt;/strong&gt; Ensuring absolute isolation at the hardware level.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  4. Disaggregated Core: The "IKEA" Router
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjwg7hvebrivh3yni92z2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjwg7hvebrivh3yni92z2.png" width="800" height="436"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;&lt;strong&gt;Used by:&lt;/strong&gt; AT&amp;amp;T (DriveNets), Major ISPs, Hyperscalers.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;For decades, if you wanted to be an ISP like AT&amp;amp;T, you had to buy a "Router Chassis." This was essentially a refrigerator-sized metal box that cost more than a house, sold by a vendor who locked you into their proprietary ecosystem forever. If you needed more ports? You had to buy a new fridge.&lt;/p&gt;
&lt;h4&gt;
  
  
  &lt;strong&gt;The Revolution:&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;The "Lego" Approach (DDC)&lt;/strong&gt; AT&amp;amp;T looked at these giant metal fridges and said, "No thanks." They moved to &lt;strong&gt;Distributed Disaggregated Chassis (DDC)&lt;/strong&gt; architecture using DriveNets.&lt;/p&gt;

&lt;p&gt;Instead of one giant proprietary machine, they built a "router" out of standard, cheap white-box switches connected by cables.&lt;/p&gt;
&lt;h4&gt;
  
  
  &lt;strong&gt;The Architecture (Deconstructed):&lt;/strong&gt; They broke the router into three generic pieces, like a kit of parts:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Brain (Control Plane):&lt;/strong&gt; Standard x86 servers running the routing software in containers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Ports (NCPs):&lt;/strong&gt; "Pizza Box" switches (using Broadcom Jericho chips) that plug into the outside world.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Fabric (NCFs):&lt;/strong&gt; "Pizza Box" switches (using Broadcom Ramon chips) that just glue the other boxes together.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  &lt;strong&gt;Why It Wins:&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;It acts exactly like &lt;strong&gt;Kubernetes for Networking&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Need more bandwidth?&lt;/strong&gt; Don't buy a new chassis. Just plug in another "Pizza Box" (NCP).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Need more throughput?&lt;/strong&gt; Plug in another Fabric box (NCF).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scale:&lt;/strong&gt; This system scales to &lt;strong&gt;192 Tbps&lt;/strong&gt;. That is a "distributed cloud of white boxes" pretending to be a router.&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  Part 3: The Anatomy of a Modern Packet
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;(Or: Why your MTU settings are ruining your life)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This is where the "Matryoshka Doll" analogy gets real. If you capture a packet flying through a Kubernetes cluster or AWS VPC, you are looking at a Russian nesting doll of headers.&lt;/p&gt;

&lt;p&gt;Let's dissect a &lt;strong&gt;Geneve&lt;/strong&gt; packet byte-by-byte.&lt;/p&gt;
&lt;h3&gt;
  
  
  The "Doll" Breakdown
&lt;/h3&gt;
&lt;h4&gt;
  
  
  Layer 1: The Delivery Truck (The Underlay)
&lt;/h4&gt;

&lt;p&gt;This gets the packet from Physical Server A to Physical Server B. The switches only look at this.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Outer Ethernet (14 Bytes):&lt;/strong&gt; Source and Destination MAC of the physical servers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Outer IP (20 Bytes):&lt;/strong&gt; Source and Destination IP of the physical servers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Outer UDP (8 Bytes):&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SRC Port:&lt;/strong&gt; A calculated hash (this creates entropy so we can use multiple cables at once).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DST Port:&lt;/strong&gt; 6081 ( The port for Geneve).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  Layer 2: The Magic Wrapper (The Overlay)
&lt;/h4&gt;

&lt;p&gt;&lt;em&gt;This is where the software-defined magic happens.&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Geneve Base Header (8 Bytes):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;VNI (24-bit):&lt;/strong&gt; The Tenant ID. This ensures Coke's data doesn't leak into Pepsi's network.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Geneve Options (Variable, ~12-20 Bytes):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;This is the killer feature&lt;/em&gt;. eBPF inserts &lt;strong&gt;Metadata&lt;/strong&gt; here.&lt;/li&gt;
&lt;li&gt;Example: &lt;code&gt;SecurityID=45912&lt;/code&gt;. The destination firewall doesn't check IPs anymore; it just checks this ID. It's &lt;code&gt;O(1)&lt;/code&gt; complexity (aka: blazing fast).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  The Math: Why Fragmentation Kills Performance
&lt;/h4&gt;

&lt;p&gt;If your application sends a standard max-size packet (1500 bytes), look what happens when we wrap it:&lt;/p&gt;

&lt;p&gt;Here’s the encapsulation overhead breakdown in a clean table format:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Layer&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Size Added&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Running Total&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Your App Payload&lt;/td&gt;
&lt;td&gt;1500 bytes&lt;/td&gt;
&lt;td&gt;1500&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Geneve Base&lt;/td&gt;
&lt;td&gt;+8 bytes&lt;/td&gt;
&lt;td&gt;1508&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Geneve TLV Options&lt;/td&gt;
&lt;td&gt;+12 bytes (average)&lt;/td&gt;
&lt;td&gt;1520&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Outer UDP&lt;/td&gt;
&lt;td&gt;+8 bytes&lt;/td&gt;
&lt;td&gt;1528&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Outer IP&lt;/td&gt;
&lt;td&gt;+20 bytes&lt;/td&gt;
&lt;td&gt;1548&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Outer Ethernet&lt;/td&gt;
&lt;td&gt;+14 bytes&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1562 bytes&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;The Problem:&lt;/strong&gt; The standard physical internet cable has an MTU (Maximum Transmission Unit) of &lt;strong&gt;1500 bytes&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Result:&lt;/strong&gt; Your 1562-byte packet hits the switch and gets dropped or fragmented (chopped into two). Fragmentation destroys CPU performance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Solution:&lt;/strong&gt; You must enable &lt;strong&gt;Jumbo Frames (MTU 9000)&lt;/strong&gt; on your physical switches. If you build a cloud without Jumbo Frames, you are trying to fit an elephant into a Mini Cooper.&lt;/p&gt;


&lt;h2&gt;
  
  
  Part 4: The Future - Where Are We Going?
&lt;/h2&gt;

&lt;p&gt;We are moving away from "Smart Software on Dumb Hardware" to "Genius Hardware."&lt;/p&gt;
&lt;h3&gt;
  
  
  1. Identity over IP
&lt;/h3&gt;

&lt;p&gt;For 40 years, we allowed traffic based on Location (Source IP). "Allow &lt;code&gt;10.0.0.5&lt;/code&gt; to talk to &lt;code&gt;10.0.0.6&lt;/code&gt;." This is dumb because IPs change. The future is &lt;strong&gt;Metadata&lt;/strong&gt;. The packet carries its own passport in the Geneve header. "Allow 'Frontend-Service' to talk to 'Backend-Database'." The network enforces this policy at line rate. We don't care what the IP is anymore.&lt;/p&gt;
&lt;h3&gt;
  
  
  2. The Rise of the DPU (SmartNICs)
&lt;/h3&gt;

&lt;p&gt;The "Tax" of the Matryoshka doll is CPU usage. Wrapping and unwrapping packets takes cycles away from your app. We are now moving this logic to &lt;strong&gt;DPUs&lt;/strong&gt; (Data Processing Units) like NVIDIA BlueField. The server's CPU doesn't even know encapsulation is happening. The Network Card (NIC) handles the encryption, the Geneve wrapping, and the firewalling. It is a "free lunch" for application performance.&lt;/p&gt;
&lt;h3&gt;
  
  
  3. Quantum-Safe Overlays
&lt;/h3&gt;

&lt;p&gt;Quantum computers will eventually break our current encryption. The beauty of flexible overlays like Geneve is that we don't need to rip out cables to fix this. We just add a new "Option TLV" to the header containing Quantum-Resistant keys. We can upgrade the security of the entire internet just by changing the packet wrapper.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Conceptualizing Hybrid Security in Geneve
&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;QuantumSafeOverlay&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;encrypt_packet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;packet&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# We carry TWO locks on the packet:
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;GenevePacket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;vni&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;packet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;vni&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="c1"&gt;# 1. The lock we trust today (Fast, Standard)
&lt;/span&gt;                &lt;span class="nc"&gt;TraditionalEncryption&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;RSA_encrypt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;packet&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;

                &lt;span class="c1"&gt;# 2. The lock we need for tomorrow (Quantum-Resistant)
&lt;/span&gt;                &lt;span class="nc"&gt;QuantumEncryption&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Kyber_encrypt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;packet&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="n"&gt;inner_packet&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;packet&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Conclusion: The Evolution Validated
&lt;/h2&gt;

&lt;p&gt;The "Matryoshka Dolls" of modern networking aren't just a neat trick; they are the only reason the internet hasn't collapsed under its own weight. We have spent 25 years moving from physical cables to virtual lies, and we have the receipts to prove it.&lt;/p&gt;

&lt;p&gt;If you scrolled to the bottom just for the summary, here is a quarter century of network engineering pain condensed into a grid:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Era&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Archetype&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Representative&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;The Tech&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;The Result&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;1995–2010&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Physical (Single Doll)&lt;/td&gt;
&lt;td&gt;AOL&lt;/td&gt;
&lt;td&gt;VLANs&lt;/td&gt;
&lt;td&gt;"Rack Rewire" nightmares; engineers crying in server rooms.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;2010–2015&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Virtualization (Dual Doll)&lt;/td&gt;
&lt;td&gt;eBay&lt;/td&gt;
&lt;td&gt;VXLAN / OpenStack&lt;/td&gt;
&lt;td&gt;16M segments; we stopped caring about cables.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;2015–2018&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Scale Crisis (Heavy Doll)&lt;/td&gt;
&lt;td&gt;Spotify&lt;/td&gt;
&lt;td&gt;Kubernetes / CNI&lt;/td&gt;
&lt;td&gt;40% CPU overhead because we got greedy with encapsulation.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;2018–2022&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Optimization (Smart Doll)&lt;/td&gt;
&lt;td&gt;Facebook&lt;/td&gt;
&lt;td&gt;eBPF / XDP&lt;/td&gt;
&lt;td&gt;10× performance; we taught the kernel to skip the boring parts.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;2022–Present&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Hardware Offload&lt;/td&gt;
&lt;td&gt;AWS&lt;/td&gt;
&lt;td&gt;Nitro / Geneve&lt;/td&gt;
&lt;td&gt;"Bare metal" speeds; the hardware finally caught up to our software.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  The Bottom Line
&lt;/h3&gt;

&lt;p&gt;For decades, we had to choose between &lt;strong&gt;Flexibility&lt;/strong&gt; (Overlays) and &lt;strong&gt;Performance&lt;/strong&gt; (Bare Metal).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you wanted speed, you dealt with rigid physical switches.&lt;/li&gt;
&lt;li&gt;If you wanted agility, you paid a "CPU Tax" to wrap packets in software.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;That era is over.&lt;/strong&gt; With eBPF optimization and hardware offloads like AWS Nitro, we have successfully paid down the technical debt. We can now wrap packets in three layers of metadata, route them based on identity rather than IP, and encrypt them against quantum computers all without the application feeling a thing.&lt;/p&gt;

&lt;p&gt;The network has successfully abstracted itself. It is no longer a set of pipes; it is a programmable substrate that is just as fluid as the code running on top of it.&lt;/p&gt;

&lt;h3&gt;
  
  
  See the Matrix Yourself
&lt;/h3&gt;

&lt;p&gt;Don't take my word for it. If you have a Kubernetes cluster running Cilium, you can watch the dolls being assembled in real-time. Run this on any node:&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
bash
# 1. See the eBPF programs hijacking your traffic
bpftool prog show

# 2. Watch the overlay traffic fly by (Standard Port 4789 or Geneve 6081)
tcpdump -i any udp port 4789 or udp port 6081 -vv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>concepts</category>
      <category>overlay</category>
      <category>network</category>
    </item>
    <item>
      <title>[Concept] Functions 101- Golang</title>
      <dc:creator>Satyajit Roy</dc:creator>
      <pubDate>Sat, 03 Jan 2026 17:43:59 +0000</pubDate>
      <link>https://forem.com/deadlock/concept-functions-101-golang-1ej4</link>
      <guid>https://forem.com/deadlock/concept-functions-101-golang-1ej4</guid>
      <description>&lt;p&gt;&lt;strong&gt;Functions&lt;/strong&gt; are the building blocks of &lt;code&gt;procedural programming&lt;/code&gt;. They help in creating modular code where a big job can be segmented into small pieces of code and might have been written by different people separated by both time and space. In fact, function is one kind of &lt;strong&gt;first-class citizen&lt;/strong&gt; types in &lt;code&gt;Go&lt;/code&gt;. In other words, we can use &lt;em&gt;functions as values&lt;/em&gt;. Although &lt;code&gt;Go&lt;/code&gt; is a static language, &lt;code&gt;Go&lt;/code&gt; functions are very flexible. The feeling of using Go functions is much like using many dynamic languages. &lt;em&gt;A function is a mapping of zero or more input parameters to zero or more output parameters.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flm8nrpmiw7wlmo6eqrwy.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flm8nrpmiw7wlmo6eqrwy.jpg" alt="Go Functions" width="800" height="235"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The advantages of using functions are:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reducing duplication of code&lt;/li&gt;
&lt;li&gt;Decomposing complex problems into simpler pieces&lt;/li&gt;
&lt;li&gt;Improving clarity of the code&lt;/li&gt;
&lt;li&gt;Reuse of code&lt;/li&gt;
&lt;li&gt;Information hiding&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Special Functions
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Golang&lt;/strong&gt; has 2 special functions &lt;em&gt;&lt;code&gt;main()&lt;/code&gt;&lt;/em&gt; and &lt;em&gt;&lt;code&gt;init()&lt;/code&gt;&lt;/em&gt; . They have some special responsibilities assigned to them&lt;/p&gt;

&lt;h3&gt;
  
  
  The main() and init() function
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;main&lt;/strong&gt; package is a special package which is used with the programs that are executable and this package contains &lt;code&gt;main()&lt;/code&gt; function. The &lt;code&gt;main()&lt;/code&gt; function is a special type of function and it is the entry point of the executable programs. It does not take any argument nor return anything. Go automatically call &lt;code&gt;main()&lt;/code&gt; function, so there is no need to call &lt;code&gt;main()&lt;/code&gt; function explicitly and every executable program must contain single main package and &lt;code&gt;main()&lt;/code&gt; function. The &lt;code&gt;init()&lt;/code&gt; function is declared implicitly and we cannot reference it from anywhere in the code, but we are allowed to create multiple &lt;code&gt;init()&lt;/code&gt; functions in the same program. The init() function can be incredibly powerful and compared to some other languages, is a lot easier to use within your Go programs. These &lt;code&gt;init()&lt;/code&gt; functions can be used within a package block and regardless of how many times that package is imported, the &lt;code&gt;init()&lt;/code&gt; function will only be called once.&lt;/p&gt;




&lt;h3&gt;
  
  
  Function with returns (none, single value or multiple values)
&lt;/h3&gt;

&lt;p&gt;We declare a function using the func keyword. A function has a name, a list of comma-separated input parameters along with their &lt;code&gt;types&lt;/code&gt;, the &lt;strong&gt;result type(s)&lt;/strong&gt;, and a &lt;strong&gt;body&lt;/strong&gt;.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func function_name(Parameter-list)(Return_type){
    // function body.....
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Let say we have function &lt;em&gt;&lt;code&gt;repeatWord()&lt;/code&gt;&lt;/em&gt; which return nothing, so &lt;em&gt;&lt;code&gt;main()&lt;/code&gt;&lt;/em&gt; just executes the &lt;em&gt;&lt;code&gt;repeatWord()&lt;/code&gt;&lt;/em&gt; which take a string and int as arguments and prints. Nothing to return&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl43mizmyia3d8ejzrzxo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl43mizmyia3d8ejzrzxo.png" alt="Repeat Word function" width="800" height="483"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we change the function to return more than one values and also return if there are any errors.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffqp8axs7cede7zuqhqw5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffqp8axs7cede7zuqhqw5.png" alt="Repeat Word function with error" width="800" height="631"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You see if the condition below matches, function return &lt;em&gt;&lt;code&gt;error&lt;/code&gt;&lt;/em&gt; using &lt;a href="https://pkg.go.dev/fmt#Errorf" rel="noopener noreferrer"&gt;fmt.Errorf&lt;/a&gt; else it send a &lt;code&gt;nil&lt;/code&gt; in place of error.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if len(s) &amp;lt;= 0 {
    return "", len(s), fmt.Errorf("Length of string can't less than euql zero")
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Overall &lt;em&gt;&lt;code&gt;repeatWord()&lt;/code&gt;&lt;/em&gt; returns multiple value, along side with error.&lt;/p&gt;




&lt;h3&gt;
  
  
  Function as Parameter
&lt;/h3&gt;

&lt;p&gt;A Go function can be passed to other functions as a &lt;em&gt;&lt;strong&gt;parameter&lt;/strong&gt;&lt;/em&gt;. Such a function is called a &lt;em&gt;higher-order&lt;/em&gt; function.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffdcz3x8zzes6721yx36z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffdcz3x8zzes6721yx36z.png" alt="Function as Parameter" width="800" height="1069"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here we have simple action functions called &lt;em&gt;&lt;code&gt;repeatWord()&lt;/code&gt;&lt;/em&gt; and &lt;em&gt;&lt;code&gt;revertWord()&lt;/code&gt;&lt;/em&gt;. Also we have function called &lt;em&gt;&lt;code&gt;applyFunction()&lt;/code&gt;&lt;/em&gt; which take a function and &lt;code&gt;string&lt;/code&gt; as parameters.&lt;/p&gt;




&lt;h2&gt;
  
  
  Function as custom type
&lt;/h2&gt;

&lt;p&gt;Go allows to create reusable functions signatures with the &lt;code&gt;type&lt;/code&gt; keyword. They have the same number of arguments with each argument is the same type. They have the same number of return values and each return value is of the same type&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo4q6e9prbglm12ffmlg8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo4q6e9prbglm12ffmlg8.png" alt="Function as custom type" width="800" height="437"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With the &lt;code&gt;type&lt;/code&gt; keyword, we create a function type which accepts one &lt;code&gt;string&lt;/code&gt; parameter and returns a &lt;code&gt;string&lt;/code&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  Function as closure aka anonymous function
&lt;/h3&gt;

&lt;p&gt;It is possible to create functions inside of functions. Go supports &lt;strong&gt;&lt;a href="https://en.wikipedia.org/wiki/Anonymous_function" rel="noopener noreferrer"&gt;anonymous functions&lt;/a&gt;&lt;/strong&gt;, which can form &lt;strong&gt;&lt;a href="https://en.wikipedia.org/wiki/Closure_(computer_science)" rel="noopener noreferrer"&gt;closures&lt;/a&gt;&lt;/strong&gt;. &lt;strong&gt;Anonymous&lt;/strong&gt; functions are useful when you want to define a function inline without having to name it. &lt;strong&gt;Closure&lt;/strong&gt; is a nested function that helps us access the outer function’s variables even after the outer function is closed&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvt3866ho3oywisze4vts.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvt3866ho3oywisze4vts.png" alt="closure aka anonymous function" width="800" height="478"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Function Higher Order
&lt;/h3&gt;

&lt;p&gt;Higher order functions are functions that operate on other functions, either by taking them as arguments or by returning them.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxuac2d6ax9aax1gehzd7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxuac2d6ax9aax1gehzd7.png" alt="Function Higher Order" width="800" height="468"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Above you can see that &lt;em&gt;&lt;code&gt;concatStringUsingFunctionOfHigerOrder()&lt;/code&gt;&lt;/em&gt; returns another function, which again return another function. It is kind of &lt;a href="https://en.wikipedia.org/wiki/Spaghetti_code" rel="noopener noreferrer"&gt;Spaghetti Code&lt;/a&gt; in my opinion. However above is just an example, I would avoid writing code like this.&lt;/p&gt;

&lt;p&gt;Hope this provide little bit more clarity on &lt;code&gt;function&lt;/code&gt; and way they can be used in &lt;code&gt;Golang&lt;/code&gt; program. Above examples can be found here: &lt;strong&gt;&lt;a href="https://github.com/kodelint/go-functions-101" rel="noopener noreferrer"&gt;go-functions-101&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Happy Coding!!
&lt;/h2&gt;

</description>
      <category>concepts</category>
      <category>go</category>
      <category>programming</category>
    </item>
    <item>
      <title>[Concept] And I thought I knew DNS</title>
      <dc:creator>Satyajit Roy</dc:creator>
      <pubDate>Sat, 03 Jan 2026 17:39:42 +0000</pubDate>
      <link>https://forem.com/deadlock/concept-and-i-thought-i-knew-dns-2kbe</link>
      <guid>https://forem.com/deadlock/concept-and-i-thought-i-knew-dns-2kbe</guid>
      <description>&lt;p&gt;Yeah, I know. We all know, use &lt;strong&gt;DNS&lt;/strong&gt; and know how they work. There are numerous of articles and blog explaining how &lt;strong&gt;DNS&lt;/strong&gt; works. However as I dig more about it I found more information which were, frankly speaking, new to me. So I thought I would write about it.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;I know that there are so many excellent blogs and articles about DNS. However, I encourage you to give this a try, hopefully you might find something new in it.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5m5z99xox7rw88cdg22b.png" alt="DNS" width="600" height="314"&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  History
&lt;/h3&gt;

&lt;p&gt;Why &lt;strong&gt;DNS&lt;/strong&gt; was created ? Believe it or not before &lt;strong&gt;DNS&lt;/strong&gt; the mapping were use to copy over network from computer to computer for the name based communication. So, each site maintained a &lt;strong&gt;HOSTS.TXT&lt;/strong&gt; file that provided a mapping between host names and network addresses in a set of simple text records that could be easily read by a person or program. It wasn’t long before people realized that keeping multiple copies of the hosts file was inefficient and error-prone. So it was decided on &lt;a href="http://www.rfc-editor.org/rfc/rfc623.txt" rel="noopener noreferrer"&gt;RFC 623&lt;/a&gt; and &lt;a href="http://www.rfc-editor.org/rfc/rfc625.txt" rel="noopener noreferrer"&gt;RFC 625&lt;/a&gt;, &lt;a href="http://www.sri.com/" rel="noopener noreferrer"&gt;Stanford Research Institute&lt;/a&gt; Network Information Center (NIC) would serve as the official source of the master hosts file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://internethalloffame.org/inductees/paul-mockapetris" rel="noopener noreferrer"&gt;Paul Mockapetris&lt;/a&gt; and his team had the mission to create a friendlier for use network, where people wouldn’t need to remember the IP address of every computer. He suggested that host names should include:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Name&lt;/strong&gt; — for example, &lt;strong&gt;IBM&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Categories/Purpose&lt;/strong&gt; — for example, .com — for &lt;strong&gt;com&lt;/strong&gt;mercial purposes&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;After a year, the categories (or generic Top-Level Domains — gTLDs) were created. They included familiar extensions such as &lt;code&gt;.com&lt;/code&gt;, &lt;code&gt;.edu&lt;/code&gt;, &lt;code&gt;.net&lt;/code&gt;, &lt;code&gt;.org&lt;/code&gt;, &lt;code&gt;.int&lt;/code&gt;, &lt;code&gt;.gov&lt;/code&gt; and &lt;code&gt;.mil&lt;/code&gt;. Before the end of 1985, there were six new names with &lt;code&gt;.com&lt;/code&gt;. The first one ever registered, &lt;a href="https://symbolics.com/" rel="noopener noreferrer"&gt;Symbolics.com&lt;/a&gt;, still exists today.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Trivia Detail&lt;/strong&gt;: What is &lt;strong&gt;DNS Interceptors&lt;/strong&gt; ? &lt;strong&gt;DNS Interceptors&lt;/strong&gt; is used for optimizations, censorship, captive portal etc. Basically &lt;strong&gt;DNS&lt;/strong&gt; is you gateway to internet and by controlling that we can control queries and requests&lt;br&gt;
&lt;strong&gt;Trivia Detail&lt;/strong&gt;: About &lt;strong&gt;Privacy&lt;/strong&gt;. there is a &lt;strong&gt;(&lt;a href="https://datatracker.ietf.org/doc/html/rfc7816" rel="noopener noreferrer"&gt;RFC 7816&lt;/a&gt;)&lt;/strong&gt; called &lt;strong&gt;QNAME minimisation&lt;/strong&gt; &lt;em&gt;(Query Name Minimisation)&lt;/em&gt; to Improve Privacy, because DNS Resolver sends the whole query to the authoritative name server, the same outcome can be achieved with minimum information&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  OK, So how does DNS Work ?
&lt;/h3&gt;

&lt;p&gt;So, &lt;strong&gt;DNS&lt;/strong&gt; in nutshell is &lt;strong&gt;Global&lt;/strong&gt; &lt;strong&gt;Distributed Identifier DB&lt;/strong&gt;. It was created to replace the &lt;em&gt;static file&lt;/em&gt; like &lt;em&gt;&lt;code&gt;/etc/hosts&lt;/code&gt;&lt;/em&gt; file. So understand the distributed model of DNS DB, let’s try to trace it backwards&lt;/p&gt;

&lt;p&gt;Let say, we want to resolve &lt;a href="https://www.google.com/" rel="noopener noreferrer"&gt;www.google.com&lt;/a&gt; and as we already know&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fclwap1pjhly5u07kez1y.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fclwap1pjhly5u07kez1y.jpeg" alt="google.com" width="800" height="252"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, lets see the how the hierarchy works when we try to visit &lt;a href="https://google.com" rel="noopener noreferrer"&gt;https://google.com&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Browser will try to see if the answer is in it’s cache, it will replay&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If not, then either the browser or operation system behave like a &lt;strong&gt;Stub Resolver&lt;/strong&gt; (&lt;code&gt;gethostaddr()&lt;/code&gt;, &lt;code&gt;gethostbyname()&lt;/code&gt;, &lt;code&gt;gethostent()&lt;/code&gt; are all &lt;strong&gt;Stub Resolver&lt;/strong&gt;)and asks the question&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;The &lt;strong&gt;DNS Stub Resolver&lt;/strong&gt; is a component of the DNS that is accessed by application programs when using the DNS for e.g. resolving domain names to IP addresses. The stub resolver simply serves as an intermediary between the application requiring DNS resolution, and a recursive DNS resolver.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Stub Resolver&lt;/strong&gt; will ask the question to &lt;strong&gt;Recursive Resolver&lt;/strong&gt; &lt;em&gt;(in most cases)&lt;/em&gt; and the &lt;strong&gt;Recursive Resolver&lt;/strong&gt; will do that bulk of work to find you the answer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh6hnqusgom5wdb6b59zv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh6hnqusgom5wdb6b59zv.png" alt="Dns Software" width="800" height="377"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Sometime between &lt;strong&gt;DNS Stub Resolver&lt;/strong&gt; and &lt;strong&gt;Recursive Resolver&lt;/strong&gt; one might have DNS Forwarders, Proxy Server which basically forward the query to &lt;strong&gt;Recursive Resolver&lt;/strong&gt;. This is mostly done keep security and hide the internal details. There are multiple types of &lt;strong&gt;Resolvers&lt;/strong&gt; like &lt;strong&gt;Stub, Recursive&lt;/strong&gt; &lt;em&gt;(mentioned above)&lt;/em&gt; then you have Forwarders, Validating, Pay Wall etc&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Most &lt;strong&gt;ISPs&lt;/strong&gt; run their own &lt;strong&gt;Recursive Resolvers&lt;/strong&gt;. Pretty much all &lt;strong&gt;Recursive Resolvers&lt;/strong&gt; keep their cache from their previous queries.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the answer for the query is not found in cache then &lt;strong&gt;Recursive Resolvers&lt;/strong&gt; try to identify the &lt;strong&gt;Authoritative Name Server&lt;/strong&gt; for the record.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Recursive Resolvers&lt;/strong&gt; might have to talk to N number of &lt;strong&gt;Authoritative Name Server&lt;/strong&gt; to find the answer or sometime talk to other &lt;strong&gt;Recursive Resolvers&lt;/strong&gt; to maintain the hierarchy of cache.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Caching&lt;/strong&gt;, as mentioned all &lt;strong&gt;Recursive Resolvers&lt;/strong&gt; maintain their own. The lifetime of that cache is handled by something called &lt;strong&gt;TTL (Time to live)&lt;/strong&gt;. The &lt;strong&gt;TTL&lt;/strong&gt; is responsible to maintain the hierarchy of cache too. Say, the &lt;strong&gt;Recursive Resolvers&lt;/strong&gt; answered the &lt;strong&gt;Stub Resolver&lt;/strong&gt; and said &lt;strong&gt;TTL&lt;/strong&gt; is &lt;strong&gt;300 Seconds&lt;/strong&gt;. Though the answer was received on &lt;code&gt;250th&lt;/code&gt; Second for &lt;strong&gt;Stub Resolver&lt;/strong&gt; and as per &lt;strong&gt;Recursive Resolvers&lt;/strong&gt; it can cache the answer for &lt;code&gt;300&lt;/code&gt; Seconds. Which mean it will end up keeping the cache for &lt;strong&gt;550 Seconds Stale&lt;/strong&gt;. So, to honor the &lt;strong&gt;TTL&lt;/strong&gt;, any &lt;strong&gt;Recursive Resolvers&lt;/strong&gt; answering should also remove the time spent in &lt;strong&gt;TTL&lt;/strong&gt;. So that the entity lower in the hierarchy get to &lt;strong&gt;cache&lt;/strong&gt; the answer for valid &lt;strong&gt;TTL&lt;/strong&gt;.&lt;br&gt;
&lt;strong&gt;Trivia Detail&lt;/strong&gt;: &lt;strong&gt;&lt;code&gt;TTL&lt;/code&gt;&lt;/strong&gt; are only suggestions for cache lifetime, you may or may not use it. Also there is something call &lt;strong&gt;Max TTL&lt;/strong&gt; set by cacheing resolvers so if you set any value higher then that, will be ignored&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Recursive Resolvers&lt;/strong&gt; usually keeps &lt;a href="https://www.iana.org/domains/root/files" rel="noopener noreferrer"&gt;Root Hint File&lt;/a&gt; &lt;em&gt;(yes, they don’t user &lt;strong&gt;resolv.conf&lt;/strong&gt;)&lt;/em&gt; and it can function if one of the IP from &lt;a href="https://www.iana.org/domains/root/files" rel="noopener noreferrer"&gt;Root Hint File&lt;/a&gt; work it can pull the latest. All it queries is that what is data around (root domain). This query is call &lt;strong&gt;&lt;a href="https://datatracker.ietf.org/doc/html/rfc8109" rel="noopener noreferrer"&gt;Priming Query&lt;/a&gt;&lt;/strong&gt;. In nutshell it means initialing the &lt;strong&gt;DNS&lt;/strong&gt; or &lt;strong&gt;Recursive Resolver&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://icannwiki.org/ICANN" rel="noopener noreferrer"&gt;ICANN&lt;/a&gt;, &lt;a href="https://icannwiki.org/Verisign" rel="noopener noreferrer"&gt;Verisign&lt;/a&gt; and the &lt;a href="https://icannwiki.org/index.php?title=Root_Server_Operators&amp;amp;action=edit&amp;amp;redlink=1" rel="noopener noreferrer"&gt;Root Server Operators&lt;/a&gt; play significant roles in the management and process of the root zone&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;Query to &lt;strong&gt;Root Domain&lt;/strong&gt; returns the Name Servers, (Which is &lt;strong&gt;13&lt;/strong&gt; in count)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5sasywg0htzohhzjcuu9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5sasywg0htzohhzjcuu9.png" alt="dig root" width="800" height="1379"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can see the &lt;strong&gt;Root Domain &lt;code&gt;.&lt;/code&gt;&lt;/strong&gt; has &lt;strong&gt;13&lt;/strong&gt; Name Servers and what you see underneath the &lt;strong&gt;ADDITIONAL SECTION&lt;/strong&gt; are &lt;a href="https://kb.wisc.edu/ddi/page.php?id=8959" rel="noopener noreferrer"&gt;GLUE Records&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="https://kb.wisc.edu/ddi/page.php?id=8959" rel="noopener noreferrer"&gt;GLUE Records&lt;/a&gt;&lt;/strong&gt; are created to eliminate &lt;strong&gt;&lt;a href="https://community.akamai.com/customers/s/article/DNS-Circular-Detection-And-Looping?language=en_US" rel="noopener noreferrer"&gt;circular reference&lt;/a&gt;&lt;/strong&gt;, in simple terms &lt;strong&gt;&lt;a href="https://community.akamai.com/customers/s/article/DNS-Circular-Detection-And-Looping?language=en_US" rel="noopener noreferrer"&gt;circular reference&lt;/a&gt;&lt;/strong&gt; occurs when the &lt;strong&gt;Authoritative Name Server&lt;/strong&gt; exists inside the &lt;strong&gt;Domain&lt;/strong&gt; itself. You can’t reach to the &lt;strong&gt;Name Server&lt;/strong&gt; because the &lt;strong&gt;Domain&lt;/strong&gt; is still unknown. Glue records can only be created at the domain registrar as the registrar controls the DNS settings for a given domain’s delegation. Every Name Server on the internet has its own glue record created by the domain’s owner.&lt;br&gt;
&lt;em&gt;Glue Records are nothing but (direct and hardcoded) A Records for the Name Servers&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;Now &lt;strong&gt;Recursive Resolvers&lt;/strong&gt; which is responsible for most of the work, finds the &lt;strong&gt;Authoritative Name Server&lt;/strong&gt;, gets the answer for the query and the remaining &lt;strong&gt;TTL&lt;/strong&gt;, hands it over to &lt;strong&gt;Stub Resolver&lt;/strong&gt; and that’s how we resolve a &lt;strong&gt;Domain Name&lt;/strong&gt; to an &lt;strong&gt;IP Address&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So I have to summarize this whole fiasco then it would something like, &lt;strong&gt;&lt;em&gt;fun intended pseudo code&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  var cache = map[string]string

    func stubResolver(domain string) string {
      var (
        ipAddress string
        cacheHit bool
      )
      ipAddress, cacheHit = cache[domain]
      if !cache {
        ipAddress = recursiveResolver(domain)
      }
      return ipAddress
    }

    func recursiveResolver(domain string) string {
      ...
      // Will recursively keep trying to identify the
      **// Authoritative Name Server**, by getting the **Name Servers
      // of each elements. It may very well go to
      // the root zone which is .

      return ipAddress
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However there are lot more to it and to understand it properly we need to understand &lt;em&gt;&lt;strong&gt;What is DNS Query ?&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  So, What is DNS Query and What does it contains ?
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;DNS Query&lt;/strong&gt; is a &lt;strong&gt;tuple&lt;/strong&gt;, called &lt;strong&gt;&lt;a href="https://tools.ietf.org/id/draft-bellis-dnsext-multi-qtypes-04.html#introduction" rel="noopener noreferrer"&gt;Query Tuple&lt;/a&gt;&lt;/strong&gt;, consisting of &lt;strong&gt;Query Name, TTL, Class, Query type&lt;/strong&gt; and &lt;strong&gt;RDATA&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd6ydz9px7r2iwu95y3pt.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd6ydz9px7r2iwu95y3pt.jpeg" alt="Query Tuple" width="800" height="343"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So requester is asking for &lt;strong&gt;QTUPLE&lt;/strong&gt; which includes everything, all the information mentioned above. It can’t just ask for something in isolation, it’s either all or nothing. That’s what is going on the raw level on the DNS Query. The wire format (&lt;a href="https://datatracker.ietf.org/doc/html/rfc1035" rel="noopener noreferrer"&gt;RFC1035&lt;/a&gt;) for this is combination of half ascii, half binary and pretty old compression scheme call &lt;a href="https://datatracker.ietf.org/doc/html/rfc8618#page-42" rel="noopener noreferrer"&gt;Label Compression&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjy9h9bo4oeaz19ow110l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjy9h9bo4oeaz19ow110l.png" alt="Raw DNS Wire Format" width="800" height="291"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Trivia Detail&lt;/strong&gt;: &lt;strong&gt;DNS&lt;/strong&gt; usually prefers &lt;strong&gt;UDP&lt;/strong&gt;, however it actually works on both &lt;strong&gt;UDP&lt;/strong&gt; and &lt;strong&gt;TCP&lt;/strong&gt;. First it send the request on &lt;strong&gt;UDP&lt;/strong&gt;, if it gets a response then good or If a &lt;strong&gt;DNS Response&lt;/strong&gt; is larger than &lt;em&gt;512 bytes&lt;/em&gt;, or if a DNS server is managing tasks like zone transfers (transferring DNS records from primary to secondary DNS server), it will try &lt;strong&gt;TCP&lt;/strong&gt;.&lt;br&gt;
&lt;strong&gt;Trivia Detail&lt;/strong&gt;: What is &lt;strong&gt;in-balliwick&lt;/strong&gt; and &lt;strong&gt;out-of-balliwick&lt;/strong&gt; servers? &lt;strong&gt;In-balliwick&lt;/strong&gt; servers are within the zone itself and work with the help of glue records. &lt;strong&gt;Out-of-balliwick&lt;/strong&gt; servers are external servers which is not part of that &lt;strong&gt;TLD&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  How does DNS Packet looks like ?
&lt;/h3&gt;

&lt;p&gt;Below is the picture of &lt;strong&gt;bits&lt;/strong&gt; used to create a &lt;strong&gt;DNS Packet&lt;/strong&gt;. &lt;strong&gt;Before&lt;/strong&gt; and &lt;strong&gt;After&lt;/strong&gt; basically shows how additional &lt;strong&gt;bits&lt;/strong&gt; has been added later in time of DNS Evolution.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F73rsydfnkfkl21xzp2g2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F73rsydfnkfkl21xzp2g2.png" alt="DNS Packet" width="800" height="433"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Mostly it was due to handle the in &lt;strong&gt;RCODE&lt;/strong&gt; section. There was only &lt;strong&gt;4 bits&lt;/strong&gt; assigned for &lt;strong&gt;RCODE&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1ej46orehhsymfaajum8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1ej46orehhsymfaajum8.png" alt="RCODE" width="800" height="275"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Later it was realized that we would need little more space in the packet and that when &lt;strong&gt;&lt;a href="https://tools.ietf.org/id/draft-ietf-dnsext-rfc2671bis-edns0-09.html" rel="noopener noreferrer"&gt;EDNS0’s “OPT” Record&lt;/a&gt;&lt;/strong&gt; was introduced (&lt;a href="https://datatracker.ietf.org/doc/html/rfc6891" rel="noopener noreferrer"&gt;RFC-8691&lt;/a&gt;). So the &lt;strong&gt;extended pseudo resource&lt;/strong&gt; record call &lt;strong&gt;OPT&lt;/strong&gt; added to &lt;strong&gt;additional section&lt;/strong&gt;. Of-course the client needs to indicate that it supports it. Most software in these days supports this.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;It reuses the resource record byte format, however changes many fields&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Total &lt;strong&gt;RCODE&lt;/strong&gt; size becomes &lt;strong&gt;4 + 8 = 12 bits&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Support additional &lt;a href="https://datatracker.ietf.org/doc/html/rfc6891#section-6.1.4" rel="noopener noreferrer"&gt;protocol flags&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Adds support for additional DNS extensions&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Used for Extended errors (&lt;a href="https://datatracker.ietf.org/doc/rfc8914/" rel="noopener noreferrer"&gt;RFC 8914&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Used for Client Subnet DNS Queries (&lt;a href="https://datatracker.ietf.org/doc/html/rfc7871" rel="noopener noreferrer"&gt;RFC 7871&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3e8yct09xpiwwjgqdv9m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3e8yct09xpiwwjgqdv9m.png" alt="OPT Resource Record" width="800" height="433"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Trivia Detail&lt;/strong&gt;: What is &lt;strong&gt;truncation&lt;/strong&gt; in &lt;strong&gt;DNS&lt;/strong&gt; ? When Clients receives bigger payload size than it can handle via &lt;strong&gt;OPT/UDP&lt;/strong&gt;. &lt;strong&gt;Truncation bit&lt;/strong&gt; is set on the DNS Packet. Some other method like removing unimportant items from packet to make it fit, or completely drop everything and ask the Client to connect using &lt;strong&gt;TCP.&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Trivia Detail&lt;/strong&gt;: &lt;strong&gt;Response Rate limiting (RRL)&lt;/strong&gt; is actually used as &lt;strong&gt;DDoS Defense&lt;/strong&gt; mechanism based on the frequency of the query.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Reverse DNS Queries
&lt;/h3&gt;

&lt;p&gt;Basically find the name using IP Address, usually it is &lt;strong&gt;PTR&lt;/strong&gt; record.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[www.google.com](http://www.google.com).  100 IN A 142.250.72.196
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;So, the IP Address of &lt;a href="http://www.google.com" rel="noopener noreferrer"&gt;www.google.com&lt;/a&gt; is &lt;code&gt;142.250.72.196&lt;/code&gt; . We just reverse it like this 196.72.250.142 and add &lt;code&gt;in-ipaddr.arpa&lt;/code&gt; and resolve it using PTR record&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Trivia Detail&lt;/strong&gt;: What is &lt;strong&gt;apex&lt;/strong&gt; zone, &lt;strong&gt;Terminal&lt;/strong&gt; and &lt;strong&gt;lame delegations&lt;/strong&gt;? &lt;strong&gt;Apex&lt;/strong&gt; is basically the &lt;strong&gt;root&lt;/strong&gt; for your domain and &lt;strong&gt;Terminal&lt;/strong&gt; is the last node of your zone. &lt;strong&gt;Lame delegation&lt;/strong&gt; mean parent still holding to NS Record which Child doesn’t uses anymore. &lt;strong&gt;(DNS Terminology)&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  What is &lt;strong&gt;Happy Eyeballs ?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Morden Clients usually send 2 queries in &lt;strong&gt;parallel&lt;/strong&gt; one for &lt;strong&gt;A Record&lt;/strong&gt; and one for &lt;strong&gt;AAAA Record&lt;/strong&gt; and its called &lt;strong&gt;Happy Eyeballs&lt;/strong&gt;(&lt;strong&gt;&lt;a href="https://datatracker.ietf.org/doc/html/rfc8305" rel="noopener noreferrer"&gt;RFC 8305&lt;/a&gt;)&lt;/strong&gt;. Browsers or Application should use whichever comes first. So there are 2 type non-existence in DNS, domain doesn’t exist and you get &lt;strong&gt;&lt;code&gt;NXDOMAIN&lt;/code&gt; Response&lt;/strong&gt; or type doesn’t exist then you get &lt;strong&gt;&lt;code&gt;NOERROR&lt;/code&gt; Response&lt;/strong&gt;. Find more detail &lt;a href="https://bluecatnetworks.com/blog/the-top-four-dns-response-codes-and-what-they-mean/" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Trivia Detail&lt;/strong&gt;: &lt;code&gt;.com&lt;/code&gt; is actually dependent on &lt;code&gt;.net&lt;/code&gt; because all the &lt;code&gt;.com&lt;/code&gt; NameServers are using &lt;code&gt;.net&lt;/code&gt; NameSever&lt;br&gt;
&lt;strong&gt;Trivia Detail&lt;/strong&gt;: &lt;strong&gt;CNAME&lt;/strong&gt; and &lt;strong&gt;DNAME&lt;/strong&gt;, what are difference ? &lt;strong&gt;CNAMEs&lt;/strong&gt; is aliases for the other elements in the tree (same or different zone doesn’t matter) and it points to all other records &lt;code&gt;A&lt;/code&gt;, &lt;code&gt;MX&lt;/code&gt;, &lt;code&gt;TXT&lt;/code&gt; etc. However, &lt;strong&gt;DNAMEs&lt;/strong&gt; are the aliases for zone themselves.&lt;br&gt;
&lt;strong&gt;Trivia Detail&lt;/strong&gt;: Can you have something like “&lt;code&gt;foo*.some-domain.com&lt;/code&gt;” ? &lt;strong&gt;No&lt;/strong&gt; More detail about Wildcard is (&lt;a href="https://datatracker.ietf.org/doc/html/rfc4592" rel="noopener noreferrer"&gt;RFC 4592&lt;/a&gt;)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Hope this blog was able to provide some more interesting fact and details about &lt;strong&gt;DNS&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Happy Learning!!
&lt;/h3&gt;

</description>
      <category>concepts</category>
      <category>dns</category>
    </item>
    <item>
      <title>Solve Dynamic backend problem with Golang</title>
      <dc:creator>Satyajit Roy</dc:creator>
      <pubDate>Mon, 25 Aug 2025 18:11:54 +0000</pubDate>
      <link>https://forem.com/deadlock/solve-dynamic-backend-problem-with-golang-o13</link>
      <guid>https://forem.com/deadlock/solve-dynamic-backend-problem-with-golang-o13</guid>
      <description>&lt;p&gt;As mentioned in a &lt;a href="https://awstip.com/terraform-some-gotcha-and-essentials-5e996c11d92f" rel="noopener noreferrer"&gt;previous blog&lt;/a&gt; post, Terraform can store its state file (&lt;code&gt;.tfstate&lt;/code&gt;) in a remote location. However, the &lt;code&gt;backend&lt;/code&gt; block requires initialization with &lt;code&gt;terraform init&lt;/code&gt; and does not support &lt;code&gt;interpolation&lt;/code&gt;. This means you have to manually populate the backend configuration before running &lt;code&gt;terraform init&lt;/code&gt; or use the &lt;code&gt;-backend-config&lt;/code&gt; switch.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;terraform&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nx"&gt;backend&lt;/span&gt; &lt;span class="s2"&gt;"s3"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;bucket&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"mybucket"&lt;/span&gt;
      &lt;span class="nx"&gt;key&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"path/to/my/key"&lt;/span&gt;
      &lt;span class="nx"&gt;region&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"us-east-1"&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This manual process of changing the &lt;code&gt;key&lt;/code&gt; for every new resource or combination of resources is manageable for small deployments but can become a major headache for larger ones.&lt;/p&gt;

&lt;p&gt;To solve this, we can dynamically generate the &lt;code&gt;backend&lt;/code&gt; block before running &lt;code&gt;terraform init&lt;/code&gt; (explained here &lt;a href="https://awstip.com/terraform-some-gotcha-and-essentials-5e996c11d92f" rel="noopener noreferrer"&gt;my previous blog&lt;/a&gt;) .&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fegjp7frcgop45nymouzm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fegjp7frcgop45nymouzm.png" width="720" height="282"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Goal&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The goal is to create a tool that automatically generates the backend block and establishes a &lt;strong&gt;1:1 relationship&lt;/strong&gt; between the &lt;code&gt;tfvars&lt;/code&gt; file and the &lt;code&gt;tfstate&lt;/code&gt; file. The tool should adhere to the following rules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It should accept environment variables for &lt;code&gt;S3&lt;/code&gt;, &lt;code&gt;DynamoDB&lt;/code&gt;, and &lt;code&gt;Region&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;It should take a &lt;code&gt;tfvars&lt;/code&gt; file as an argument.&lt;/li&gt;
&lt;li&gt;It should generate the backend configuration using either the environment variables or the absolute path of the &lt;code&gt;tfvars&lt;/code&gt; file.&lt;/li&gt;
&lt;li&gt;It should be able to run &lt;code&gt;terraform init&lt;/code&gt;, &lt;code&gt;terraform plan&lt;/code&gt;, &lt;code&gt;terraform apply&lt;/code&gt;, and &lt;code&gt;terraform destroy&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;It should run &lt;code&gt;terraform init&lt;/code&gt;, &lt;code&gt;terraform plan&lt;/code&gt;, and &lt;code&gt;terraform apply&lt;/code&gt; if the filename ends with &lt;code&gt;*.tfvars&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;It should run &lt;code&gt;terraform plan -destroy&lt;/code&gt; and &lt;code&gt;terraform destroy&lt;/code&gt; if the filename ends with &lt;code&gt;*.destroy&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Explanation&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Let's call our tool &lt;code&gt;autotf&lt;/code&gt;. It will have two sub-commands: &lt;code&gt;verify&lt;/code&gt; and &lt;code&gt;deploy&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Flow Control and Decision Making&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Actions are performed based on the file extension.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fv2%2Fformat%3Awebp%2F1%2A3HKB5znMYp_thwDVAQ2kBQ.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fv2%2Fformat%3Awebp%2F1%2A3HKB5znMYp_thwDVAQ2kBQ.jpeg" width="800" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Building Resources
&lt;/h3&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;1. Verify Command&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;When you run the following command, &lt;code&gt;autotf&lt;/code&gt; will automatically generate the backend configuration, initialize Terraform, and then run &lt;code&gt;terraform plan&lt;/code&gt; or &lt;code&gt;terraform plan -destroy&lt;/code&gt; based on the file extension.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;S3Bucket&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"some-s3-bucket"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;Region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"us-east-1"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;DynamoDB&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"some-dynamodb-table"&lt;/span&gt;
./autotf verify stage/s3/autotf-testing01.tfvars
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;autotf&lt;/code&gt; should automatically generate the backend configuration and initialize &lt;code&gt;terraform&lt;/code&gt; using it by running &lt;code&gt;terraform init&lt;/code&gt; and then run terraform plan or &lt;code&gt;terraform plan -destroy&lt;/code&gt; depending on the file name extension &lt;code&gt;_.tfvars&lt;/code&gt; or &lt;code&gt;_.destroy&lt;/code&gt; sequentially.&lt;/p&gt;

&lt;h4&gt;
  
  
  Output
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;INFO 2022-03-28 17:50:29 will run terraform init, plan on &lt;span class="o"&gt;[&lt;/span&gt;autotf-testing01.tfvars]

+------------------+----------------+-------------------------+-----------------------------------+
| Resource Name    | Backend Bucket | TFVars Name             | Backend Key                       |
+------------------+----------------+-------------------------+-----------------------------------+
| autotf-testing01 | autotf-testing | autotf-testing01.tfvars | stage/s3/autotf-testing01.tfstate |
+------------------+----------------+-------------------------+-----------------------------------+

Initializing the backend...

Successfully configured the backend &lt;span class="s2"&gt;"s3"&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; Terraform will automatically
use this backend unless the backend configuration changes.

Initializing provider plugins...
- Finding latest version of hashicorp/aws...
- Installing hashicorp/aws v4.8.0...
- Installed hashicorp/aws v4.8.0 &lt;span class="o"&gt;(&lt;/span&gt;signed by HashiCorp&lt;span class="o"&gt;)&lt;/span&gt;

Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file &lt;span class="k"&gt;in &lt;/span&gt;your version control repository
so that Terraform can guarantee to make the same selections by default when
you run &lt;span class="s2"&gt;"terraform init"&lt;/span&gt; &lt;span class="k"&gt;in &lt;/span&gt;the future.

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running &lt;span class="s2"&gt;"terraform plan"&lt;/span&gt; to see
any changes that are required &lt;span class="k"&gt;for &lt;/span&gt;your infrastructure. All Terraform commands
should now work.

If you ever &lt;span class="nb"&gt;set &lt;/span&gt;or change modules or backend configuration &lt;span class="k"&gt;for &lt;/span&gt;Terraform,
rerun this &lt;span class="nb"&gt;command &lt;/span&gt;to reinitialize your working directory. If you forget, other
commands will detect it and remind you to &lt;span class="k"&gt;do &lt;/span&gt;so &lt;span class="k"&gt;if &lt;/span&gt;necessary.
Acquiring state lock. This may take a few moments...

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  &lt;span class="c"&gt;# aws_s3_bucket.bucket will be created&lt;/span&gt;
  + resource &lt;span class="s2"&gt;"aws_s3_bucket"&lt;/span&gt; &lt;span class="s2"&gt;"bucket"&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      + acceleration_status                  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;known after apply&lt;span class="o"&gt;)&lt;/span&gt;
      + acl                                  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;known after apply&lt;span class="o"&gt;)&lt;/span&gt;
      + arn                                  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;known after apply&lt;span class="o"&gt;)&lt;/span&gt;
      + bucket                               &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"autotf-testing01"&lt;/span&gt;
      + bucket_domain_name                   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;known after apply&lt;span class="o"&gt;)&lt;/span&gt;
      + bucket_regional_domain_name          &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;known after apply&lt;span class="o"&gt;)&lt;/span&gt;
      + cors_rule                            &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;known after apply&lt;span class="o"&gt;)&lt;/span&gt;
      + force_destroy                        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;false&lt;/span&gt;
      + grant                                &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;known after apply&lt;span class="o"&gt;)&lt;/span&gt;
      + hosted_zone_id                       &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;known after apply&lt;span class="o"&gt;)&lt;/span&gt;
      + &lt;span class="nb"&gt;id&lt;/span&gt;                                   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;known after apply&lt;span class="o"&gt;)&lt;/span&gt;
      + lifecycle_rule                       &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;known after apply&lt;span class="o"&gt;)&lt;/span&gt;
      + logging                              &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;known after apply&lt;span class="o"&gt;)&lt;/span&gt;
      + object_lock_enabled                  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;known after apply&lt;span class="o"&gt;)&lt;/span&gt;
      + policy                               &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;known after apply&lt;span class="o"&gt;)&lt;/span&gt;
      + region                               &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;known after apply&lt;span class="o"&gt;)&lt;/span&gt;
      + replication_configuration            &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;known after apply&lt;span class="o"&gt;)&lt;/span&gt;
      + request_payer                        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;known after apply&lt;span class="o"&gt;)&lt;/span&gt;
      + server_side_encryption_configuration &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;known after apply&lt;span class="o"&gt;)&lt;/span&gt;
      + tags                                 &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
          + &lt;span class="s2"&gt;"Environment"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Dev"&lt;/span&gt;
          + &lt;span class="s2"&gt;"Name"&lt;/span&gt;        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"autotf-testing01"&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
      + tags_all                             &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
          + &lt;span class="s2"&gt;"Environment"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Dev"&lt;/span&gt;
          + &lt;span class="s2"&gt;"Name"&lt;/span&gt;        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"autotf-testing01"&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
      + versioning                           &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;known after apply&lt;span class="o"&gt;)&lt;/span&gt;
      + website                              &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;known after apply&lt;span class="o"&gt;)&lt;/span&gt;
      + website_domain                       &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;known after apply&lt;span class="o"&gt;)&lt;/span&gt;
      + website_endpoint                     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;known after apply&lt;span class="o"&gt;)&lt;/span&gt;

      + object_lock_configuration &lt;span class="o"&gt;{&lt;/span&gt;
          + object_lock_enabled &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;known after apply&lt;span class="o"&gt;)&lt;/span&gt;
          + rule                &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;known after apply&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

Plan: 1 to add, 0 to change, 0 to destroy.

Changes to Outputs:
  + bucket_name &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;known after apply&lt;span class="o"&gt;)&lt;/span&gt;

────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

Note: You didn&lt;span class="s1"&gt;'t use the -out option to save this plan, so Terraform can'&lt;/span&gt;t guarantee to take exactly these actions &lt;span class="k"&gt;if &lt;/span&gt;you run &lt;span class="s2"&gt;"terraform apply"&lt;/span&gt; now.
Releasing state lock. This may take a few moments...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;strong&gt;2. Deploy Command&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Running the &lt;code&gt;deploy&lt;/code&gt; command with a &lt;code&gt;*.tfvars&lt;/code&gt; file will initiate the resource creation process.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;S3Bucket&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"some-s3-bucket"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;Region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"us-east-1"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;DynamoDB&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"some-dynamodb-table"&lt;/span&gt;
./autotf deploy stage/s3/autotf-testing01.tfvars
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  &lt;strong&gt;Destroying Resources&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Resource destruction follows the same flow control. If the file extension is &lt;code&gt;*.destroy&lt;/code&gt;, the &lt;code&gt;verify&lt;/code&gt; command will run &lt;code&gt;terraform init&lt;/code&gt; and &lt;code&gt;terraform plan -destroy&lt;/code&gt;, and the &lt;code&gt;deploy&lt;/code&gt; command will run &lt;code&gt;terraform init&lt;/code&gt; and &lt;code&gt;terraform destroy&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Change the file name from *.tfvars to *.destroy&lt;/span&gt;
&lt;span class="nb"&gt;mv &lt;/span&gt;stage/s3/autotf-testing01.tfvars stage/s3/autotf-testing01.destroy

&lt;span class="c"&gt;# Run the `autotf` deploy command again with the new filename&lt;/span&gt;
./autotf deploy stage/s3/autotf-testing01.destroy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Output
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;INFO 2022-03-28 18:13:07 will run terraform init, plan &lt;span class="nt"&gt;-destory&lt;/span&gt; on &lt;span class="o"&gt;[&lt;/span&gt;autotf-testing01.destroy]

Initializing the backend...

Initializing provider plugins...
- Reusing previous version of hashicorp/aws from the dependency lock file
- Using previously-installed hashicorp/aws v4.8.0

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running &lt;span class="s2"&gt;"terraform plan"&lt;/span&gt; to see
any changes that are required &lt;span class="k"&gt;for &lt;/span&gt;your infrastructure. All Terraform commands
should now work.

If you ever &lt;span class="nb"&gt;set &lt;/span&gt;or change modules or backend configuration &lt;span class="k"&gt;for &lt;/span&gt;Terraform,
rerun this &lt;span class="nb"&gt;command &lt;/span&gt;to reinitialize your working directory. If you forget, other
commands will detect it and remind you to &lt;span class="k"&gt;do &lt;/span&gt;so &lt;span class="k"&gt;if &lt;/span&gt;necessary.
Acquiring state lock. This may take a few moments...
aws_s3_bucket.bucket: Refreshing state... &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;autotf-testing01]

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  - destroy

Terraform will perform the following actions:

  &lt;span class="c"&gt;# aws_s3_bucket.bucket will be destroyed&lt;/span&gt;
  - resource &lt;span class="s2"&gt;"aws_s3_bucket"&lt;/span&gt; &lt;span class="s2"&gt;"bucket"&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      - acl                                  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"private"&lt;/span&gt; -&amp;gt; null
      - arn                                  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"arn:aws:s3:::autotf-testing01"&lt;/span&gt; -&amp;gt; null
      - bucket                               &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"autotf-testing01"&lt;/span&gt; -&amp;gt; null
      - bucket_domain_name                   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"autotf-testing01.s3.amazonaws.com"&lt;/span&gt; -&amp;gt; null
      - bucket_regional_domain_name          &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"autotf-testing01.s3.amazonaws.com"&lt;/span&gt; -&amp;gt; null
      - cors_rule                            &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt; -&amp;gt; null
      - force_destroy                        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;false&lt;/span&gt; -&amp;gt; null
      - grant                                &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt; -&amp;gt; null
      - hosted_zone_id                       &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Z3AQBSTGFYJSTF"&lt;/span&gt; -&amp;gt; null
      - &lt;span class="nb"&gt;id&lt;/span&gt;                                   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"autotf-testing01"&lt;/span&gt; -&amp;gt; null
      - lifecycle_rule                       &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt; -&amp;gt; null
      - logging                              &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt; -&amp;gt; null
      - object_lock_enabled                  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;false&lt;/span&gt; -&amp;gt; null
      - region                               &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"us-east-1"&lt;/span&gt; -&amp;gt; null
      - replication_configuration            &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt; -&amp;gt; null
      - request_payer                        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"BucketOwner"&lt;/span&gt; -&amp;gt; null
      - server_side_encryption_configuration &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt; -&amp;gt; null
      - tags                                 &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
          - &lt;span class="s2"&gt;"Environment"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Dev"&lt;/span&gt;
          - &lt;span class="s2"&gt;"Name"&lt;/span&gt;        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"autotf-testing01"&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt; -&amp;gt; null
      - tags_all                             &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
          - &lt;span class="s2"&gt;"Environment"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Dev"&lt;/span&gt;
          - &lt;span class="s2"&gt;"Name"&lt;/span&gt;        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"autotf-testing01"&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt; -&amp;gt; null
      - versioning                           &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;
          - &lt;span class="o"&gt;{&lt;/span&gt;
              - enabled    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;false&lt;/span&gt;
              - mfa_delete &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;false&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;,
        &lt;span class="o"&gt;]&lt;/span&gt; -&amp;gt; null
      - website                              &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt; -&amp;gt; null
    &lt;span class="o"&gt;}&lt;/span&gt;

Plan: 0 to add, 0 to change, 1 to destroy.

Changes to Outputs:
  - bucket_name &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"autotf-testing01"&lt;/span&gt; -&amp;gt; null

────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

Note: You didn&lt;span class="s1"&gt;'t use the -out option to save this plan, so Terraform can'&lt;/span&gt;t guarantee to take exactly these actions &lt;span class="k"&gt;if &lt;/span&gt;you run &lt;span class="s2"&gt;"terraform apply"&lt;/span&gt; now.
Releasing state lock. This may take a few moments...
Acquiring state lock. This may take a few moments...
aws_s3_bucket.bucket: Refreshing state... &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;autotf-testing01]

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  - destroy

Terraform will perform the following actions:

  &lt;span class="c"&gt;# aws_s3_bucket.bucket will be destroyed&lt;/span&gt;
  - resource &lt;span class="s2"&gt;"aws_s3_bucket"&lt;/span&gt; &lt;span class="s2"&gt;"bucket"&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      - acl                                  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"private"&lt;/span&gt; -&amp;gt; null
      - arn                                  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"arn:aws:s3:::autotf-testing01"&lt;/span&gt; -&amp;gt; null
      - bucket                               &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"autotf-testing01"&lt;/span&gt; -&amp;gt; null
      - bucket_domain_name                   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"autotf-testing01.s3.amazonaws.com"&lt;/span&gt; -&amp;gt; null
      - bucket_regional_domain_name          &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"autotf-testing01.s3.amazonaws.com"&lt;/span&gt; -&amp;gt; null
      - cors_rule                            &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt; -&amp;gt; null
      - force_destroy                        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;false&lt;/span&gt; -&amp;gt; null
      - grant                                &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt; -&amp;gt; null
      - hosted_zone_id                       &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Z3AQBSTGFYJSTF"&lt;/span&gt; -&amp;gt; null
      - &lt;span class="nb"&gt;id&lt;/span&gt;                                   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"autotf-testing01"&lt;/span&gt; -&amp;gt; null
      - lifecycle_rule                       &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt; -&amp;gt; null
      - logging                              &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt; -&amp;gt; null
      - object_lock_enabled                  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;false&lt;/span&gt; -&amp;gt; null
      - region                               &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"us-east-1"&lt;/span&gt; -&amp;gt; null
      - replication_configuration            &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt; -&amp;gt; null
      - request_payer                        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"BucketOwner"&lt;/span&gt; -&amp;gt; null
      - server_side_encryption_configuration &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt; -&amp;gt; null
      - tags                                 &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
          - &lt;span class="s2"&gt;"Environment"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Dev"&lt;/span&gt;
          - &lt;span class="s2"&gt;"Name"&lt;/span&gt;        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"autotf-testing01"&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt; -&amp;gt; null
      - tags_all                             &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
          - &lt;span class="s2"&gt;"Environment"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Dev"&lt;/span&gt;
          - &lt;span class="s2"&gt;"Name"&lt;/span&gt;        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"autotf-testing01"&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt; -&amp;gt; null
      - versioning                           &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;
          - &lt;span class="o"&gt;{&lt;/span&gt;
              - enabled    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;false&lt;/span&gt;
              - mfa_delete &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;false&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;,
        &lt;span class="o"&gt;]&lt;/span&gt; -&amp;gt; null
      - website                              &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt; -&amp;gt; null
    &lt;span class="o"&gt;}&lt;/span&gt;

Plan: 0 to add, 0 to change, 1 to destroy.

Changes to Outputs:
  - bucket_name &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"autotf-testing01"&lt;/span&gt; -&amp;gt; null
aws_s3_bucket.bucket: Destroying... &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;autotf-testing01]
aws_s3_bucket.bucket: Destruction &lt;span class="nb"&gt;complete &lt;/span&gt;after 0s
Releasing state lock. This may take a few moments...

Destroy &lt;span class="nb"&gt;complete&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; Resources: 1 destroyed.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  &lt;strong&gt;The &lt;code&gt;autotf&lt;/code&gt; Tool&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;autotf&lt;/code&gt; tool is available on GitHub. It's a demo to showcase how to solve this common Terraform problem. The control flow is straightforward: for each &lt;code&gt;verify&lt;/code&gt; and &lt;code&gt;deploy&lt;/code&gt; command, the backend configuration is dynamically generated from the &lt;code&gt;tfvars&lt;/code&gt; file, ensuring it's always consistent.&lt;/p&gt;

&lt;p&gt;Here is an example of the Terraform code for creating an S3 bucket.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Terraform Code&lt;/strong&gt;
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;terraform&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;backend&lt;/span&gt; &lt;span class="s2"&gt;"s3"&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;provider&lt;/span&gt; &lt;span class="s2"&gt;"aws"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;region&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;region&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_s3_bucket"&lt;/span&gt; &lt;span class="s2"&gt;"bucket"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;bucket&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;

  &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;Name&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;
    &lt;span class="nx"&gt;Environment&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Dev"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"region"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"name"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"bucket_name"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_s3_bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;strong&gt;Command Run&lt;/strong&gt;
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./autotf verify stage/s3/autotf-testing01.tfvars
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using an external tool provides the ability to manage Terraform without manually editing the backend configuration. Generating the backend configuration based on a predefined logic is a much more efficient approach.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fv2%2Fformat%3Awebp%2F1%2A3HKB5znMYp_thwDVAQ2kBQ.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fv2%2Fformat%3Awebp%2F1%2A3HKB5znMYp_thwDVAQ2kBQ.jpeg" width="800" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Above flow-control explains how the sequence of events will occur for &lt;code&gt;verify&lt;/code&gt; and &lt;code&gt;deploy&lt;/code&gt; sub-commands respectively. Because the backend configuration is getting generated dynamically with each &lt;code&gt;tfvars&lt;/code&gt; file so we don’t have to persist it and it will always be the same as long as we used the same &lt;code&gt;tfvars&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;Here is example for verify step for creating a &lt;strong&gt;S3 Bucket&lt;/strong&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Terraform Code
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;terraform&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;backend&lt;/span&gt; &lt;span class="s2"&gt;"s3"&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;provider&lt;/span&gt; &lt;span class="s2"&gt;"aws"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;region&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;region&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_s3_bucket"&lt;/span&gt; &lt;span class="s2"&gt;"bucket"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;bucket&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;

  &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;Name&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;
    &lt;span class="nx"&gt;Environment&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Dev"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"region"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"name"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"bucket_name"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_s3_bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Command I Ran
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; ./autotf verify stage/s3/autotf-testing01.tfvars
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Output
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;INFO 2022-03-28 17:50:29 will run terraform init, plan on &lt;span class="o"&gt;[&lt;/span&gt;autotf-testing01.tfvars]

+------------------+----------------+-------------------------+-----------------------------------+
| Resource Name    | Backend Bucket | TFVars Name             | Backend Key                       |
+------------------+----------------+-------------------------+-----------------------------------+
| autotf-testing01 | autotf-testing | autotf-testing01.tfvars | stage/s3/autotf-testing01.tfstate |
+------------------+----------------+-------------------------+-----------------------------------+

Initializing the backend...

Successfully configured the backend &lt;span class="s2"&gt;"s3"&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; Terraform will automatically
use this backend unless the backend configuration changes.

Initializing provider plugins...
- Finding latest version of hashicorp/aws...
- Installing hashicorp/aws v4.8.0...
- Installed hashicorp/aws v4.8.0 &lt;span class="o"&gt;(&lt;/span&gt;signed by HashiCorp&lt;span class="o"&gt;)&lt;/span&gt;

Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file &lt;span class="k"&gt;in &lt;/span&gt;your version control repository
so that Terraform can guarantee to make the same selections by default when
you run &lt;span class="s2"&gt;"terraform init"&lt;/span&gt; &lt;span class="k"&gt;in &lt;/span&gt;the future.

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running &lt;span class="s2"&gt;"terraform plan"&lt;/span&gt; to see
any changes that are required &lt;span class="k"&gt;for &lt;/span&gt;your infrastructure. All Terraform commands
should now work.

If you ever &lt;span class="nb"&gt;set &lt;/span&gt;or change modules or backend configuration &lt;span class="k"&gt;for &lt;/span&gt;Terraform,
rerun this &lt;span class="nb"&gt;command &lt;/span&gt;to reinitialize your working directory. If you forget, other
commands will detect it and remind you to &lt;span class="k"&gt;do &lt;/span&gt;so &lt;span class="k"&gt;if &lt;/span&gt;necessary.
Acquiring state lock. This may take a few moments...

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  &lt;span class="c"&gt;# aws_s3_bucket.bucket will be created&lt;/span&gt;
  + resource &lt;span class="s2"&gt;"aws_s3_bucket"&lt;/span&gt; &lt;span class="s2"&gt;"bucket"&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      + acceleration_status                  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;known after apply&lt;span class="o"&gt;)&lt;/span&gt;
      + acl                                  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;known after apply&lt;span class="o"&gt;)&lt;/span&gt;
      + arn                                  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;known after apply&lt;span class="o"&gt;)&lt;/span&gt;
      + bucket                               &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"autotf-testing01"&lt;/span&gt;
      + bucket_domain_name                   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;known after apply&lt;span class="o"&gt;)&lt;/span&gt;
      + bucket_regional_domain_name          &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;known after apply&lt;span class="o"&gt;)&lt;/span&gt;
      + cors_rule                            &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;known after apply&lt;span class="o"&gt;)&lt;/span&gt;
      + force_destroy                        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;false&lt;/span&gt;
      + grant                                &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;known after apply&lt;span class="o"&gt;)&lt;/span&gt;
      + hosted_zone_id                       &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;known after apply&lt;span class="o"&gt;)&lt;/span&gt;
      + &lt;span class="nb"&gt;id&lt;/span&gt;                                   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;known after apply&lt;span class="o"&gt;)&lt;/span&gt;
      + lifecycle_rule                       &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;known after apply&lt;span class="o"&gt;)&lt;/span&gt;
      + logging                              &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;known after apply&lt;span class="o"&gt;)&lt;/span&gt;
      + object_lock_enabled                  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;known after apply&lt;span class="o"&gt;)&lt;/span&gt;
      + policy                               &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;known after apply&lt;span class="o"&gt;)&lt;/span&gt;
      + region                               &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;known after apply&lt;span class="o"&gt;)&lt;/span&gt;
      + replication_configuration            &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;known after apply&lt;span class="o"&gt;)&lt;/span&gt;
      + request_payer                        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;known after apply&lt;span class="o"&gt;)&lt;/span&gt;
      + server_side_encryption_configuration &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;known after apply&lt;span class="o"&gt;)&lt;/span&gt;
      + tags                                 &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
          + &lt;span class="s2"&gt;"Environment"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Dev"&lt;/span&gt;
          + &lt;span class="s2"&gt;"Name"&lt;/span&gt;        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"autotf-testing01"&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
      + tags_all                             &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
          + &lt;span class="s2"&gt;"Environment"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Dev"&lt;/span&gt;
          + &lt;span class="s2"&gt;"Name"&lt;/span&gt;        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"autotf-testing01"&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
      + versioning                           &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;known after apply&lt;span class="o"&gt;)&lt;/span&gt;
      + website                              &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;known after apply&lt;span class="o"&gt;)&lt;/span&gt;
      + website_domain                       &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;known after apply&lt;span class="o"&gt;)&lt;/span&gt;
      + website_endpoint                     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;known after apply&lt;span class="o"&gt;)&lt;/span&gt;

      + object_lock_configuration &lt;span class="o"&gt;{&lt;/span&gt;
          + object_lock_enabled &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;known after apply&lt;span class="o"&gt;)&lt;/span&gt;
          + rule                &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;known after apply&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

Plan: 1 to add, 0 to change, 0 to destroy.

Changes to Outputs:
  + bucket_name &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;known after apply&lt;span class="o"&gt;)&lt;/span&gt;

────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

Note: You didn&lt;span class="s1"&gt;'t use the -out option to save this plan, so Terraform can'&lt;/span&gt;t guarantee to take exactly these actions &lt;span class="k"&gt;if &lt;/span&gt;you run &lt;span class="s2"&gt;"terraform apply"&lt;/span&gt; now.
Releasing state lock. This may take a few moments...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As I mentioned before in &lt;a href="https://awstip.com/terraform-some-gotcha-and-essentials-5e996c11d92f" rel="noopener noreferrer"&gt;my previous blog&lt;/a&gt; with the help of some external tool to achieve the dynamic backend configuration generation and we did it. We can even run this tool in &lt;code&gt;docker&lt;/code&gt; container (How ? &lt;a href="https://towardsdev.com/run-golang-app-inside-a-docker-container-8cb6e64ae722" rel="noopener noreferrer"&gt;Explained here&lt;/a&gt;) in our CI System.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Personal Best Practices&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Here are some rules I personally follow for better Terraform management:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ensure consistency:&lt;/strong&gt; The resource name, &lt;code&gt;tfvars&lt;/code&gt; filename, and &lt;code&gt;tfstate&lt;/code&gt; filename should be the same to maintain a &lt;strong&gt;1:1 relationship&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Derive names automatically:&lt;/strong&gt; For multiple resources forming a single entity, names are automatically derived from the primary resource's name.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep &lt;code&gt;tfvars&lt;/code&gt; short:&lt;/strong&gt; Use defaults to minimize the size of &lt;code&gt;tfvars&lt;/code&gt; files.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use ternary operators:&lt;/strong&gt; This helps manage both computed and provided values effectively.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Make modules self-sufficient:&lt;/strong&gt; Design modules to be as nimble and independent as possible.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Write validators:&lt;/strong&gt; Implement validators to support a "fail-fast" approach.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Avoid &lt;code&gt;depends_on&lt;/code&gt;:&lt;/strong&gt; Try to use it as little as possible.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Happy Coding and Terraforming! 💻&lt;/p&gt;

</description>
      <category>concepts</category>
      <category>terraform</category>
      <category>automation</category>
      <category>go</category>
    </item>
    <item>
      <title>I Got Tired of Typoing in My Git Commits, So I Wrote a Spellchecker</title>
      <dc:creator>Satyajit Roy</dc:creator>
      <pubDate>Sat, 23 Aug 2025 09:38:26 +0000</pubDate>
      <link>https://forem.com/deadlock/i-got-tired-of-typoing-in-my-git-commits-so-i-wrote-a-spellchecker-916</link>
      <guid>https://forem.com/deadlock/i-got-tired-of-typoing-in-my-git-commits-so-i-wrote-a-spellchecker-916</guid>
      <description>&lt;h2&gt;
  
  
  I Got Tired of Typoing in My Git Commits, So I Wrote a Spellchecker
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Problem: A Constant, Tiny Annoyance
&lt;/h3&gt;

&lt;p&gt;I’m a decent developer, but a terrible speller. It’s a combination that leads to a specific, low-grade, yet constant form of humiliation: the typo-ridden Git commit message.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr0se79e45q3uf0l3a2ik.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr0se79e45q3uf0l3a2ik.png" alt="A frustrated developer at a computer" width="553" height="426"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You know the ones:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;git commit -m "Fix spec for user controlelr"&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;git commit -m "Add new feture for exporting data"&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;git commit -m "Corect a stupid tpyo in a stupid comment"&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every time I’d push a branch and open a &lt;code&gt;pull request&lt;/code&gt;, I’d see my own mistakes staring back at me from the beautifully crafted UI of &lt;strong&gt;GitHub&lt;/strong&gt; or &lt;strong&gt;GitLab&lt;/strong&gt;. It was a tiny, public testament to my carelessness. Linters protect my code, but nothing was protecting my prose.&lt;/p&gt;

&lt;p&gt;I was tired of it. It was time to &lt;strong&gt;automate&lt;/strong&gt; the solution.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Solution: Git Hooks to the Rescue
&lt;/h3&gt;

&lt;p&gt;The natural place to solve this is with a &lt;strong&gt;&lt;a href="https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks" rel="noopener noreferrer"&gt;Git hook&lt;/a&gt;&lt;/strong&gt;, specifically the &lt;code&gt;commit-msg&lt;/code&gt; hook. This hook runs after the default commit message file is created but &lt;em&gt;before&lt;/em&gt; the &lt;em&gt;commit&lt;/em&gt; is finalized. It’s the perfect place to inspect the message and, if it doesn’t meet your standards, reject the commit entirely.&lt;/p&gt;

&lt;p&gt;The plan was simple:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Write a script that takes the proposed commit message file as an argument.&lt;/li&gt;
&lt;li&gt; Extract the message from the file.&lt;/li&gt;
&lt;li&gt; Run it through a spellchecker.&lt;/li&gt;
&lt;li&gt; If there are potential errors, print them and exit with a non-zero status (telling Git to abort the commit).&lt;/li&gt;
&lt;li&gt; If it’s clean, exit successfully and let the commit proceed.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The Implementation: A Bit of Bash and &lt;code&gt;aspell&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;I’m a big fan of using existing command-line tools, and for spellchecking, the classic &lt;code&gt;aspell&lt;/code&gt; is perfect for this job.&lt;/p&gt;

&lt;p&gt;Here is the core of the &lt;code&gt;commit-msg&lt;/code&gt; hook I wrote:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;

&lt;span class="c"&gt;# commit-msg hook to spell check the commit message&lt;/span&gt;

&lt;span class="c"&gt;# Check if aspell is installed&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nb"&gt;command&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; aspell &amp;amp;&amp;gt; /dev/null
&lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Error: aspell is not installed. Please install it to use the spellcheck hook."&lt;/span&gt;
    &lt;span class="nb"&gt;exit &lt;/span&gt;1
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="c"&gt;# Get the commit message file path from Git&lt;/span&gt;
&lt;span class="nv"&gt;MSG_FILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# Read the commit message&lt;/span&gt;
&lt;span class="nv"&gt;MESSAGE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$MSG_FILE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# Check if the message is empty or just comments (for verbose editing)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$MESSAGE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$MESSAGE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;~ ^# &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
    &lt;span class="c"&gt;# If empty or all comments, this is likely an interactive edit, so we skip checking.&lt;/span&gt;
    &lt;span class="nb"&gt;exit &lt;/span&gt;0
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="c"&gt;# Use aspell to check the message.&lt;/span&gt;
&lt;span class="c"&gt;# - list: just list the misspelled words&lt;/span&gt;
&lt;span class="c"&gt;# --mode=email: better for checking prose, not code&lt;/span&gt;
&lt;span class="c"&gt;# --ignore-case: self-explanatory&lt;/span&gt;
&lt;span class="c"&gt;# --ignore=3: ignore words under 3 characters (lets 'git' through)&lt;/span&gt;
&lt;span class="nv"&gt;ERRORS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$MESSAGE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | aspell &lt;span class="nt"&gt;--mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;email &lt;span class="nt"&gt;--ignore-case&lt;/span&gt; &lt;span class="nt"&gt;--ignore&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;3 list&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$ERRORS&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"---------------------------------------------------------"&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"OH NO! Your commit message has spelling mistakes!"&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"---------------------------------------------------------"&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"The following words are not recognized:"&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$ERRORS&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;sort&lt;/span&gt; | &lt;span class="nb"&gt;uniq
    echo&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Please fix your commit message and try again."&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"To bypass this check, use 'git commit --no-verify'."&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"---------------------------------------------------------"&lt;/span&gt;
    &lt;span class="nb"&gt;exit &lt;/span&gt;1
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="c"&gt;# If we get here, the spell check passed.&lt;/span&gt;
&lt;span class="nb"&gt;exit &lt;/span&gt;0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How to Install It
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Make the script executable.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chmod&lt;/span&gt; +x commit-msg
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Place it in your Git hooks directory.&lt;/strong&gt; For a single repository, that’s &lt;code&gt;.git/hooks/&lt;/code&gt;. To use it globally for all your repos (highly recommended!), you can set a global &lt;code&gt;core.hooksPath&lt;/code&gt; or copy it to your global template directory.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# For a single project&lt;/span&gt;
&lt;span class="nb"&gt;cp &lt;/span&gt;commit-msg /path/to/my/project/.git/hooks/

&lt;span class="c"&gt;# To install it globally for all new repos&lt;/span&gt;
&lt;span class="c"&gt;# 1. Create a global templates directory (if you haven't already)&lt;/span&gt;
&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; ~/.git-templates/hooks
&lt;span class="c"&gt;# 2. Copy your hook into it&lt;/span&gt;
&lt;span class="nb"&gt;cp &lt;/span&gt;commit-msg ~/.git-templates/hooks/
&lt;span class="c"&gt;# 3. Tell Git to use this directory for all new 'git init' or clones&lt;/span&gt;
git config &lt;span class="nt"&gt;--global&lt;/span&gt; init.templatedir &lt;span class="s1"&gt;'~/.git-templates'&lt;/span&gt;
&lt;span class="c"&gt;# (For existing repos, you'll need to manually copy the hook or re-run 'git init')&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  The Result: Beautiful, Typo-Free Commit History
&lt;/h3&gt;

&lt;p&gt;The effect was immediate and glorious. Now, when I try to commit with a typo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Fix the tpyo"&lt;/span&gt;
OH NO! Your commit message has spelling mistakes!
&lt;span class="nt"&gt;---------------------------------------------------------&lt;/span&gt;
The following words are not recognized:
tpyo
&lt;span class="nt"&gt;---------------------------------------------------------&lt;/span&gt;
Please fix your commit message and try again.
To bypass this check, use &lt;span class="s1"&gt;'git commit --no-verify'&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It forces me to be better. It’s a small, automated nudge towards quality that has completely eliminated this petty annoyance from my workflow. My commit history is cleaner, and my pull requests no longer have that initial, embarrassing comment from me that just says &lt;em&gt;"fixed a typo in the commit message."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It’s a tiny &lt;em&gt;investment&lt;/em&gt; in tooling that has paid for itself in reduced &lt;em&gt;frustration&lt;/em&gt; a hundred times over. If you’re also tired of &lt;code&gt;typos&lt;/code&gt;, I highly recommend giving it a try.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Dev Setup on Autopilot</title>
      <dc:creator>Satyajit Roy</dc:creator>
      <pubDate>Mon, 18 Aug 2025 18:46:59 +0000</pubDate>
      <link>https://forem.com/deadlock/dev-setup-on-autopilot-3ok0</link>
      <guid>https://forem.com/deadlock/dev-setup-on-autopilot-3ok0</guid>
      <description>&lt;h2&gt;
  
  
  Dev Setup on Autopilot
&lt;/h2&gt;

&lt;p&gt;Every developer knows the ritual. A new laptop arrives shiny, fast, and brimming with potential. Or perhaps you’re upgrading your existing machine, or starting a new role with a fresh corporate setup. The excitement is palpable, but then reality hits: the painstaking process of recreating your perfect development environment.&lt;/p&gt;

&lt;p&gt;For years, I’ve lived this saga. Like many of you, I have my carefully curated arsenal of tools, fonts, and configurations that make me productive. My terminal needs to look just right, my version managers must be in place, and a dozen specific CLI utilities are non-negotiable.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Deja Vu of Re-Setup
&lt;/h2&gt;

&lt;p&gt;The problem isn’t just the initial setup; it’s the &lt;strong&gt;memory&lt;/strong&gt; part. I’d spend hours, sometimes days, painstakingly recalling, searching, and reinstalling. Let me give you some concrete examples of the frustration:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Elusive brew Formula:&lt;/strong&gt; You remember using &lt;code&gt;brew&lt;/code&gt; to install that niche CLI tool for managing cloud resources, but was it brew install &lt;code&gt;aws-cli&lt;/code&gt; or &lt;code&gt;brew install awscli&lt;/code&gt;? Did it have a specific &lt;code&gt;--with-zsh-completion&lt;/code&gt; flag? Or was it &lt;code&gt;aws-cli@2&lt;/code&gt; because the latest version broke a script? You spend 15 minutes in brew search and then another 10 digging through old documentation or &lt;code&gt;~/.zsh_history&lt;/code&gt; (if you even remembered to back it up).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Go Tooling Conundrum:&lt;/strong&gt; You need &lt;code&gt;protoc-gen-go-grpc&lt;/code&gt;. Did you &lt;code&gt;go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest&lt;/code&gt;? Or was it an older &lt;code&gt;v1.2.3&lt;/code&gt; because the team's build system isn't on the newest &lt;code&gt;protobuf&lt;/code&gt;? Or, even worse, did you download a pre-compiled binary from a &lt;strong&gt;GitHub Release&lt;/strong&gt; because it was faster, and now you have no idea where it came from?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Perfect Font, Gone:&lt;/strong&gt; Your beautiful coding font, say &lt;strong&gt;“Fira Code Nerd Font Mono”&lt;/strong&gt; suddenly isn’t rendering correctly. Was it version &lt;code&gt;v3.0.2&lt;/code&gt; or &lt;code&gt;v3.1.1&lt;/code&gt; of &lt;strong&gt;Nerd Fonts&lt;/strong&gt;? And which specific &lt;code&gt;*.ttf&lt;/code&gt; file within the archive did you copy to &lt;code&gt;~/Library/Fonts&lt;/code&gt;? Now you're hunting through &lt;strong&gt;GitHub Releases&lt;/strong&gt;, downloading multi-gigabyte archives just to find that one precise file.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Dotfiles’ Blind Spots:&lt;/strong&gt; While a &lt;code&gt;~/.dotfiles&lt;/code&gt; repository is a lifesaver for shell aliases (&lt;code&gt;alias gcm='git commit -m'&lt;/code&gt;) or Vim plugins, they notoriously fall short when it comes to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Actual Software Installation:&lt;/strong&gt; Your dotfiles won’t magically install Homebrew, or &lt;code&gt;git&lt;/code&gt; itself, or &lt;code&gt;Node.js&lt;/code&gt;, or the &lt;code&gt;Rust&lt;/code&gt; toolchain. They assume these foundational tools are already there.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Installation Methods:&lt;/strong&gt; Your &lt;code&gt;shellrc&lt;/code&gt; might expect &lt;code&gt;pyenv&lt;/code&gt; to be in your &lt;code&gt;$PATH&lt;/code&gt;, but it won't tell you if &lt;code&gt;pyenv&lt;/code&gt; was installed via &lt;code&gt;brew&lt;/code&gt;, &lt;code&gt;git clone&lt;/code&gt;, or a custom script.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;System-Level Settings:&lt;/strong&gt; Those &lt;strong&gt;macOS&lt;/strong&gt; &lt;code&gt;defaults write&lt;/code&gt; commands that perfect your trackpad speed, hide desktop icons, or ensure hidden files are always visible, these are often scattered notes or manual tweaks, not cleanly managed.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This constant “re-setup tax” was a major pain point, a recurring nightmare that chipped away at my valuable time and focus. I wanted a way to truly encapsulate my &lt;strong&gt;entire&lt;/strong&gt; development environment, not just bits and pieces.&lt;/p&gt;




&lt;h3&gt;
  
  
  My Solution: Introducing &lt;code&gt;setup-devbox&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;That frustration finally boiled over, and I decided to tackle it head-on. I focused on a piece of software that solves this exact problem: &lt;a href="https://github.com/kodelint/setup-devbox" rel="noopener noreferrer"&gt;&lt;code&gt;setup-devbox&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/kodelint/setup-devbox" rel="noopener noreferrer"&gt;&lt;code&gt;setup-devbox&lt;/code&gt;&lt;/a&gt; is my answer to the "new laptop dilemma." It’s a command-line tool that lets you define your entire development environment in &lt;strong&gt;declarative &lt;code&gt;YAML&lt;/code&gt; files&lt;/strong&gt;. This isn't just about listing tools; it's about stating the &lt;strong&gt;desired end-state&lt;/strong&gt; of your machine, which is repeatable every single time, in a format that's both human-readable and machine-executable.&lt;/p&gt;

&lt;h4&gt;
  
  
  Why Declarative &lt;code&gt;YAML&lt;/code&gt;?
&lt;/h4&gt;

&lt;p&gt;The power of declarative YAML is that it acts as your single source of truth. It lives alongside your code in version control, meaning:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Readability:&lt;/strong&gt; It’s easy to glance at &lt;code&gt;tools.yaml&lt;/code&gt; and instantly know what's supposed to be installed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Version Control:&lt;/strong&gt; You can track changes to your environment setup over time, just like you track changes to your application code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Shareability:&lt;/strong&gt; Want to onboard a new team member to an identical setup? Share your &lt;a href="https://github.com/kodelint/setup-devbox" rel="noopener noreferrer"&gt;&lt;code&gt;setup-devbox&lt;/code&gt;&lt;/a&gt; config files.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No More Guesswork:&lt;/strong&gt; No more trying to remember a specific brew flag or the exact go install command. The &lt;code&gt;YAML&lt;/code&gt; specifies it all.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  What &lt;a href="https://github.com/kodelint/setup-devbox" rel="noopener noreferrer"&gt;&lt;code&gt;setup-devbox&lt;/code&gt;&lt;/a&gt; Manages:
&lt;/h4&gt;

&lt;p&gt;When you define your environment, &lt;a href="https://github.com/kodelint/setup-devbox" rel="noopener noreferrer"&gt;&lt;code&gt;setup-devbox&lt;/code&gt;&lt;/a&gt; steps up to handle the heavy lifting across several crucial domains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Tools (and Their Installation Methods!):&lt;/strong&gt; This is where it shines. You define tools like &lt;code&gt;git&lt;/code&gt;, &lt;code&gt;Node.js&lt;/code&gt;, &lt;code&gt;kubectl&lt;/code&gt;, or even specific versions of &lt;code&gt;gh&lt;/code&gt; (GitHub CLI). Crucially, you also tell &lt;a href="https://github.com/kodelint/setup-devbox" rel="noopener noreferrer"&gt;&lt;code&gt;setup-devbox&lt;/code&gt;&lt;/a&gt; how to install them: - &lt;code&gt;brew&lt;/code&gt;: For standard packages on &lt;code&gt;macOS&lt;/code&gt; and &lt;code&gt;Linux&lt;/code&gt;. - &lt;code&gt;cargo&lt;/code&gt;: For your favorite Rust CLI tools. - &lt;code&gt;github&lt;/code&gt;: For tools distributed as &lt;strong&gt;GitHub Releases&lt;/strong&gt; (e.g., specific versions of &lt;code&gt;terraform&lt;/code&gt; or &lt;code&gt;helm&lt;/code&gt;). - &lt;code&gt;url&lt;/code&gt;: For direct downloads of binaries or installers that don't fit other categories (e.g., a specific Go installer &lt;code&gt;.pkg&lt;/code&gt;).&lt;br&gt;
It intelligently uses the correct installer and even handles &lt;code&gt;rename_to&lt;/code&gt; for convenience (e.g., &lt;code&gt;cli&lt;/code&gt; to &lt;code&gt;gh&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;macOS System Settings (&lt;code&gt;defaults write&lt;/code&gt;):&lt;/strong&gt; Tired of manually changing Finder settings or keyboard behaviors after a clean install? &lt;a href="https://github.com/kodelint/setup-devbox" rel="noopener noreferrer"&gt;&lt;code&gt;setup-devbox&lt;/code&gt;&lt;/a&gt; lets you declare those &lt;code&gt;defaults write&lt;/code&gt; commands directly in your &lt;code&gt;settings.yaml&lt;/code&gt;, ensuring consistency every time.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Shell Configuration (&lt;code&gt;.zshrc&lt;/code&gt;, &lt;code&gt;.bashrc&lt;/code&gt; etc.):&lt;/strong&gt; Beyond just aliases, you can define raw lines of configuration to be injected into your shell startup files. This includes everything from &lt;code&gt;$PATH&lt;/code&gt; modifications to eval "&lt;code&gt;$(starship init zsh)&lt;/code&gt;" or complex &lt;code&gt;fzf&lt;/code&gt; bindings.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Fonts:&lt;/strong&gt; My coding experience isn’t complete without specific fonts, often Nerd Fonts. &lt;a href="https://github.com/kodelint/setup-devbox" rel="noopener noreferrer"&gt;&lt;code&gt;setup-devbox&lt;/code&gt;&lt;/a&gt; automates the download and installation of these, ensuring my terminal looks perfect on every machine.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At present it support &lt;strong&gt;GitHub, Brew, Cargo, Rustup, Go, Pip&lt;/strong&gt; and &lt;strong&gt;Direct URL&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here are examples of my &lt;code&gt;tools.yaml&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;git-spellcheck&lt;/span&gt;
  &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;0.0.1&lt;/span&gt;
  &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;github&lt;/span&gt;
  &lt;span class="na"&gt;repo&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;kodelint/git-spellcheck&lt;/span&gt;
  &lt;span class="na"&gt;tag&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v0.0.1&lt;/span&gt;
  &lt;span class="na"&gt;rename_to&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;git-spellcheck&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;git-pr&lt;/span&gt;
  &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;0.1.0&lt;/span&gt;
  &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;github&lt;/span&gt;
  &lt;span class="na"&gt;repo&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;kodelint/git-pr&lt;/span&gt;
  &lt;span class="na"&gt;tag&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v0.1.0&lt;/span&gt;
  &lt;span class="na"&gt;rename_to&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;git-pr&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cli&lt;/span&gt;
  &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2.74.0"&lt;/span&gt;
  &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;github&lt;/span&gt;
  &lt;span class="na"&gt;repo&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cli/cli&lt;/span&gt;
  &lt;span class="na"&gt;tag&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v2.74.0&lt;/span&gt;
  &lt;span class="na"&gt;rename_to&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gh&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;delta&lt;/span&gt;
  &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0.18.2"&lt;/span&gt;
  &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;github&lt;/span&gt;
  &lt;span class="na"&gt;repo&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dandavison/delta&lt;/span&gt;
  &lt;span class="na"&gt;tag&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;0.18.2&lt;/span&gt;
  &lt;span class="na"&gt;rename_to&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;delta&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Example of &lt;code&gt;fonts.yaml&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;fonts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;0xProto&lt;/span&gt;
  &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;3.4.0&lt;/span&gt;
  &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;github&lt;/span&gt;
  &lt;span class="na"&gt;repo&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ryanoasis/nerd-fonts&lt;/span&gt;
  &lt;span class="na"&gt;tag&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v3.4.0&lt;/span&gt;
  &lt;span class="na"&gt;install_only&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;regular"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Mono"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="s"&gt;Example of shellrc.yaml&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Example of &lt;code&gt;shellrc.yaml&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;shellrc&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;shell&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;zsh&lt;/span&gt;
  &lt;span class="na"&gt;raw_configs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
   &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;export PATH=$HOME/bin:$PATH&lt;/span&gt;
   &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;export PATH=$HOME/.cargo/bin:$PATH&lt;/span&gt;
   &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;export PATH=$HOME/go/bin:$PATH&lt;/span&gt;
   &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;eval "$(starship init zsh)"&lt;/span&gt;
   &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;[&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;-f&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;~/.fzf.zsh&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;]&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;source&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;~/.fzf.zsh"&lt;/span&gt;
   &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;zle -N fzf-history-widget - bindkey '^R' fzf-history-widget&lt;/span&gt;
   &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;export&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;FZF_CTRL_R_OPTS="--no-preview&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;--scheme=history&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;--tiebreak=index&lt;/span&gt;&lt;span class="nv"&gt;   &lt;/span&gt;&lt;span class="s"&gt;--bind=ctrl-r:toggle-sort"'&lt;/span&gt;
   &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt; &lt;span class="err"&gt;export&lt;/span&gt; &lt;span class="err"&gt;FZF_CTRL_T_OPTS="&lt;/span&gt;
      &lt;span class="s"&gt;--preview 'bat --style=numbers --color=always {} || cat {}'&lt;/span&gt;
      &lt;span class="s"&gt;--preview-window=right:80%&lt;/span&gt;
      &lt;span class="s"&gt;--bind ctrl-b:preview-page-up,ctrl-f:preview-page-down"&lt;/span&gt;
&lt;span class="na"&gt;aliases&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;code&lt;/span&gt;
      &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cd $HOME/Documents/github/&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gocode&lt;/span&gt;
      &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cd $HOME/go/src/&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;edconf&lt;/span&gt;
      &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;zed $HOME/.zshrc&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;g&lt;/span&gt;
      &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;git&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gs&lt;/span&gt;
      &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;g status&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Example of &lt;code&gt;settings.yaml&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;settings&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;macos&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;domain&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;NSGlobalDomain&lt;/span&gt;
      &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AppleShowAllExtensions&lt;/span&gt;
      &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;true"&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bool&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;domain&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;com.apple.finder&lt;/span&gt;
      &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AppleShowAllFiles&lt;/span&gt;
      &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;true"&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bool&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;domain&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;com.apple.dock&lt;/span&gt;
      &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;expose-animation-duration&lt;/span&gt;
      &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0.1"&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;float&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;domain&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;NSGlobalDomain&lt;/span&gt;
      &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;KeyRepeat&lt;/span&gt;
      &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1"&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;int&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;domain&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;com.apple.finder&lt;/span&gt;
      &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ShowPathbar&lt;/span&gt;
      &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;true"&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bool&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  The Magic of State Management
&lt;/h4&gt;

&lt;p&gt;The core idea is simple yet powerful: you run &lt;code&gt;setup-devbox now&lt;/code&gt;, and it springs into action. But it's not a dumb script that reinstalls everything every time. It leverages an internal &lt;code&gt;state.json&lt;/code&gt; file. This file acts as &lt;code&gt;setup-devbox&lt;/code&gt;'s memory, keeping track of what has already been installed and configured, and how.&lt;/p&gt;

&lt;p&gt;This means that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Idempotency:&lt;/strong&gt; Running &lt;code&gt;setup-devbox&lt;/code&gt; now multiple times won't break anything or perform redundant work. If a tool is already installed and matches your desired version, &lt;code&gt;setup-devbox&lt;/code&gt; simply skips it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Efficiency:&lt;/strong&gt; Only missing or outdated components are installed or updated, saving you precious time and bandwidth.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Reliability:&lt;/strong&gt; The &lt;code&gt;state.json&lt;/code&gt; ensures that your environment progresses predictably towards the desired state you've defined.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This means that whether I’m upgrading my MacBook, spinning up a new virtual machine, or onboarding onto a client’s specific environment, I can replicate my ideal setup with minimal effort. The entire “re-setup tax” is almost eliminated, freeing me up to do what I love: &lt;strong&gt;develop&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reclaim Your Setup Time, Forever
&lt;/h3&gt;

&lt;p&gt;Building &lt;a href="https://github.com/kodelint/setup-devbox" rel="noopener noreferrer"&gt;&lt;code&gt;setup-devbox&lt;/code&gt;&lt;/a&gt; has transformed my personal development workflow from a recurring chore into a one-command automation. My development environment is no longer a collection of scattered memories and manual steps; it’s a declarative, version-controlled blueprint that setup-devbox brings to life with intelligent efficiency.&lt;/p&gt;

&lt;p&gt;If you, like me, have suffered the “&lt;strong&gt;new laptop setup&lt;/strong&gt;” headache too many times, I genuinely believe setup-devbox can be a game-changer for you. It's my personal solution to a universal developer problem, and I'm excited to share it with the community.&lt;/p&gt;

&lt;p&gt;Head over to the GitHub Repository: &lt;a href="https://github.com/kodelint/setup-devbox" rel="noopener noreferrer"&gt;&lt;code&gt;setup-devbox&lt;/code&gt;&lt;/a&gt;, explore the configuration examples, and give &lt;a href="https://github.com/kodelint/setup-devbox" rel="noopener noreferrer"&gt;&lt;code&gt;setup-devbox&lt;/code&gt;&lt;/a&gt; a try. I'm actively developing it, and your feedback, ideas, or even contributions would be incredibly valuable.&lt;/p&gt;

&lt;h4&gt;
  
  
  Repository: &lt;a href="https://github.com/kodelint/setup-devbox" rel="noopener noreferrer"&gt;&lt;code&gt;setup-devbox&lt;/code&gt;&lt;/a&gt;
&lt;/h4&gt;

&lt;h4&gt;
  
  
  Happy Developing!!
&lt;/h4&gt;

</description>
      <category>rust</category>
      <category>macos</category>
      <category>productivity</category>
      <category>cli</category>
    </item>
    <item>
      <title>Git Selective Ignore: Because Sometimes You Need to Keep Secrets from Git (But Not From Yourself)</title>
      <dc:creator>Satyajit Roy</dc:creator>
      <pubDate>Wed, 17 Aug 2022 02:24:56 +0000</pubDate>
      <link>https://forem.com/deadlock/golang-garbage-collection-in-general-1o2l</link>
      <guid>https://forem.com/deadlock/golang-garbage-collection-in-general-1o2l</guid>
      <description>&lt;h1&gt;
  
  
  Git Selective Ignore: Because Sometimes You Need to Keep Secrets from Git (But Not From Yourself)
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;Or: How I Learned to Stop Worrying and Love Committing Without Fear&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Picture this:&lt;/strong&gt; It's &lt;strong&gt;2 AM&lt;/strong&gt;, you're deep in the coding zone, your coffee has gone cold (again), and you've just figured out why your API integration wasn't working. You quickly hardcode that API key to test it out—just temporarily, of course. The fix works! You're ecstatic. You commit your changes with a triumphant message: "Fixed the thing that was broken!"&lt;/p&gt;

&lt;p&gt;Fast forward to &lt;strong&gt;9 AM&lt;/strong&gt; the next day. Your security team is having what can only be described as a "spirited discussion" about API keys appearing in your Git history. Your coffee is cold again, but this time it's because your blood has turned to ice.&lt;/p&gt;

&lt;p&gt;Sound familiar? Welcome to the club. We have t-shirts, but ironically, we can't put the design in our Git repo because it has our logo's secret color codes in it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Git Philosophy: Everything Is Sacred (Even Your Mistakes)
&lt;/h2&gt;

&lt;p&gt;Git operates on a beautiful but sometimes inconvenient principle: &lt;strong&gt;everything matters&lt;/strong&gt;. When Linus Torvalds created &lt;code&gt;Git&lt;/code&gt; in 2005 &lt;em&gt;(in just 10 days, because apparently some people are just built different)&lt;/em&gt;, he designed it around the idea that every character in your codebase tells a story. Git treats files as atomic units—either the whole file is tracked, or it isn't.&lt;/p&gt;

&lt;p&gt;This philosophy has served us well. Git's immutable history and complete file tracking have prevented countless disasters. But it also means that when you accidentally commit &lt;code&gt;API_KEY = "sk_live_definitely_not_my_real_key_12345"&lt;/code&gt;, Git faithfully preserves that mistake for all eternity, like a digital time capsule of your poor judgment.&lt;/p&gt;

&lt;p&gt;The traditional &lt;code&gt;.gitignore&lt;/code&gt; file is fantastic for what it does—ignoring entire files or directories. Need to keep your &lt;code&gt;node_modules&lt;/code&gt; out of the repo? Perfect. Don't want your IDE settings cluttering up the project? Easy. But try telling &lt;code&gt;.gitignore&lt;/code&gt; to ignore just line 42 of &lt;code&gt;config.py&lt;/code&gt; while keeping the rest of the file, and it'll give you the digital equivalent of a blank stare.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enter the Real World: Where Perfect Theory Meets Messy Reality
&lt;/h2&gt;

&lt;p&gt;Here's the thing about development: we live in a world of temporary hacks that become permanent features, debug statements that somehow make it to production, and test configurations that work so well locally that we forget they contain production credentials.&lt;/p&gt;

&lt;h3&gt;
  
  
  Consider these common scenarios:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Debug Block&lt;/strong&gt;: Those &lt;code&gt;console.log&lt;/code&gt; statements that helped you figure out why the async function was returning undefined, but now clutter your clean, professional codebase.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Local Config&lt;/strong&gt;: Database connection strings, API endpoints, and feature flags that need to be different for local development but shouldn't make their way into the shared repository.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Temporary Experiment&lt;/strong&gt;: That experimental algorithm you're testing, complete with hardcoded values and performance logging, sitting right in the middle of your otherwise pristine production code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Security Nightmare&lt;/strong&gt;: API keys, tokens, passwords, and other credentials that somehow always seem to sneak into codebases despite our best intentions.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Traditional Solutions: A Comedy of Errors
&lt;/h2&gt;

&lt;p&gt;Let's look at how we typically handle these situations:&lt;/p&gt;

&lt;h3&gt;
  
  
  Option 1: The Paranoid Approach
&lt;/h3&gt;

&lt;p&gt;You meticulously remove every sensitive line before committing, then carefully add them back after. This works great until you forget to add something back, spend three hours debugging why your app won't start, and realize you removed the line that sets up the database connection.&lt;/p&gt;

&lt;h3&gt;
  
  
  Option 2: The Environment Variable Dance
&lt;/h3&gt;

&lt;p&gt;You move everything to environment variables. This is actually good practice, but now your local setup requires a &lt;code&gt;.env&lt;/code&gt; file with 47 different variables, and new developers need a PhD in configuration management just to run the project locally.&lt;/p&gt;

&lt;h3&gt;
  
  
  Option 3: The Separate Config Files
&lt;/h3&gt;

&lt;p&gt;You keep sensitive configs in separate files and gitignore those files entirely. This works until you need to share the structure of the config with your team, or until someone accidentally deletes the local config file and has no template to recreate it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Option 4: The Git Surgery
&lt;/h3&gt;

&lt;p&gt;You realize you've committed something sensitive and spend the next hour learning about &lt;code&gt;git filter-branch&lt;/code&gt; and &lt;code&gt;BFG Repo-Cleaner&lt;/code&gt;. By the time you're done, you've rewritten half your Git history, broken everyone else's local repos, and you're pretty sure you've violated several laws of physics.&lt;/p&gt;

&lt;h2&gt;
  
  
  Git Selective Ignore: A Surgical Solution
&lt;/h2&gt;

&lt;p&gt;This is where &lt;code&gt;git-selective-ignore&lt;/code&gt; comes in. Think of it as a precision instrument in a world of sledgehammers.&lt;/p&gt;

&lt;p&gt;
  &lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fkodelint%2Fblog-images%2Fblob%2Fmain%2Fcommon%2F01-git-selecting-ignore.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fkodelint%2Fblog-images%2Fblob%2Fmain%2Fcommon%2F01-git-selecting-ignore.png" alt="git-selective-ignore" width="" height=""&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;Instead of treating files as atomic units, this tool lets you specify exactly which parts of a file should be ignored during commits. It's like having a conversation with Git:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You&lt;/strong&gt;: &lt;em&gt;"Hey Git, commit this file, but ignore lines 13-16, and also any line that contains 'API_KEY', and oh, while you're at it, skip that debug block between the comments."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Git&lt;/strong&gt;: &lt;em&gt;"That's not how I—"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;git-selective-ignore&lt;/strong&gt;: &lt;em&gt;"I got this. &lt;code&gt;Git&lt;/code&gt;, just commit what they want you to commit. Trust me."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Git&lt;/strong&gt;: "...okay, but this feels weird."&lt;/p&gt;

&lt;h2&gt;
  
  
  How It Actually Works (The Magic Behind the Curtain)
&lt;/h2&gt;

&lt;p&gt;The tool operates using Git hooks—specifically &lt;code&gt;pre-commit&lt;/code&gt; and &lt;code&gt;post-commit&lt;/code&gt; hooks. Here's the elegant dance it performs:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Pre-commit&lt;/strong&gt;: Before Git commits your changes, the tool scans your staged files, creates temporary clean versions with the specified content removed, and stages these sanitized versions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Commit&lt;/strong&gt;: Git commits the clean versions to history.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Post-commit&lt;/strong&gt;: The tool restores your original files, so your working directory contains all your local configs, debug statements, and temporary code.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It's like having a butler who tidies up your room before guests arrive, then puts everything back exactly where you left it after they leave.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real-World Example: The API Key Tango
&lt;/h2&gt;

&lt;p&gt;Let's say you have this in your &lt;code&gt;main.rs&lt;/code&gt; and &lt;code&gt;lib.rs&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Starting application..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// DEBUG BLOCK START&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Debug: Application started in debug mode"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// DEBUG BLOCK END&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;API_KEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"sk_live_1234567890abcdef"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Using API key: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;API_KEY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="cm"&gt;/* Temporary lines for testing - remove before prod */&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;temp_feature&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"experimental_feature_xyz"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Testing temporary feature: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;temp_feature&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="cm"&gt;/* End temporary section */&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;SECRET&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Some secret value"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"SECRET configured"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Application completed successfully"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Another Test"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;GITHUB_TOKEN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"github_fake_token_093790841-831-8lncdlwnelkqix12=-1x;xm;m"&lt;/span&gt;

    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{} &amp;lt;- My GitHub Token"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;GITHUB_TOKEN&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;API_KEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;env&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;'API_KEY&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="nn"&gt;env&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;'API_KEY&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"The value of APP_KEY is: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;API_KEY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nd"&gt;eprintln!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Error getting environment variable {}: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;'API_KEY&lt;/span&gt;'&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With traditional &lt;code&gt;Git&lt;/code&gt;, you have two choices:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Commit everything (including secrets) 😬😬😬&lt;/li&gt;
&lt;li&gt;Manually clean it up before every commit 🫩🫩🫩&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;With &lt;code&gt;git-selective-ignore&lt;/code&gt;, you set up your patterns once 🕺🏽 💃🏻:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Ignore any lines containing these sensitive terms&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; git-selective-ignore add all API_KEY &lt;span class="nt"&gt;--pattern-type&lt;/span&gt; line-regex
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; git-selective-ignore add all SECRET &lt;span class="nt"&gt;--pattern-type&lt;/span&gt; line-regex

&lt;span class="c"&gt;# Ignore debug blocks&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; git-selective-ignore add all &lt;span class="s2"&gt;"// DEBUG BLOCK START ||| // DEBUG BLOCK END"&lt;/span&gt; &lt;span class="nt"&gt;--pattern-type&lt;/span&gt; block-start-end

&lt;span class="c"&gt;# Ignore specific line ranges for temporary code&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; git-selective-ignore add src/main.rs 13-16 &lt;span class="nt"&gt;--pattern-type&lt;/span&gt; line-range
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now when you commit, Git's history will only contain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Starting application..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Using API key: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;API_KEY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"SECRET configured"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Application completed successfully"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But your local file remains unchanged, so you can keep working with all your debug statements and test configurations intact.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Approach Works Better
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Compared to Manual Cleanup
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No more forgetting&lt;/strong&gt;: You don't have to remember what to remove and add back&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No broken local environments&lt;/strong&gt;: Your working directory always contains what you need&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consistent team experience&lt;/strong&gt;: Everyone gets the same sanitized commits&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Compared to Environment Variables
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Faster iteration&lt;/strong&gt;: No need to restart processes when changing test values&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Better debugging&lt;/strong&gt;: You can see actual values in your code while developing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Simpler onboarding&lt;/strong&gt;: New developers can run the project with sensible defaults&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Compared to Separate Config Files
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No structural divergence&lt;/strong&gt;: The team sees the shape of your configuration&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No lost configs&lt;/strong&gt;: Your local setup is preserved in your working directory&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Version control benefits&lt;/strong&gt;: You can still track changes to the configuration structure&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Advanced Patterns: Getting Surgical
&lt;/h2&gt;

&lt;p&gt;The tool supports several pattern types for different use cases:&lt;/p&gt;

&lt;h3&gt;
  
  
  Line Regex (for scattered sensitive data)
&lt;/h3&gt;

&lt;p&gt;Perfect for API keys, passwords, or debug statements scattered throughout your codebase:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; git-selective-ignore add all &lt;span class="s2"&gt;"console&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="s2"&gt;log.*debug"&lt;/span&gt; &lt;span class="nt"&gt;--pattern-type&lt;/span&gt; line-regex
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Line Ranges (for temporary code blocks)
&lt;/h3&gt;

&lt;p&gt;When you know exactly which lines contain temporary code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; git-selective-ignore add src/config.py 45-52 &lt;span class="nt"&gt;--pattern-type&lt;/span&gt; line-range
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Block Start/End (for structured temporary sections)
&lt;/h3&gt;

&lt;p&gt;When you use comments to mark temporary code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; git-selective-ignore add all &lt;span class="s2"&gt;"// TODO: REMOVE ||| // END TODO"&lt;/span&gt; &lt;span class="nt"&gt;--pattern-type&lt;/span&gt; block-start-end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Philosophy Shift: From Binary to Granular
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;git-selective-ignore&lt;/code&gt; represents a philosophical shift in how we think about version control. Instead of the binary choice of "track this file or don't," we get granular control over what parts of our development process should be preserved in history.&lt;/p&gt;

&lt;p&gt;This isn't about hiding poor practices—it's about recognizing that the code we need to develop effectively isn't always the same as the code we want to preserve historically. It's the difference between your private workshop (messy, full of tools and work-in-progress) and the finished product you show to the world.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started: Your First Steps into Selective Ignoring
&lt;/h2&gt;

&lt;p&gt;Installation is straightforward. You can use their &lt;a href="https://github.com/kodelint/setup-devbox" rel="noopener noreferrer"&gt;setup-devbox&lt;/a&gt; tool, download from releases, or build from source:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Build from source&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; git clone https://github.com/kodelint/git-selective-ignore.git
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;git-selective-ignore
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; cargo &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--path&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then in any repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Initialize selective ignore&lt;/span&gt;
git-selective-ignore init

&lt;span class="c"&gt;# Install the Git hooks&lt;/span&gt;
git-selective-ignore install-hooks

&lt;span class="c"&gt;# Add your first pattern&lt;/span&gt;
git-selective-ignore add all &lt;span class="s2"&gt;"API_KEY"&lt;/span&gt; &lt;span class="nt"&gt;--pattern-type&lt;/span&gt; line-regex

&lt;span class="c"&gt;# Check what would be ignored&lt;/span&gt;
git-selective-ignore status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The tool stores its configuration in &lt;code&gt;.git/selective-ignore.toml&lt;/code&gt;, so each repository can have its own rules without affecting others.&lt;/p&gt;

&lt;p&gt;You can also see the violations in the code base with &lt;code&gt;status&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; git-selective-ignore status
✓ Configuration is valid.
   ├─ Line Range Pattern &lt;span class="s1"&gt;'13-16'&lt;/span&gt;: 4 line&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; matched
   │  └─ Lines 13-16
   ├─ Regex Pattern &lt;span class="s1"&gt;'API_KEY'&lt;/span&gt;: 1 line&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; matched
   │  └─ Line 10
   ├─ Regex Pattern &lt;span class="s1"&gt;'GITHUB_TOKEN'&lt;/span&gt;: 1 line&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; matched
   │  └─ Line 20
   ├─ Block Pattern &lt;span class="s1"&gt;'// DEBUG BLOCK START ||| // DEBUG BLOCK END'&lt;/span&gt;: 3 line&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; matched
   │  └─ Lines 6-8
   ├─ Regex Pattern &lt;span class="s1"&gt;'SECRET'&lt;/span&gt;: 1 line&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; matched
   │  └─ Line 18
   └─ Summary: 10 line&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; ignored, 17 line&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; remaining &lt;span class="o"&gt;(&lt;/span&gt;of 27 total&lt;span class="o"&gt;)&lt;/span&gt;
   ├─ Regex Pattern &lt;span class="s1"&gt;'GITHUB_TOKEN'&lt;/span&gt;: 1 line&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; matched
   │  └─ Line 7
   └─ Summary: 1 line&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; ignored, 18 line&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; remaining &lt;span class="o"&gt;(&lt;/span&gt;of 19 total&lt;span class="o"&gt;)&lt;/span&gt;
📊 Git Selective Ignore Status Report
&lt;span class="o"&gt;=====================================&lt;/span&gt;
🎯 Specifically Configured Files:
🟡 src/main.rs &lt;span class="o"&gt;(&lt;/span&gt;8 patterns, 10/27 lines ignored, 37.0%&lt;span class="o"&gt;)&lt;/span&gt;

🌐 Files Affected by Global &lt;span class="s1"&gt;'ALL'&lt;/span&gt; Patterns:
🟡 src/lib.rs &lt;span class="o"&gt;(&lt;/span&gt;6 patterns, 1/19 lines ignored, 5.3%&lt;span class="o"&gt;)&lt;/span&gt;

📈 Summary:
  Total files: 2
  Total patterns: 8
  Total ignored lines: 11
  Files with issues: 2

📋 Breakdown:
  Specifically configured files: 1
  Files affected by &lt;span class="s1"&gt;'ALL'&lt;/span&gt; patterns only: 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use &lt;code&gt;list&lt;/code&gt; to see what Ignore Patterns are installed&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; git-selective-ignore list
✓ Configuration is valid.

📁 File: all
  🔍 ID: 78ed02f4-db7c-4921-b565-5e8986f19705 | Type: LineRegex | Pattern: API_KEY
  🔍 ID: 7fb165d1-bab6-4c79-a13b-51f2f29a88e9 | Type: LineRegex | Pattern: APP_KEY
  🔍 ID: 02b17597-bb85-428c-be56-3d0cd4a3c44b | Type: LineRegex | Pattern: GITHUB_TOKEN
  🔍 ID: 76447f06-dd03-4c3b-b27a-b611579e9cb8 | Type: BlockStartEnd | Pattern: // DEBUG BLOCK START &lt;span class="o"&gt;||&lt;/span&gt;| // DEBUG BLOCK END
  🔍 ID: 48f984d1-dd90-4984-99d6-ae6c63c591d6 | Type: LineRegex | Pattern: SECRET
  🔍 ID: b9a54bc2-048d-4fa0-b6ff-dc66aff6e706 | Type: LineRegex | Pattern: password

📁 File: src/main.rs
  🔍 ID: 31ca2ff0-90d8-47ea-90db-413cedf09bcf | Type: LineRange | Pattern: 13-16
  🔍 ID: a941d428-87ed-4378-898d-d5156723dfd0 | Type: BlockStartEnd | Pattern: /&lt;span class="k"&gt;*&lt;/span&gt; TEMP_CODE_START &lt;span class="k"&gt;*&lt;/span&gt;/ &lt;span class="o"&gt;||&lt;/span&gt;| /&lt;span class="k"&gt;*&lt;/span&gt; TEMP_CODE_END &lt;span class="k"&gt;*&lt;/span&gt;/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  A Word of Caution: With Great Power...
&lt;/h2&gt;

&lt;p&gt;Like any powerful tool, &lt;code&gt;git-selective-ignore&lt;/code&gt; should be used thoughtfully. It's not a license to be sloppy with sensitive data, it's a safety net for the inevitable times when we are human.&lt;/p&gt;

&lt;h4&gt;
  
  
  Remember:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Security is still your responsibility&lt;/strong&gt;: This tool helps prevent accidental commits, but you should still follow security best practices&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Team coordination matters&lt;/strong&gt;: Make sure your team knows which patterns are in place&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test your patterns&lt;/strong&gt;: Use the &lt;code&gt;status&lt;/code&gt; command to verify your patterns work as expected&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Future of Granular Version Control
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;git-selective-ignore&lt;/code&gt; points toward a future where version control systems understand that not everything in our working directory needs to be preserved for posterity. It's a tool that acknowledges the messy reality of software development while maintaining the clean history that makes Git so valuable.&lt;/p&gt;

&lt;p&gt;In a world where we're constantly told to "shift left" on security and best practices, tools like this help us maintain good hygiene without sacrificing development velocity. We can iterate quickly, debug effectively, and experiment freely, all while ensuring our Git history remains clean and secure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion: Sleep Better at Night
&lt;/h2&gt;

&lt;p&gt;The next time you're coding at 2 AM and need to hardcode an API key for testing, you can do so without the nagging worry that you'll forget to clean it up. The next time you want to add verbose debug logging to figure out a tricky bug, you can do it without cluttering your team's commit history.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git-selective-ignore&lt;/code&gt; gives you the freedom to develop the way you need to while maintaining the professional, secure codebase your team depends on. It's not just a tool, it's peace of mind.&lt;/p&gt;

&lt;p&gt;And your security team? They'll sleep better too, knowing that those 2 AM coding sessions are far less likely to result in morning meetings about exposed credentials.&lt;/p&gt;

&lt;p&gt;Now if you'll excuse me, I need to go commit some code. Don't worry, I've got selective ignore set up for my embarrassing variable names.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Ready to try git-selective-ignore? Check it out on &lt;a href="https://github.com/kodelint/git-selective-ignore" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; and start committing with confidence.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>rust</category>
      <category>git</category>
      <category>productivity</category>
      <category>cli</category>
    </item>
  </channel>
</rss>
