Git Stash, Tags & Advanced Tips
TL;DR — Quick Summary
git stashtemporarily shelves uncommitted work;git stash poprestores it.- Annotated tags (
git tag -a) mark releases permanently — they must be pushed separately withgit push origin --tags. git bisectdoes a binary search through history to find the commit that introduced a bug.git blameshows line-by-line authorship;git log -Sfinds when a string was added/removed.
Lesson Overview
🗃️ Git Stash — Shelve Work Temporarily
You're in the middle of coding a feature when your manager asks you to urgently fix a different bug. Your work isn't ready to commit, but you need a clean working directory. Git stash is the solution — it saves your uncommitted changes to a temporary stack and cleans your working directory.
🏷️ Git Tags — Marking Milestones
Tags are like branches that never move. They permanently mark specific commits — most commonly used for release versions. Unlike branches, tags don't advance when you commit. Once a tag points to a commit, it always will.
- Lightweight tags: Just a pointer to a commit.
git tag v1.0.0 - Annotated tags: A full Git object with message, author, and date.
git tag -a v1.0.0 -m "First stable release"
🔍 Git Bisect — Find the Commit That Broke Everything
You have a bug in production but don't know which of the 50 recent commits introduced it. git bisect uses binary search to find the culprit commit — checking the midpoint each time and narrowing down in O(log n) steps.
🔎 Searching Git History
Git's history is a powerful database of your entire project's evolution. You can search it in many ways:
- Search commit messages:
git log --grep="payment" - Search code changes:
git log -S "functionName"(pickaxe) - See who edited each line:
git blame filename
Conceptual Deep Dive
git stash), get your working directory clean, do your urgent task, commit it, and then paste your in-progress work back (git stash pop). You can even have multiple items on your stash stack.
Git tags are like sticky notes permanently glued to specific commits. v1.0.0, v2.3.1 — these tags will always point to exactly those commits, even years later. This is how you give users download links to specific releases.Implementation Lab
# You're mid-feature with unsaved work
git status
# modified: src/feature.js
# modified: src/styles.css
# Stash everything (staged + unstaged)
git stash
# Saved working directory and index state WIP on main: ...
# With a descriptive name (recommended for multiple stashes)
git stash push -m "WIP: adding notification system"
# Your working directory is clean — now fix the urgent bug
git checkout -b hotfix/login-crash
# ... fix, commit, merge ...
# Return to your feature and restore stashed changes
git checkout feature/notifications
git stash pop # apply the most recent stash AND remove it from stack
# Or apply without removing from stack (reusable):
git stash apply
# See all stashed work
git stash list
# stash@{0}: On feature/notifications: WIP: adding notification system
# stash@{1}: On main: WIP: started dashboard redesign
# Apply a specific stash
git stash pop stash@{1}
# Delete a stash without applying it
git stash drop stash@{0}
# Stash including untracked (new) files
git stash push -u -m "Include new files too"new files too"# Create a lightweight tag at current commit
git tag v1.0.0
# Create an annotated tag with a message (preferred for releases)
git tag -a v1.0.0 -m "First stable release — adds user auth and dashboard"
# Tag a specific past commit by hash
git tag -a v0.9.0 9f3a2c1 -m "Beta release"
# See all tags
git tag
# v0.9.0
# v1.0.0
# See details of an annotated tag
git show v1.0.0
# Push tags to GitHub (not pushed by default!)
git push origin v1.0.0 # push one tag
git push origin --tags # push ALL tags
# Delete a local tag
git tag -d v0.9.0
# Delete a remote tag
git push origin :refs/tags/v0.9.0# A bug exists in the current HEAD but worked at some point
# Use bisect to find the exact culprit commit
# Start bisect
git bisect start
# Mark the current commit as 'bad' (has the bug)
git bisect bad
# Mark a known good commit (e.g., last week's release tag)
git bisect good v1.2.0
# Git checks out a commit in the middle
# TEST the bug:
# - If bug exists: git bisect bad
# - If bug doesn't exist: git bisect good
git bisect bad
# Git checks out another midpoint...
git bisect good
# After ~6-7 steps Git reports:
# 'a1b2c3d is the first bad commit'
# commit a1b2c3d Author: Dev <dev@co.com>
# Date: Mon Jan 6 ...
# Refactor user session handling
# Now you know which commit caused the bug!
# End bisect session (returns to original HEAD)
git bisect reset# Search commit messages for a keyword
git log --grep="payment" --oneline
# Find which commits added or removed a specific string in code
git log -S "getUserById" --oneline
# This is the 'pickaxe' search — incredibly useful for tracking down when a function appeared
# See who last edited each line of a file (blame)
git blame src/auth.js
# Shows: hash | author | date | line content
# Blame a specific line range
git blame -L 20,40 src/auth.js
# Search all commits that changed a specific file
git log --follow --oneline src/auth.js
# Find deleted files
git log --all --full-history -- "**/deletedFile.js"Pro Tips — Senior Dev Insights
Automate bisect: git bisect run ./test.sh — Git runs your script on each commit and marks it good/bad based on exit code. Fully hands-free.
Use git log -S "functionName" -p to find exactly when a function was added and see the full diff of that change — fantastic for debugging.
Create a GitHub Release (on top of a tag) to attach binaries, changelogs, and release notes — much more professional than a raw tag.
git shortlog -sn gives a contributor leaderboard showing commit counts per author — fun for team retrospectives.
Common Developer Pitfalls
Accumulating many stashes without descriptive names and forgetting what each one contains.
Forgetting to push tags to remote — your team won't see them and GitHub won't show them in releases.
git stash apply instead of git stash pop — apply keeps the stash in the stack, causing duplicate stashes over time.git bisect reset after finding a bug — you'll be left in a detached HEAD state.Interview Mastery
git stash temporarily saves your uncommitted changes (both staged and unstaged) onto a stack and restores your working directory to a clean state. Use it when: (1) you need to urgently switch branches or contexts without committing half-done work, (2) you want to pull the latest changes but have local modifications that would conflict, (3) you want to test something on a clean state. git stash pop restores the most recent stash.
A lightweight tag (git tag v1.0) is just a pointer to a commit — like a branch that never moves. An annotated tag (git tag -a v1.0 -m "msg") is a full Git object stored in the database with its own SHA, including the tagger's name, email, date, and a message. Annotated tags are preferred for releases because they capture who tagged it and when.
git bisect performs a binary search through your commit history to find the specific commit that introduced a bug. You tell it a 'bad' commit (has the bug) and a 'good' commit (doesn't have it). Git checks out the midpoint commit between them and asks you to test. Based on your answer (good/bad), it halves the search space again. After O(log n) steps, it identifies the exact commit that introduced the regression.
Real-World Blueprint
git bisect start, mark HEAD as bad and the release from 2 weeks ago as good. After 7 rounds of testing, bisect pinpoints a commit from 5 days ago: 'Refactor data fetching — remove caching layer.' Mystery solved in 15 minutes instead of hours of manual code archaeology.Hands-on Lab Exercises
Modify 3 files without committing, stash them with a descriptive message, make an unrelated commit, then restore the stash.
Create 3 annotated tags on different commits and push them to GitHub. View them on the GitHub releases page.
git bisect to find it.git blame on a file in any public GitHub repo to find who last edited a specific function.Real-World Practice Scenarios
You have unfinished work on a feature branch and need to quickly review a colleague's PR (which requires checking out their branch). What do you do with your WIP?
You need to give a user a download link for version 1.4.2 of your software, which was released 3 months ago. How do tags help?
A bug was reported that worked 3 weeks ago. There are 80 commits since then. How would you use Git tooling to find the culprit commit efficiently?
A colleague says 'Who wrote this terrible code?' about a function. Show them the Git way to answer that question professionally.
Git Stash, Tags & Advanced Tips
TL;DR — Quick Summary
git stashtemporarily shelves uncommitted work;git stash poprestores it.- Annotated tags (
git tag -a) mark releases permanently — they must be pushed separately withgit push origin --tags. git bisectdoes a binary search through history to find the commit that introduced a bug.git blameshows line-by-line authorship;git log -Sfinds when a string was added/removed.
Overview
🗃️ Git Stash — Shelve Work Temporarily
You're in the middle of coding a feature when your manager asks you to urgently fix a different bug. Your work isn't ready to commit, but you need a clean working directory. Git stash is the solution — it saves your uncommitted changes to a temporary stack and cleans your working directory.
🏷️ Git Tags — Marking Milestones
Tags are like branches that never move. They permanently mark specific commits — most commonly used for release versions. Unlike branches, tags don't advance when you commit. Once a tag points to a commit, it always will.
- Lightweight tags: Just a pointer to a commit.
git tag v1.0.0 - Annotated tags: A full Git object with message, author, and date.
git tag -a v1.0.0 -m "First stable release"
🔍 Git Bisect — Find the Commit That Broke Everything
You have a bug in production but don't know which of the 50 recent commits introduced it. git bisect uses binary search to find the culprit commit — checking the midpoint each time and narrowing down in O(log n) steps.
🔎 Searching Git History
Git's history is a powerful database of your entire project's evolution. You can search it in many ways:
- Search commit messages:
git log --grep="payment" - Search code changes:
git log -S "functionName"(pickaxe) - See who edited each line:
git blame filename
Deep Dive Analysis
Think of stash as a clipboard for your code changes. You copy your messy in-progress work to the clipboard (<code>git stash</code>), get your working directory clean, do your urgent task, commit it, and then paste your in-progress work back (<code>git stash pop</code>). You can even have multiple items on your stash stack. Git tags are like sticky notes permanently glued to specific commits. <code>v1.0.0</code>, <code>v2.3.1</code> — these tags will always point to exactly those commits, even years later. This is how you give users download links to specific releases.
Implementation Reference
# You're mid-feature with unsaved work
git status
# modified: src/feature.js
# modified: src/styles.css
# Stash everything (staged + unstaged)
git stash
# Saved working directory and index state WIP on main: ...
# With a descriptive name (recommended for multiple stashes)
git stash push -m "WIP: adding notification system"
# Your working directory is clean — now fix the urgent bug
git checkout -b hotfix/login-crash
# ... fix, commit, merge ...
# Return to your feature and restore stashed changes
git checkout feature/notifications
git stash pop # apply the most recent stash AND remove it from stack
# Or apply without removing from stack (reusable):
git stash apply
# See all stashed work
git stash list
# stash@{0}: On feature/notifications: WIP: adding notification system
# stash@{1}: On main: WIP: started dashboard redesign
# Apply a specific stash
git stash pop stash@{1}
# Delete a stash without applying it
git stash drop stash@{0}
# Stash including untracked (new) files
git stash push -u -m "Include new files too"# Create a lightweight tag at current commit
git tag v1.0.0
# Create an annotated tag with a message (preferred for releases)
git tag -a v1.0.0 -m "First stable release — adds user auth and dashboard"
# Tag a specific past commit by hash
git tag -a v0.9.0 9f3a2c1 -m "Beta release"
# See all tags
git tag
# v0.9.0
# v1.0.0
# See details of an annotated tag
git show v1.0.0
# Push tags to GitHub (not pushed by default!)
git push origin v1.0.0 # push one tag
git push origin --tags # push ALL tags
# Delete a local tag
git tag -d v0.9.0
# Delete a remote tag
git push origin :refs/tags/v0.9.0# A bug exists in the current HEAD but worked at some point
# Use bisect to find the exact culprit commit
# Start bisect
git bisect start
# Mark the current commit as 'bad' (has the bug)
git bisect bad
# Mark a known good commit (e.g., last week's release tag)
git bisect good v1.2.0
# Git checks out a commit in the middle
# TEST the bug:
# - If bug exists: git bisect bad
# - If bug doesn't exist: git bisect good
git bisect bad
# Git checks out another midpoint...
git bisect good
# After ~6-7 steps Git reports:
# 'a1b2c3d is the first bad commit'
# commit a1b2c3d Author: Dev <dev@co.com>
# Date: Mon Jan 6 ...
# Refactor user session handling
# Now you know which commit caused the bug!
# End bisect session (returns to original HEAD)
git bisect reset# Search commit messages for a keyword
git log --grep="payment" --oneline
# Find which commits added or removed a specific string in code
git log -S "getUserById" --oneline
# This is the 'pickaxe' search — incredibly useful for tracking down when a function appeared
# See who last edited each line of a file (blame)
git blame src/auth.js
# Shows: hash | author | date | line content
# Blame a specific line range
git blame -L 20,40 src/auth.js
# Search all commits that changed a specific file
git log --follow --oneline src/auth.js
# Find deleted files
git log --all --full-history -- "**/deletedFile.js"Common Pitfalls
- •Accumulating many stashes without descriptive names and forgetting what each one contains.
- •Forgetting to push tags to remote — your team won't see them and GitHub won't show them in releases.
- •Using <code>git stash apply</code> instead of <code>git stash pop</code> — apply keeps the stash in the stack, causing duplicate stashes over time.
- •Not using <code>git bisect reset</code> after finding a bug — you'll be left in a detached HEAD state.
Key Takeaways
Hands-on Practice
- ✓Modify 3 files without committing, stash them with a descriptive message, make an unrelated commit, then restore the stash.
- ✓Create 3 annotated tags on different commits and push them to GitHub. View them on the GitHub releases page.
- ✓Set up a repo with 10 commits where one commit introduces a bug (a specific string in a file). Practice using <code>git bisect</code> to find it.
- ✓Use <code>git blame</code> on a file in any public GitHub repo to find who last edited a specific function.
Expert Pro Tips
Interview Preparation
Q: What is git stash and when would you use it?
Master Answer:
<code>git stash</code> temporarily saves your uncommitted changes (both staged and unstaged) onto a stack and restores your working directory to a clean state. Use it when: (1) you need to urgently switch branches or contexts without committing half-done work, (2) you want to pull the latest changes but have local modifications that would conflict, (3) you want to test something on a clean state. <code>git stash pop</code> restores the most recent stash.
Q: What is the difference between annotated and lightweight tags?
Master Answer:
A <strong>lightweight tag</strong> (<code>git tag v1.0</code>) is just a pointer to a commit — like a branch that never moves. An <strong>annotated tag</strong> (<code>git tag -a v1.0 -m "msg"</code>) is a full Git object stored in the database with its own SHA, including the tagger's name, email, date, and a message. Annotated tags are preferred for releases because they capture who tagged it and when.
Q: How does git bisect work?
Master Answer:
<code>git bisect</code> performs a binary search through your commit history to find the specific commit that introduced a bug. You tell it a 'bad' commit (has the bug) and a 'good' commit (doesn't have it). Git checks out the midpoint commit between them and asks you to test. Based on your answer (good/bad), it halves the search space again. After O(log n) steps, it identifies the exact commit that introduced the regression.
Industrial Blueprint
"A senior developer notices a performance regression in the dashboard — it was fast 2 weeks ago but now loads slowly. They run <code>git bisect start</code>, mark HEAD as bad and the release from 2 weeks ago as good. After 7 rounds of testing, bisect pinpoints a commit from 5 days ago: 'Refactor data fetching — remove caching layer.' Mystery solved in 15 minutes instead of hours of manual code archaeology."
Simulated Scenarios
© 2026 DevHub Engineering • All Proprietary Rights Reserved
Generated on March 7, 2026 • Ver: 4.0.2
Document Class: Master Education
Confidential Information • Licensed to User