7

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

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

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

编辑:

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

4

2 回答 2

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%        
于 2012-08-23T08:54:40.763 回答
2

为了理解这一点,您需要更深入地研究 git 内部结构。

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

  • 斑点

    在 git 中存储准确的文件内容。

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

  • 犯罪

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

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

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

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

Git Internals可以提供帮助。

于 2012-08-23T09:03:33.637 回答