<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Priyanshu Soni</title>
    <description>The latest articles on DEV Community by Priyanshu Soni (@priyanshu_soni_2a2f21f739).</description>
    <link>https://dev.to/priyanshu_soni_2a2f21f739</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%2F1718976%2F62102edb-f39d-4e6a-a683-5956f57ecf60.jpeg</url>
      <title>DEV Community: Priyanshu Soni</title>
      <link>https://dev.to/priyanshu_soni_2a2f21f739</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/priyanshu_soni_2a2f21f739"/>
    <language>en</language>
    <item>
      <title>Python Internals with Classes</title>
      <dc:creator>Priyanshu Soni</dc:creator>
      <pubDate>Sun, 22 Mar 2026 14:18:49 +0000</pubDate>
      <link>https://dev.to/priyanshu_soni_2a2f21f739/python-internals-with-classes-5ajo</link>
      <guid>https://dev.to/priyanshu_soni_2a2f21f739/python-internals-with-classes-5ajo</guid>
      <description>&lt;h1&gt;
  
  
  I wrote a class in Python with &lt;code&gt;num_instances = 0&lt;/code&gt; and expected it to reset every time a new object was created.
&lt;/h1&gt;

&lt;p&gt;It didn't. Here's why — and it completely changed how I think about memory. 🧠&lt;/p&gt;




&lt;h2&gt;
  
  
  The code that confused me
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ObjectCounter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;num_instances&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;  &lt;span class="c1"&gt;# I thought this resets every time
&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&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;ObjectCounter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;num_instances&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

&lt;span class="n"&gt;obj1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ObjectCounter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  &lt;span class="c1"&gt;# num_instances = 1
&lt;/span&gt;&lt;span class="n"&gt;obj2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ObjectCounter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  &lt;span class="c1"&gt;# num_instances = 2
# Never reset to 0. Why??
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;My assumption was wrong. &lt;code&gt;num_instances = 0&lt;/code&gt; does NOT run on every object creation. It runs &lt;strong&gt;once&lt;/strong&gt; — when Python first reads the class definition.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Think of the class body like a &lt;strong&gt;blueprint being drawn once.&lt;/strong&gt; The &lt;code&gt;__init__&lt;/code&gt; is the construction happening each time. The blueprint is never redrawn.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Diagram 1 — What actually happens step by step
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[ Class defined ]  ──►  [ obj1 = ObjectCounter() ]  ──►  [ obj2 = ObjectCounter() ]
num_instances = 0            __init__ runs                   __init__ runs
  runs ONCE here              count = 1                        count = 2
  lives in class memory       mutates class attribute          counter keeps growing
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;vs a function:&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;num = 0  →  created fresh on every call  →  dies when function returns  →  always resets to 0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Diagram 2 — Stack vs Heap: where things actually live
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────────────┐     ┌──────────────────────────────────────┐
│        STACK MEMORY         │     │            HEAP MEMORY               │
│  Function calls &amp;amp; locals    │     │   Classes, objects, lists, dicts     │
│                             │     │                                      │
│  ┌─────────────────────┐    │     │  ┌──────────────────────────────┐    │
│  │ main()              │    │     │  │  ObjectCounter (class object) │    │
│  │ x, y, z → born &amp;amp;   │    │     │  │  __dict__: {num_instances: 2} │    │
│  │ die here            │    │     │  │  Stays alive entire program   │    │
│  └─────────────────────┘    │     │  └──────────┬──────────┬─────────┘   │
│                             │     │             ▲          ▲             │
│  ┌─────────────────────┐    │     │   ┌─────────┴──┐  ┌───┴────────┐    │
│  │ my_function()       │    │     │   │    obj1     │  │    obj2    │    │
│  │ num = 0             │    │     │   │  instance   │  │  instance  │    │
│  │ reset every call    │    │     │   └─────────────┘  └────────────┘    │
│  └─────────────────────┘    │     │                                      │
│                             │     │                                      │
│  ✕ temporary                │     │  ✓ permanent (until GC)             │
│  ✕ dies when fn returns     │     │  ✓ shared across all instances      │
│  ✕ no shared state          │     │  ✓ mutated in place, never reset    │
└─────────────────────────────┘     └──────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Diagram 3 — The mind-bending part: variables are just labels
&lt;/h2&gt;

