问题
I can not find a good visualization of the git stash
operation. So I created my own based on some rare comments on the internet.
This this visualization correct?
Edit note: I need to change the color of stash@{0}
because it's no branch.
Where are stashes stored in my .git
directory? I think it's a reference and stored in refs
, right?
Legend:
- C1, C2 - commits
- Idx - Index
- WD - working directory
- dashed line and dashed borders => free for garbage collection
Reworked Image
回答1:
The "before git stash
" and "after git stash
" graphs are essentially correct (there are two new commits, not on any branch, pointed-to by refs/stash
aka stash@{0}
). What's missing from this diagram is that the index and work-tree themselves are reset, in the same way git reset --hard
does it—in fact, using git reset --hard
—after git stash
.
The "after git stash branch
" graph is [edit to match new diagram]
much harder to draw, though: git stash branch
uses the idx
and wd
commits to restore the state of the index and work-tree, and then drops them entirely from refs/stash
. Those two commits now have no name at all and are therefore eligible for garbage collection (git gc
may now remove them as soon as they expire, in terms of "prune time", based on gc.pruneExpire
in your configuration). The new branch name test
points to the parent commit to which idx
and WD
pointed, back when idx
and WD
were still guaranteed to exist.
Making a new commit immediately at this point (git stash branch <name> && git commit
) will make a new commit from the restored index, as in the updated drawing.
Where are stashes stored in my .git directory?
The commits themselves are commits, and hence are stored like any other commit, in .git/objects/
(as loose or packed objects).
I think it's a reference and stored in refs, right?
Yes, refs/stash
is a reference. The git stash
code uses (or abuses?) the reflog entries for refs/stash
to manage the "stash stack", so both the hash ID in refs/stash
itself, and all those in any refs/stash
reflog entries, matter: they keep the WD
commit alive, by pointing directly to it, and hence also keep the idx
commit (the ^2
or second parent of WD
) alive (since it is reachable through the WD
commit).
来源:https://stackoverflow.com/questions/46575029/is-this-a-valid-visualization-of-the-git-stash-operation