Git:git如何记住每个分支的索引?

时间:2012-08-23 08:46:06

标签: git git-index

例如,我在repo中创建文件a(假设我在主分支上), 然后我git add agit commit。 之后我git branch copygit checkout copy。 最后,我在word目录中创建文件b,然后git add b

当我结帐回主分支时,Git似乎很聪明,git ls-files,文件b未列出。

所以我很困惑,因为我们在回购中只有一个index文件,git如何同时为分支维护不同的临时区域?

编辑:

如何解释分阶段但未提交的文件,仍然会记住每个分支?

2 个答案:

答案 0 :(得分:4)

我没有详细介绍实现,但是当您切换分支时,会手动更新索引文件以反映新HEAD的内容。

例如,我必须在这里分支master(有一个文件)和test(有两个文件)。

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

分支切换发生时,它改变了索引。

此外,如果您“手动”切换分支,git不会更新索引并感到困惑。从上面继续。

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
#

换句话说,索引有一个丢失的文件,它存在于当前存储库中,因此它“暂存为删除”。

对于分段后切换分支,索引是一个不变的单独区域。

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%        

答案 1 :(得分:2)

为了理解这一点,你需要深入了解git内部。

Git将各种信息存储为对象。主要有三种对象。

  • <强>团块

    在git中存储acctural文件内容。

  • <强>树

    存储树结构的信息,可能包含对其他blob对象和树对象的引用。

  • <强>提交

    存储有关提交的信息,包含对树对象的引用和其他信息,例如作者,提交者,提交消息等。

索引文件是一个树对象,它提供有关当前工作树的信息。

每个对象都由其内容的唯一sha1哈希标识。在.git/refs.git/packed_refs下,git保存分支与它指向的提交对象的sha1哈希之间的关系。

每次签出新分支时,git只根据与该分支的提交相关联的树对象提取文件,并生成新的索引文件。

Git Internals可以提供帮助。