&lt;p&gt;In Python, a variable doesn't &lt;em&gt;hold&lt;/em&gt; a value. It's just a &lt;strong&gt;label pointing to an object on the heap.&lt;/strong&gt; Even &lt;code&gt;x = 5&lt;/code&gt; — that integer is a full heap object with its own memory address.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Stack (names)            Heap (objects)
┌───────────┐
│  a = ─────┼──────────► ┌─────────────────────┐
└───────────┘      ┌────►│  list: [1, 2, 3, 4] │
┌───────────┐      │     │  ref count = 2       │
│  b = ─────┼──────┘     └─────────────────────┘
└───────────┘

b.append(4) also changes a!
Both names point to the same object.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Diagram 4 — Python's secret: integer interning
&lt;/h2&gt;

&lt;p&gt;Python pre-creates integers from &lt;code&gt;-5 to 256&lt;/code&gt; and reuses them forever. Beyond that, new objects are made each time.&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="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;    &lt;span class="c1"&gt;# True  → SAME object in memory!
&lt;/span&gt;
&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;    &lt;span class="c1"&gt;# False → different objects
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Small int (-5 to 256): interned        Large int: new object each time

┌──────────┐                           ┌──────────┐     ┌──────────────┐
│  a = 5   │──┐                        │ a = 1000 │────►│ int: 1000 (A)│
└──────────┘  ├──► ┌──────────────┐    └──────────┘     └──────────────┘
              │    │   int: 5     │
┌──────────┐  │    │ shared forever│   ┌──────────┐     ┌──────────────┐
│  b = 5   │──┘    └──────────────┘   │ b = 1000 │────►│ int: 1000 (B)│
└──────────┘                          └──────────┘     └──────────────┘

  a is b → True                          a is b → False
  id(a) == id(b) ✓                       id(a) != id(b) ✗
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Diagram 5 — How memory gets freed: reference counting
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;x = [1,2,3]   ──►   y = x      ──►    del y      ──►    del x
ref count = 1       ref count = 2    ref count = 1     ref count = 0
                                                          → freed! 🗑️
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When ref count hits &lt;strong&gt;0&lt;/strong&gt;, Python automatically frees that memory from the heap.&lt;br&gt;
No manual &lt;code&gt;malloc&lt;/code&gt;/&lt;code&gt;free&lt;/code&gt; needed — unlike C/C++.&lt;/p&gt;




&lt;h2&gt;
  
  
  The full picture
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌──────────────────────────────────────────────────┐
│                   HEAP MEMORY                    │
│                                                  │
│   type (metaclass)                               │
│     ▲        ▲                                   │
│     │        │                                   │
│    int      str        ← built-in classes        │
│     ▲                                            │
│     │                                            │
│  ObjectCounter         ← your class              │
│  { num_instances: 2 }                            │
│     ▲        ▲                                   │
│     │        │                                   │
│  instance_1  instance_2  ← your objects          │
│                                                  │
│  5, 256, "hello"  ← interned primitives          │
└──────────────────────────────────────────────────┘

┌──────────────────────────────────────────────────┐
│                  STACK MEMORY                    │
│  x, y ────────────────────────► (point to        │
│                                   heap objects)  │
└──────────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;One question about a class counter led me to understand &lt;strong&gt;stack vs heap, reference semantics, interning, and garbage collection.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Python hides a lot of complexity behind clean syntax. But when you peek under the hood, it's elegant all the way down.&lt;/p&gt;

&lt;p&gt;If this was useful, I write about things I'm actively learning as an SDE. Follow along. 🚀&lt;/p&gt;

&lt;p&gt;#Python #SoftwareEngineering #WebDevelopment #Programming #LearningInPublic #ComputerScience #100DaysOfCode&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Git Stash</title>
      <dc:creator>Priyanshu Soni</dc:creator>
      <pubDate>Tue, 17 Mar 2026 16:56:25 +0000</pubDate>
      <link>https://dev.to/priyanshu_soni_2a2f21f739/git-stash-2od9</link>
      <guid>https://dev.to/priyanshu_soni_2a2f21f739/git-stash-2od9</guid>
      <description>&lt;h2&gt;
  
  
  Mastering git stash
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;A deep dive into the use cases, workflow patterns, and hidden pitfalls of one of Git's most underappreciated commands.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;What is git stash?&lt;/li&gt;
&lt;li&gt;How it works internally&lt;/li&gt;
&lt;li&gt;Core use cases&lt;/li&gt;
&lt;li&gt;Essential commands&lt;/li&gt;
&lt;li&gt;Advanced patterns&lt;/li&gt;
&lt;li&gt;Bottlenecks &amp;amp; pitfalls&lt;/li&gt;
&lt;li&gt;Stash vs. alternatives&lt;/li&gt;
&lt;li&gt;Quick reference cheatsheet&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  1. What is git stash?
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;git stash&lt;/code&gt; is a Git command that temporarily shelves (stashes) changes you've made to your working directory so you can switch context — then come back and re-apply them later. Think of it as a clipboard for your in-progress work.&lt;/p&gt;

