2017-04-15 112 views
1

我偶然发现了一个奇怪的现象,据我可以告诉可以可靠地使用这个剧本我写转载:国家和去除

#!/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结束,另一个开始。我把它放在引擎收录,所以我们可以参考行号更容易: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如图同时添加和无缘无故删除:这是完全一样的在回购,索引和工作树中。 git add .魔法清理git status

这是预期的行为?如果是这样:为什么?为什么不只显示一个干净的git status而不需要git add .必须先执行?

+0

您是否可以缩短命令以仅显示相关的输出,即文件既存在又被删除的部分?另外,你介意写一切都明确(没有反引号)吗? – AnoE

+0

@AnoE最好有完整的命令来重现问题。它帮助我非常了解发生了什么。 – Schwern

+0

@AnoE大部分的输出都显示了这一点。 backtick命令找出提交ID。这些在脚本的每次执行上都不同,因为这些执行发生在不同的时间,并且具有其中不同人的姓名和电子邮件地址(取决于运行的计算机的git配置)。如果我把我的提交散列在那里,它不会在你的计算机上工作。 –

回答

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 committhis将承诺,尽管它从工作副本中丢失。 git commit将暂存区中的内容变为提交。

大多数时候你不需要担心暂存区域,但当你不得不将复杂的改变分解为多个提交时,它很容易变得10非常方便。像git add -p这样的命令成为创建更小,更集中的提交的非常强大的工具。


什么你正在运行到的是“工作副本”和“临时区域”(也称为“指数”或“缓存”)之间的差异。工作副本是磁盘上的实际文件,如folder/b

暂存区域是下一个提交构建的地方。你可以把它想象成一个临时目录。 git add将工作副本中的文件复制到临时区域。 git commit将在暂存区域中进行任何操作并将其转换为下一个提交。

这就是为什么您可以对同一文件进行“暂存”和“非暂存”更改的原因。这意味着临时区域中的版本与磁盘上的版本不同,该版本与以前提交(HEAD)中的版本不同。

+0

这不是发生了什么事。执行第14行后(请参阅行号编号的pastebin链接),分段区域是干净的。显示该现象的'git status'发生在第25行第14行之后的'git add'之前的第23行。 –

+0

啊,第16行自动将结帐引起的变化添加到登台区域,右? –

+0

@ UTF-8是的,第一个'git checkout'相当于从旧提交重新创建b,然后将其添加到暂存区域。 'rm *'正在删除工作副本*中的所有文件*,但是暂存区中的b被单独保留。第二个'git checkout'将a和c带回,但不是b。部分困惑可能是因为有几种不同形式的'git checkout'。你正在使用'git checkout [-p | --patch] [] [ - ] ...'这个形式与其他人非常不同。 – Schwern