Skip to content
academia.sh

Lesson 14 / 15

Stash

Temporarily setting aside unfinished work; the stash stack, inspecting its content, including untracked files, and what the stash corresponds to in the object model.

Contents

The tools covered so far were about completed changes: a change is either committed or undone. There is a third situation — the change is unfinished, and it becomes necessary to switch to other work. Committing is premature, because there is no working whole yet; undoing is a loss.

The stash is a holding area defined for exactly this situation: the working directory and the staging area are cleaned, their content is set aside, and it is brought back later.

Unfinished Work

An option that lists all the terms is being added to the search script. The usage line has been updated, the implementation has not been written yet; an untracked file has also been created as a to-do list:

git status --short
 M ara.sh
?? TODO.md

Meanwhile a gap in the documentation is reported, and it needs to be fixed first. The unfinished work cannot be committed.

Putting Work in the Stash

git stash push -m "listeleme seçeneği, yarım"
Saved working directory and index state On main: listeleme seçeneği, yarım
git status --short
?? TODO.md

The change in the tracked file disappeared; the working directory returned to its state at the last commit. The untracked TODO.md stayed in place: by default, the stash takes only tracked files.

The -m option attaches a description to the entry. If no description is given, the last commit’s subject line is put in its place; once multiple entries pile up, these descriptions stop being distinctive.

The Stash Is a Stack

git stash list
stash@{0}: On main: listeleme seçeneği, yarım

Entries behave like a stack: the most recently added one becomes stash@{0}, earlier entries shift back by one position. The last-in-first-out order defined in the Data Structures course is applied here directly. Access is not limited to the stack, though: any entry can be named by its index number and taken or deleted on its own.

Inspecting the Content

git stash show
 ara.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
git stash show -p
diff --git a/ara.sh b/ara.sh
index 582ddde..726faa9 100755
--- a/ara.sh
+++ b/ara.sh
@@ -2,7 +2,7 @@
 # terimler.txt içinde arama yapar.
 
 if [ $# -ne 1 ]; then
-    echo "kullanım: ara.sh ARANAN" >&2
+    echo "kullanım: ara.sh [-l] ARANAN" >&2
     exit 1
 fi
 

The second command gives the full diff. If no entry is specified, stash@{0} is assumed; for another entry, its name is written.

Interrupting Work

Because the working directory is clean, the urgent fix is made comfortably and committed:

git commit -m "Aramanın harf duyarsızlığını README'de belirt"
[main 498105a] Aramanın harf duyarsızlığını README'de belirt
 1 file changed, 2 insertions(+)

Bringing It Back

git stash pop
On branch main
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
	modified:   ara.sh

Untracked files:
  (use "git add <file>..." to include in what will be committed)
	TODO.md

no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (de2b7f622af30b8141497a63c589cc0ff5b48666)

The unfinished work came back, and the stash entry was deleted. The last line reports the deleted entry’s object ID; if this ID is saved, the entry can be brought back even if it is deleted by mistake.

The distinction between the two commands matters:

Command Effect
git stash apply Applies the content, leaves the entry in the list
git stash pop Applies the content and drops the entry from the list
git stash drop Deletes the entry without applying it
git stash clear Deletes every entry

Because a conflict can arise while applying, apply is preferred in cases where the outcome is uncertain: if the application fails, the entry is still in the list.

Including Untracked Files

git stash push -u -m "listeleme seçeneği, yarım"
Saved working directory and index state On main: listeleme seçeneği, yarım
git status --short

The output is empty; TODO.md has been stashed too. The -u option covers untracked files as well. Ignored files need a separate option; the default behavior leaves them in place.

What the Stash Is in the Object Model

The stash is not a separate data structure. It is a ref named refs/stash, and what it points to is a commit:

git rev-parse stash@{0}
8ac8f2017d7f01e1fb748baa81fa9cc387ed6acf
git cat-file -p stash@{0}
tree 67b9d0564a53a73b74f42170488295f1d2f53fb1
parent 498105a461806443b43bf3287f41a9fe045f7ef8
parent 529c6c8bd87596bd7c343b11f6374532386b1296
parent 0e958ff47522e4f1b686243da04d5acec59cd351
author Deniz Kaya <[email protected]> 1710226080 +0300
committer Deniz Kaya <[email protected]> 1710226080 +0300

On main: listeleme seçeneği, yarım

There are three parent lines. The first is the branch tip at the moment the stash was taken; the second is a commit storing the staging area’s state at that moment; the third, because -u was used, is a commit storing the untracked files. Without -u there would have been two parents.

This structure answers the lesson’s opening question at the level of the object model: the stash is not “a temporary area” — it is a small piece of history made of ordinary commits, just attached to no branch. Stash entries also stand in the object database, and once they become unreachable, they fall within the scope of garbage collection.

Limits

The stash is local and is not shared; entries in one copy of the repository do not show up in other copies. It carries no structure beyond descriptions: entries are neither sorted nor grouped. For this reason it is not suitable for long-term holding — which piece of work an accumulated entry belongs to becomes unclear before long.

If unfinished work needs to be held for days, the right tool is not the stash but commits written on a separate branch. Branches are the subject of the Branching and Collaboration course.

In the example repository, the entry is brought back:

git stash pop
On branch main
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
	modified:   ara.sh

Untracked files:
  (use "git add <file>..." to include in what will be committed)
	TODO.md

no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (8ac8f2017d7f01e1fb748baa81fa9cc387ed6acf)

The option is then completed, TODO.md is deleted, and the change is committed:

git commit -m "Tüm terimleri listeleyen -l seçeneğini ekle"
[main 701fa37] Tüm terimleri listeleyen -l seçeneğini ekle
 1 file changed, 6 insertions(+), 1 deletion(-)

Summary

  • The stash sets aside changes in tracked files and returns the working directory to its state at the last commit.
  • Entries are held in stack order; stash@{0} is the most recently added.
  • apply leaves the entry in the list, pop drops it, drop deletes it without applying it.
  • The -u option covers untracked files too.
  • A stash entry is a commit with two or three parents, attached to no branch.

Next Step

Specific points in history have not been given human-readable names; everything has been referred to by forty-character IDs or by relative notation. When a release is published, that point needs a permanent name. The course’s last lesson takes up tags, the fourth object type, and their relationship with semantic versioning.

To keep your progress and take notes, Log in

My notes

Log in to take notes.

Start typing to search.

↑↓ Esc navigate · open · close