For example, I create file a in the repo(suppose I'm on the master branch),
then I git add a
and git commit
.
After that I git branch copy
and git checkout copy
.
Finaly I create file b in the word directory then git add b
.
Git seems to be smart when I checkout back to the master branch, and git ls-files
, file b is not listed.
So I'm confused, since we only have one index
file in a repo, how can git maintain different staging area for branches at the same time?
EDIT:
How to explain the files which are staged but not commited, is still remembered per branch?
I've not dived into the implementation in detail but when you switch a branch, the index file is manually updated to reflect the content of the new HEAD
.
For example, I have to branches here master
(with one file) and test
(with two files).
noufal@sanitarium% git branch
master
* test
noufal@sanitarium% file .git/index
.git/index: Git index, version 2, 2 entries
noufal@sanitarium% git checkout master
Switched to branch 'master'
noufal@sanitarium% file .git/index
.git/index: Git index, version 2, 1 entries
It's changed the index when the branch switching happened.
Also, if you "manually" switching branches, git doesn't update the index and gets confused. Continuing from above.
noufal@sanitarium% more .git/HEAD
ref: refs/heads/master
noufal@sanitarium% echo "ref: refs/heads/test" > .git/HEAD
noufal@sanitarium% file .git/index
.git/index: Git index, version 2, 1 entries
noufal@sanitarium% git status
# On branch test
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# deleted: b
#
In other words, the index has a missing file which is there in the current repository so it's "staged for delete".
As for switching branches after staging, the index is a separate area which doesn't change.
noufal@sanitarium% git branch
* master
test
noufal@sanitarium% ls
x
noufal@sanitarium% git status
# On branch master
nothing to commit (working directory clean)
noufal@sanitarium% git checkout test
Switched to branch 'test'
noufal@sanitarium% ls
x
noufal@sanitarium% echo "Something" > b
noufal@sanitarium% git add b
noufal@sanitarium% git status
# On branch test
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# new file: b
#
noufal@sanitarium% git checkout master
A b
Switched to branch 'master'
noufal@sanitarium% git status # Also there in index on master branch.
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# new file: b
#
noufal@sanitarium% git commit -m "Added b in master"
[master 41d0c68] Added b in master
1 file changed, 1 insertion(+)
create mode 100644 b
noufal@sanitarium% git status
# On branch master
nothing to commit (working directory clean)
noufal@sanitarium% git checkout test
Switched to branch 'test'
noufal@sanitarium% ls # Missing in the test branch although it was `git add`ed here.
x
noufal@sanitarium%