Are these the same thing? If so, why are there so many terms?!
Also, I know there is t开发者_开发知识库his thing called git stash, which is a place where you can temporarily store changes to your working copy without committing them to the repo. I find this tool really useful, but again, the name is very similar to a bunch of other concepts in git -> this is very confusing!!
The index/stage/cache are the same thing - as for why so many terms, I think that index was the 'original' term, but people found it confusing, so the other terms were introduced. And I agree that it makes things a bit confusing sometimes at first.
The stash
facility of git is a way to store 'in-progress' work that you don't want to commit right now in a commit object that gets stored in a particular stash directory/database). The basic stash
command will store uncommitted changes made to the working directory (both cached/staged and uncached/unstaged changes) and will then revert the working directory to HEAD.
It's not really related to the index/stage/cache except that it'll store away uncommitted changes that are in the cache.
This lets you quickly save the state of a dirty working directory and index so you can perform different work in a clean environment. Later you can get back the information in the stash object and apply it to your working directory (even if the working directory itself is in a different state).
The official git stash
manpage has pretty good detail, while remaining understandable. It also has good examples of scenarios of how stash
might be used.
It's very confusing indeed. The 3 terms are used interchangeably. Here's my take on why it's called each of those things. The git index is:
- a binary file
.git/index
that is an index of all the tracked files - used as a staging area for commits
- contains cached SHA1 hashes for the files (speeds up performance)
An important note is that the index/cache/stage contains a list of ALL files under source control, even unchanged ones. Unfortunately, phrases like "add a file to the index" or "file is staged to the index" can misleadingly imply that the index only contains changed files.
Here's a demo that shows that the git index contains list of ALL files, not only the changed files:
# setup
git init
echo 'x' > committed.txt
git add committed.txt
git commit -m 'initial'
echo 'y' > staged.txt
git add staged.txt
echo 'z' > working.txt
# list HEAD
git ls-tree --name-only -r HEAD
# committed.txt
# list index
git ls-files
# committed.txt
# staged.txt
# raw content of .git/index
strings .git/index
# DIRC
# committed.txt
# staged.txt
# TREE
# list working dir
ls -1
# committed.txt
# staged.txt
# working.txt
Additional reading:
https://www.kernel.org/pub/software/scm/git/docs/technical/racy-git.txt
What does the git index contain EXACTLY?
The history
https://stackoverflow.com/a/6718135/14972148
confusion: --cache vs --index etc.
From my modified man gitcli
:
add/index/stage/cache
The index file:
- is an index of all tracked files
- used as a staging area for commits
- contains cached SHA1 hashes for the files (speeds up performance)
From man git
:
$GIT_INDEX_FILE
sets the index file.
If not specified,
$GIT_DIR/index
is used.
The index file is a binary file.
When opened by nvim, here is part of the screenshot:
When opened by nvim with a plugin named fugitive
:
The content is very similar to
the output of
git status
, instead of strings .git/index
related command
- git add ("a file is added/staged to the index")
- git restore --staged ( --staged | restore the index )
- git rm --cached (--cached | only remove files from the index )
stage vs track
- Untracked changes are not in Git.
- Unstaged changes are in Git, but not marked for commit.
- Staged changes are in Git and marked for commit.
git ls-files
1.
-c, --cached ( cache: obsolete for index)
Show cached files in the output
(default)
-s, --stage
Show staged (git add) files'
mode bits,
object name
stage number
-u, --unmerged
(forces --stage)
Show unmerged files in the output
-d, --deleted
-m, --modified
-k, --killed
Show files on the filesystem
that need to be removed due to
file/directory conflicts
for checkout-index to succeed.
2.
-o, --others
other (i.e. untracked) files
--directory
If a whole directory is classified as "other",
show just its name (with a trailing slash)
and not its whole contents.
--no-empty-directory
Do not list empty directories.
Has no effect without --directory.
Further Reading
https://github.blog/2021-11-10-make-your-monorepo-feel-small-with-gits-sparse-index/
精彩评论