&lt;p&gt;It captures both staged and unstaged modifications, stores them on an internal stack, and restores your working directory to match the last commit — giving you a clean slate without forcing you to make a premature commit.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The stash is local to your machine. It is never pushed to a remote, which makes it ideal for temporary, personal work-in-progress storage rather than sharing incomplete work.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  2. How it works internally
&lt;/h2&gt;

&lt;p&gt;Under the hood, &lt;code&gt;git stash&lt;/code&gt; creates two (or three) commits in your repository's object store and records them as a special reference under &lt;code&gt;refs/stash&lt;/code&gt;. The stash is structured as a merge commit.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Working tree (dirty) → git stash → Clean tree (HEAD) → Work elsewhere → git stash pop → Restored
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Git stores three objects per stash entry:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A commit for the &lt;strong&gt;index&lt;/strong&gt; (staged changes)&lt;/li&gt;
&lt;li&gt;A commit for the &lt;strong&gt;working tree&lt;/strong&gt; (unstaged changes)&lt;/li&gt;
&lt;li&gt;Optionally a third commit for &lt;strong&gt;untracked files&lt;/strong&gt; when &lt;code&gt;-u&lt;/code&gt; is used&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The stash reference forms a linked list — a stack — where &lt;code&gt;stash@{0}&lt;/code&gt; is always the most recent entry.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Core use cases
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Emergency hotfix
&lt;/h3&gt;

&lt;p&gt;You're mid-feature when a critical production bug lands. Stash your work, fix the bug on &lt;code&gt;main&lt;/code&gt;, release — then pop your stash and carry on.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git stash push &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"WIP: user auth refactor"&lt;/span&gt;
git checkout main
&lt;span class="c"&gt;# fix the bug, commit, push&lt;/span&gt;
git checkout feature/auth
git stash pop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Branch switching
&lt;/h3&gt;

&lt;p&gt;Git won't let you switch branches with a dirty working tree if the changes conflict. Stash eliminates the friction of making a temporary commit just to change context.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git stash
git checkout other-branch
&lt;span class="c"&gt;# do your thing&lt;/span&gt;
git checkout original-branch
git stash pop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Experiment isolation
&lt;/h3&gt;

&lt;p&gt;Run your test suite from a clean baseline. Stash your experimental changes, test, then restore — without polluting your commit history.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git stash push &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"experimental: new caching layer"&lt;/span&gt;
npm &lt;span class="nb"&gt;test&lt;/span&gt;          &lt;span class="c"&gt;# test against clean HEAD&lt;/span&gt;
git stash pop     &lt;span class="c"&gt;# restore experiment&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Pulling upstream changes
&lt;/h3&gt;

&lt;p&gt;Avoid merge conflicts during a pull by stashing local uncommitted changes first, pulling, then popping.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git stash
git pull &lt;span class="nt"&gt;--rebase&lt;/span&gt;
git stash pop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Wrong branch commit prep
&lt;/h3&gt;

&lt;p&gt;Started work on the wrong branch? Stash the changes, check out the correct branch, and pop. Your changes land exactly where they should.&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;# Oops — we're on main&lt;/span&gt;
git stash
git checkout feature/correct-branch
git stash pop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Code review baseline
&lt;/h3&gt;

&lt;p&gt;Reviewing a colleague's PR while mid-feature? Stash yours, check out their branch cleanly, review, then return to exactly where you left off.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git stash push &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"WIP: payment flow"&lt;/span&gt;
git fetch origin
git checkout &lt;span class="nb"&gt;pr&lt;/span&gt;/teammate-branch
&lt;span class="c"&gt;# review their code&lt;/span&gt;
git checkout my-feature-branch
git stash pop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  4. Essential commands
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Saving a stash
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Basic stash — saves tracked modified files&lt;/span&gt;
git stash

&lt;span class="c"&gt;# With a descriptive message (highly recommended)&lt;/span&gt;
git stash push &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"WIP: refactor auth middleware"&lt;/span&gt;

&lt;span class="c"&gt;# Include untracked files&lt;/span&gt;
git stash push &lt;span class="nt"&gt;-u&lt;/span&gt;

