我偶然发现了一个奇怪的现象,据我所知,我可以用这个脚本可靠地再现这个现象:
#!/bin/bash
rm -Rf repo
mkdir repo
cd repo
git init
mkdir folder
echo a > folder/a
echo b > folder/b
git add .
git commit -m "First commit."
rm folder/b
echo c > folder/c
git add .
git commit -m "Second commit."
cd folder
git checkout `git log --pretty=format:%H | tail -1` .
echo "###################################################################"
git status
echo "###################################################################"
rm *
git checkout `git log --pretty=format:%H | head -1` .
echo "###################################################################"
git status
echo "###################################################################"
git add .
echo "###################################################################"
git status
echo "###################################################################"
哈希只是为了让您更容易看到一个git status
结束而另一个开始的位置。我把它放在pastebin上,这样我们就可以更容易地参考行号:https://pastebin.com/z8GgDpfw
它的输出是:
$ ./script.sh Initialized empty Git repository in /[...]/repo/.git/
[master (root-commit) 165986a] First commit.
2 files changed, 2 insertions(+)
create mode 100644 folder/a
create mode 100644 folder/b
[master 241e479] Second commit.
2 files changed, 1 insertion(+), 1 deletion(-)
delete mode 100644 folder/b
create mode 100644 folder/c
###################################################################
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: b
###################################################################
###################################################################
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: b
Changes not staged for commit:
(use "git add/rm <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
deleted: b
###################################################################
###################################################################
On branch master
nothing to commit, working directory clean
###################################################################
b
显示为添加和删除都没有明显原因:它在repo,index和工作树中完全相同。 git add .
神奇地清除git status
。
这是预期的行为吗?如果是这样:为什么?为什么不首先显示干净的git status
而不必git add .
执行?{/ p>
答案 0 :(得分:2)
您所做的是将新文件添加到暂存区域,然后将其从工作副本中删除。这很容易复制。
$ git init repo
Initialized empty Git repository in /Users/schwern/tmp/repo/.git/
$ cd repo/
$ touch this
$ git add this
$ rm this
$ git status
On branch master
Initial commit
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: this
Changes not staged for commit:
(use "git add/rm <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
deleted: this
touch this
在工作副本中创建了一个文件。 git add this
将其复制到暂存区域。 rm this
已从工作副本中删除了该文件,但该文件仍在暂存区。
如果我git commit
现在,this
将被提交,尽管工作副本中缺少该git commit
。 git add -p
将暂存区域中的任何内容转换为提交。
大多数情况下,您不必担心暂存区域,但是当您必须将复杂的更改分成多个提交时,它变得非常非常方便。像folder/b
这样的命令成为创建更小,更集中的提交的非常强大的工具。
您遇到的是&#34;工作副本&#34;和#34;集结区&#34; (也称为&#34;索引&#34;或&#34;缓存&#34;)。工作副本是磁盘上的实际文件,如git add
。
暂存区域是构建下一个提交的位置。您可以将其视为临时目录。 git commit
将工作副本中的文件复制到暂存区域。 HEAD
占用暂存区域中的任何内容并将其转换为下一次提交。
这就是为什么你可以进行&#34;上演&#34;和&#34;未分期&#34;更改到同一文件。这意味着暂存区域中的版本与磁盘上的版本不同,后者与上一次提交中的版本(func reportCall(with UUID: UUID, updated update: CXCallUpdate)
)不同。