&lt;span class="c"&gt;# Include everything — tracked, untracked, AND ignored&lt;/span&gt;
git stash push &lt;span class="nt"&gt;-a&lt;/span&gt;

&lt;span class="c"&gt;# Stash only specific files (partial stash)&lt;/span&gt;
git stash push &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"only auth"&lt;/span&gt; src/auth.ts src/middleware.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Listing and inspecting stashes
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# List all stash entries&lt;/span&gt;
git stash list
&lt;span class="c"&gt;# stash@{0}: On main: WIP: refactor auth middleware&lt;/span&gt;
&lt;span class="c"&gt;# stash@{1}: On feature/payments: add stripe webhook handler&lt;/span&gt;
&lt;span class="c"&gt;# stash@{2}: WIP on hotfix/login: fix null pointer&lt;/span&gt;

&lt;span class="c"&gt;# Show what's in a stash (summary)&lt;/span&gt;
git stash show stash@&lt;span class="o"&gt;{&lt;/span&gt;1&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;# Show full diff of a stash&lt;/span&gt;
git stash show &lt;span class="nt"&gt;-p&lt;/span&gt; stash@&lt;span class="o"&gt;{&lt;/span&gt;1&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Restoring a stash
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Pop: apply latest stash AND remove from stack&lt;/span&gt;
git stash pop

&lt;span class="c"&gt;# Apply: apply but KEEP the stash entry (safer)&lt;/span&gt;
git stash apply stash@&lt;span class="o"&gt;{&lt;/span&gt;2&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;# Apply to a new branch (avoids conflicts on current branch)&lt;/span&gt;
git stash branch feature/new-branch stash@&lt;span class="o"&gt;{&lt;/span&gt;0&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Removing stashes
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Drop a specific stash entry&lt;/span&gt;
git stash drop stash@&lt;span class="o"&gt;{&lt;/span&gt;1&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;# Nuke the entire stash list — irreversible!&lt;/span&gt;
git stash clear
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  5. Advanced patterns
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Partial stashing with interactive mode
&lt;/h3&gt;

&lt;p&gt;One of the most powerful but underused features is &lt;code&gt;--patch&lt;/code&gt; mode, which lets you selectively stash only specific hunks within a file — not the entire file.&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;# Interactively choose which hunks to stash&lt;/span&gt;
git stash push &lt;span class="nt"&gt;--patch&lt;/span&gt;

&lt;span class="c"&gt;# Prompt options:&lt;/span&gt;
&lt;span class="c"&gt;# y = stash this hunk&lt;/span&gt;
&lt;span class="c"&gt;# n = skip this hunk&lt;/span&gt;
&lt;span class="c"&gt;# s = split into smaller hunks&lt;/span&gt;
&lt;span class="c"&gt;# e = manually edit the hunk&lt;/span&gt;
&lt;span class="c"&gt;# q = quit (stash what's been selected so far)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Preserving index state on restore
&lt;/h3&gt;

&lt;p&gt;By default, &lt;code&gt;git stash pop&lt;/code&gt; doesn't restore your staging area (index) — it dumps everything into the working tree as unstaged. Use &lt;code&gt;--index&lt;/code&gt; to preserve what was staged vs. unstaged.&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;# Restore both working tree AND index state&lt;/span&gt;
git stash pop &lt;span class="nt"&gt;--index&lt;/span&gt;

&lt;span class="c"&gt;# Or with apply (keeps stash entry in stack)&lt;/span&gt;
git stash apply &lt;span class="nt"&gt;--index&lt;/span&gt; stash@&lt;span class="o"&gt;{&lt;/span&gt;0&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Creating a branch from a stash
&lt;/h3&gt;

&lt;p&gt;If your stash would conflict with your current branch because the codebase has diverged, create a new branch from the commit that existed when you stashed:&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;# Branches from the stash's original parent commit&lt;/span&gt;
git stash branch feature/recovered-work stash@&lt;span class="o"&gt;{&lt;/span&gt;0&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="c"&gt;# Switched to a new branch 'feature/recovered-work'&lt;/span&gt;
&lt;span class="c"&gt;# Changes to be committed:&lt;/span&gt;
&lt;span class="c"&gt;#   modified:   src/auth.ts&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is particularly useful when you've been sitting on a stash for a long time and the branch has moved on significantly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stashing with a keep-index option
&lt;/h3&gt;

&lt;p&gt;If you only want to stash the unstaged changes (leaving your staged changes intact and visible in the index), use &lt;code&gt;--keep-index&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;# Stash only unstaged changes; keep staged changes as-is&lt;/span&gt;
git stash push &lt;span class="nt"&gt;--keep-index&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"only unstaged"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Recovering a lost stash
&lt;/h3&gt;

&lt;p&gt;If you accidentally drop a stash before it was garbage-collected, you can recover it:&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;# Find dangling commit objects&lt;/span&gt;
git fsck &lt;span class="nt"&gt;--lost-found&lt;/span&gt;

&lt;span class="c"&gt;# Look through the output for commit objects&lt;/span&gt;
&lt;span class="c"&gt;# Then inspect them&lt;/span&gt;
git show &amp;lt;dangling-commit-hash&amp;gt;

&lt;span class="c"&gt;# If it's your stash, apply it directly&lt;/span&gt;
git stash apply &amp;lt;dangling-commit-hash&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Warning:&lt;/strong&gt; This only works before &lt;code&gt;git gc&lt;/code&gt; runs. Once garbage collection collects the dangling object, it is gone permanently.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  6. Bottlenecks &amp;amp; pitfalls
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Stash entries are easy to lose
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;git stash clear&lt;/code&gt; and &lt;code&gt;git stash drop&lt;/code&gt; are irreversible under normal usage. Once dropped, entries are not shown in &lt;code&gt;git log&lt;/code&gt; and become dangling objects, eventually collected by &lt;code&gt;git gc&lt;/code&gt;. Lost stashes can only be recovered via &lt;code&gt;git fsck --lost-found&lt;/code&gt; — and only before garbage collection runs.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. No automatic inclusion of untracked files
&lt;/h3&gt;

&lt;p&gt;By default, &lt;code&gt;git stash&lt;/code&gt; only saves &lt;strong&gt;tracked&lt;/strong&gt; files. New files you haven't run &lt;code&gt;git add&lt;/code&gt; on are completely ignored. This silently leaves behind context — a new config file, a test fixture — leading to confusing "it works on my machine" situations when you switch branches.&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;# This does NOT stash new-file.ts if it was never git add-ed&lt;/span&gt;
git stash

&lt;span class="c"&gt;# This does:&lt;/span&gt;
git stash push &lt;span class="nt"&gt;-u&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Merge conflicts on pop
&lt;/h3&gt;

&lt;p&gt;If the branch has changed significantly since you stashed, &lt;code&gt;git stash pop&lt;/code&gt; can produce merge conflicts. When this happens, Git applies the changes but does &lt;strong&gt;not&lt;/strong&gt; automatically drop the stash entry — you're left in a conflicted state with the stash still in the list, leading to accidental double-pops if you're not careful.&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;# Safer pattern: use apply, resolve conflicts, then drop manually&lt;/span&gt;
git stash apply stash@&lt;span class="o"&gt;{&lt;/span&gt;0&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="c"&gt;# ... resolve conflicts ...&lt;/span&gt;
git stash drop stash@&lt;span class="o"&gt;{&lt;/span&gt;0&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Index state is not preserved by default
&lt;/h3&gt;

&lt;p&gt;When you pop or apply a stash, Git does not restore which files were staged vs. unstaged unless you explicitly pass &lt;code&gt;--index&lt;/code&gt;. This breaks your carefully prepared commit structure — suddenly everything is unstaged and you have to re-add files before committing.&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;# Without --index: all changes land unstaged&lt;/span&gt;
git stash pop

&lt;span class="c"&gt;# With --index: staged/unstaged split is preserved&lt;/span&gt;
git stash pop &lt;span class="nt"&gt;--index&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. The stash stack grows silently
&lt;/h3&gt;

&lt;p&gt;Developers often stash, forget, stash again, and accumulate a pile of entries with useless default messages like &lt;code&gt;WIP on main: abc1234 some commit&lt;/code&gt;. Weeks later, it's impossible to know which stash is which without laboriously inspecting diffs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best practice:&lt;/strong&gt; Always use &lt;code&gt;git stash push -m "descriptive message"&lt;/code&gt;. Treat stash entries like sticky notes — label them or they become clutter.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Not cross-machine or collaborative
&lt;/h3&gt;

&lt;p&gt;Stashes live entirely in your local &lt;code&gt;.git/&lt;/code&gt; directory. They are &lt;strong&gt;never&lt;/strong&gt; pushed to the remote. This means you can't resume stashed work on a different machine, and you can't hand off a stash to a teammate. For any kind of collaboration or remote backup, a WIP commit on a draft branch is far superior.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Stash doesn't track the originating branch
&lt;/h3&gt;

&lt;p&gt;A stash records the commit it was made from, but not the branch name (except in the description). If you apply a stash to a different branch, Git won't warn you — context mismatches can introduce subtle bugs that are hard to trace.&lt;/p&gt;

&lt;h3&gt;
  
  
  8. Submodule and binary file behaviour
&lt;/h3&gt;

&lt;p&gt;Git stash has historically had inconsistent behaviour with submodules — changes inside a submodule may not be stashed, or may be stashed incompletely. Similarly, large binary files can make stash operations unexpectedly slow since Git stores entire objects, not deltas, for binary content.&lt;/p&gt;




&lt;h2&gt;
  
  
  7. Stash vs. alternatives
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Approach&lt;/th&gt;
&lt;th&gt;Best for&lt;/th&gt;
&lt;th&gt;Drawbacks&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;git stash&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Short-lived, local context switches. Emergency hotfixes.&lt;/td&gt;
&lt;td&gt;Local only, no history, stack can accumulate&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WIP commit on a branch&lt;/td&gt;
&lt;td&gt;Longer-running work-in-progress. Cross-machine work.&lt;/td&gt;
&lt;td&gt;Slightly more ceremony; must remember to amend or squash later&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;git worktree&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Running two branches simultaneously (e.g. review + develop)&lt;/td&gt;
&lt;td&gt;Uses more disk space, less familiar to most developers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Draft PR / branch push&lt;/td&gt;
&lt;td&gt;Sharing WIP, cross-machine access, remote backup&lt;/td&gt;
&lt;td&gt;Pollutes remote with WIP branches unless managed carefully&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;git checkout -b&lt;/code&gt; new branch&lt;/td&gt;
&lt;td&gt;When the stash work might become a full feature anyway&lt;/td&gt;
&lt;td&gt;Creates a branch — but that's often the right answer&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Rule of thumb:&lt;/strong&gt; If you think you'll need the stashed changes for more than a few hours, or if you might need to access them from another machine, skip the stash and make a WIP commit on a feature branch instead. Stash is powerful for short, local interruptions — but it's a poor long-term storage mechanism.&lt;/p&gt;




&lt;h2&gt;
  
  
  8. Quick reference cheatsheet
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# --- SAVING ---&lt;/span&gt;
git stash                              &lt;span class="c"&gt;# Stash tracked modified files&lt;/span&gt;
git stash push &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"message"&lt;/span&gt;            &lt;span class="c"&gt;# Stash with a descriptive label&lt;/span&gt;
git stash push &lt;span class="nt"&gt;-u&lt;/span&gt;                      &lt;span class="c"&gt;# Include untracked files&lt;/span&gt;
git stash push &lt;span class="nt"&gt;-a&lt;/span&gt;                      &lt;span class="c"&gt;# Include untracked + ignored files&lt;/span&gt;
git stash push &lt;span class="nt"&gt;--patch&lt;/span&gt;                 &lt;span class="c"&gt;# Interactively choose hunks to stash&lt;/span&gt;
git stash push &lt;span class="nt"&gt;--keep-index&lt;/span&gt;            &lt;span class="c"&gt;# Stash only unstaged changes&lt;/span&gt;
git stash push file1.ts file2.ts       &lt;span class="c"&gt;# Stash specific files only&lt;/span&gt;

&lt;span class="c"&gt;# --- INSPECTING ---&lt;/span&gt;
git stash list                         &lt;span class="c"&gt;# List all stash entries&lt;/span&gt;
git stash show stash@&lt;span class="o"&gt;{&lt;/span&gt;N&lt;span class="o"&gt;}&lt;/span&gt;               &lt;span class="c"&gt;# Summary of a stash entry&lt;/span&gt;
git stash show &lt;span class="nt"&gt;-p&lt;/span&gt; stash@&lt;span class="o"&gt;{&lt;/span&gt;N&lt;span class="o"&gt;}&lt;/span&gt;            &lt;span class="c"&gt;# Full diff of a stash entry&lt;/span&gt;

&lt;span class="c"&gt;# --- RESTORING ---&lt;/span&gt;
git stash pop                          &lt;span class="c"&gt;# Apply latest stash, remove from stack&lt;/span&gt;
git stash apply stash@&lt;span class="o"&gt;{&lt;/span&gt;N&lt;span class="o"&gt;}&lt;/span&gt;              &lt;span class="c"&gt;# Apply a specific stash, keep in stack&lt;/span&gt;
git stash pop &lt;span class="nt"&gt;--index&lt;/span&gt;                  &lt;span class="c"&gt;# Restore staging area state too&lt;/span&gt;
git stash apply &lt;span class="nt"&gt;--index&lt;/span&gt; stash@&lt;span class="o"&gt;{&lt;/span&gt;N&lt;span class="o"&gt;}&lt;/span&gt;      &lt;span class="c"&gt;# Apply with index state preserved&lt;/span&gt;
git stash branch &amp;lt;branch&amp;gt; stash@&lt;span class="o"&gt;{&lt;/span&gt;N&lt;span class="o"&gt;}&lt;/span&gt;    &lt;span class="c"&gt;# Apply stash as a new branch&lt;/span&gt;

&lt;span class="c"&gt;# --- REMOVING ---&lt;/span&gt;
git stash drop stash@&lt;span class="o"&gt;{&lt;/span&gt;N&lt;span class="o"&gt;}&lt;/span&gt;               &lt;span class="c"&gt;# Delete a specific stash entry&lt;/span&gt;
git stash clear                        &lt;span class="c"&gt;# Delete ALL stash entries (irreversible!)&lt;/span&gt;

&lt;span class="c"&gt;# --- RECOVERY ---&lt;/span&gt;
git fsck &lt;span class="nt"&gt;--lost-found&lt;/span&gt;                  &lt;span class="c"&gt;# Find dangling objects (lost stashes)&lt;/span&gt;
git show &amp;lt;&lt;span class="nb"&gt;hash&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;                        &lt;span class="c"&gt;# Inspect a dangling commit&lt;/span&gt;
git stash apply &amp;lt;&lt;span class="nb"&gt;hash&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;                 &lt;span class="c"&gt;# Apply a recovered stash by hash&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Golden rules for using git stash safely:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Always label stashes with &lt;code&gt;-m "descriptive message"&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Prefer &lt;code&gt;git stash apply&lt;/code&gt; over &lt;code&gt;git stash pop&lt;/code&gt; when uncertain — it keeps the entry until you explicitly drop it.&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;git stash list&lt;/code&gt; regularly and clean up stale entries.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;-u&lt;/code&gt; if you have new untracked files you care about.&lt;/li&gt;
&lt;li&gt;For anything lasting more than a few hours, use a WIP commit on a branch instead.&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  9. Deep dive — understanding &lt;code&gt;--index&lt;/code&gt; and tracked vs. untracked files
&lt;/h2&gt;

&lt;p&gt;This section answers two of the most common points of confusion when using &lt;code&gt;git stash&lt;/code&gt; day-to-day.&lt;/p&gt;




&lt;h3&gt;
  
  
  9.1 The three zones of Git
&lt;/h3&gt;

&lt;p&gt;Before &lt;code&gt;--index&lt;/code&gt; makes sense, you need to clearly see the three zones Git works with:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Zone&lt;/th&gt;
&lt;th&gt;What it is&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Working tree&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Your actual files on disk — what you see in your editor&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Index (staging area)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A snapshot you've explicitly prepared with &lt;code&gt;git add&lt;/code&gt;, ready to become a commit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Repository (HEAD)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The last committed state&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;git add&lt;/code&gt; moves a file from the working tree into the index. &lt;code&gt;git commit&lt;/code&gt; moves everything in the index into the repository. &lt;code&gt;git stash&lt;/code&gt; saves both the working tree and the index — and puts HEAD back in your working tree.&lt;/p&gt;




&lt;h3&gt;
  
  
  9.2 What &lt;code&gt;--index&lt;/code&gt; actually does
&lt;/h3&gt;

&lt;p&gt;When you run &lt;code&gt;git stash&lt;/code&gt;, Git secretly saves &lt;strong&gt;two separate snapshots&lt;/strong&gt; internally:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One snapshot of your &lt;strong&gt;working tree&lt;/strong&gt; (all modified files)&lt;/li&gt;
&lt;li&gt;One snapshot of your &lt;strong&gt;index&lt;/strong&gt; (which files were staged)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But when you run &lt;code&gt;git stash pop&lt;/code&gt; to restore, by default Git only replays the working tree snapshot. It throws away the index snapshot entirely — so every file comes back as "modified but unstaged", regardless of what was staged before.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git stash pop --index&lt;/code&gt; tells Git: "restore both snapshots — put the staged files back into the staging area, leave the rest as just modified."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Without &lt;code&gt;--index&lt;/code&gt;:&lt;/strong&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;# Before stash:   index.py → unstaged,  index2.py → staged&lt;/span&gt;
git stash
git stash pop
&lt;span class="c"&gt;# After pop:      index.py → unstaged,  index2.py → ALSO unstaged (staged status lost!)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;With &lt;code&gt;--index&lt;/code&gt;:&lt;/strong&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;# Before stash:   index.py → unstaged,  index2.py → staged&lt;/span&gt;
git stash
git stash pop &lt;span class="nt"&gt;--index&lt;/span&gt;
&lt;span class="c"&gt;# After pop:      index.py → unstaged,  index2.py → staged (perfectly restored)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Rule of thumb:&lt;/strong&gt; If you ran &lt;code&gt;git add&lt;/code&gt; on anything before stashing, always pop with &lt;code&gt;--index&lt;/code&gt;. If nothing was staged, it makes no difference.&lt;/p&gt;




&lt;h3&gt;
  
  
  9.3 Tracked vs. untracked files — why &lt;code&gt;index.py&lt;/code&gt; might not get stashed
&lt;/h3&gt;

&lt;p&gt;This is the other major surprise. By default, &lt;code&gt;git stash&lt;/code&gt; only saves files that Git is already &lt;strong&gt;tracking&lt;/strong&gt; — meaning files that have appeared in at least one previous commit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scenario A — &lt;code&gt;index.py&lt;/code&gt; is a previously committed file (tracked):&lt;/strong&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;# index.py has been committed before — Git knows about it&lt;/span&gt;
&lt;span class="c"&gt;# index2.py is staged&lt;/span&gt;

git stash
&lt;span class="c"&gt;# Result: BOTH files are stashed. index.py is included&lt;/span&gt;
&lt;span class="c"&gt;#         because Git tracks it, even though it wasn't staged.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Scenario B — &lt;code&gt;index.py&lt;/code&gt; is a brand new file, never committed (untracked):&lt;/strong&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;# index.py was just created — never committed, never git add-ed&lt;/span&gt;
&lt;span class="c"&gt;# index2.py is staged&lt;/span&gt;

git stash
&lt;span class="c"&gt;# Result: only index2.py is stashed.&lt;/span&gt;
&lt;span class="c"&gt;#         index.py is completely ignored — it stays sitting in&lt;/span&gt;
&lt;span class="c"&gt;#         your folder but is NOT saved in the stash at all.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is exactly why you might see &lt;code&gt;index.py&lt;/code&gt; still in your folder after a stash — Git didn't touch it because it doesn't know it exists yet.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fix — use &lt;code&gt;-u&lt;/code&gt; to include untracked files:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git stash push &lt;span class="nt"&gt;-u&lt;/span&gt;
&lt;span class="c"&gt;# Now both index.py (untracked) and index2.py (staged) are stashed&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Flag&lt;/th&gt;
&lt;th&gt;What gets stashed&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;git stash&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Tracked modified files only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;git stash push -u&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Tracked files + new untracked files&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;git stash push -a&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Everything including files in &lt;code&gt;.gitignore&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h3&gt;
  
  
  9.4 The perfect round trip for your scenario
&lt;/h3&gt;

&lt;p&gt;Putting it all together — if you have &lt;code&gt;index.py&lt;/code&gt; (untracked/unstaged) and &lt;code&gt;index2.py&lt;/code&gt; (staged):&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;# Step 1 — stash everything including the untracked file&lt;/span&gt;
git stash push &lt;span class="nt"&gt;-u&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"WIP: both files"&lt;/span&gt;

&lt;span class="c"&gt;# Step 2 — go do your other work ...&lt;/span&gt;

&lt;span class="c"&gt;# Step 3 — restore exactly as you left it&lt;/span&gt;
git stash pop &lt;span class="nt"&gt;--index&lt;/span&gt;

&lt;span class="c"&gt;# Result:&lt;/span&gt;
&lt;span class="c"&gt;#   index.py  → back as unstaged (or untracked, depending on scenario)&lt;/span&gt;
&lt;span class="c"&gt;#   index2.py → back as staged, ready to commit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The two flags &lt;code&gt;-u&lt;/code&gt; (on push) and &lt;code&gt;--index&lt;/code&gt; (on pop) are a matched pair. Use them together whenever your stash contains a mix of tracked, untracked, staged, and unstaged files.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>git</category>
      <category>github</category>
      <category>gitbasics</category>
    </item>
  </channel>
</rss>
