git status / git diff -C不检测索引中的文件副本

时间:2014-11-29 03:01:48

标签: git

git status [1]的文档意味着它应该能够检测重命名和副本(具有C状态)或者无论git diff -C应该做什么,但都不能似乎工作:

mkdir test
cd test/
git init
echo 'Hello World!' > hello.txt
echo 'Goodbye World!' > goodbye.txt
git add -A
git commit -m "Initial commit"

cp hello.txt copied.txt
mv goodbye.txt moved.txt
git add -A

$ git status --short
A  copied.txt  <------------ NO COPY DETECTED
R  goodbye.txt -> moved.txt

$ git diff -M -C --summary --cached
 create mode 100644 copied.txt  <------------ NO COPY DETECTED
 rename goodbye.txt => moved.txt (100%)

$ git commit -m Test
$ git diff -M -C --summary HEAD~
  create mode 100644 copied.txt  <------------ NO COPY DETECTED
  rename goodbye.txt => moved.txt (100%)

与话题相关的问题:在将更改添加到索引之前,是否可以让git statusgit diff检测副本并在workdir中重命名?

[1] http://git-scm.com/docs/git-status

3 个答案:

答案 0 :(得分:4)

由于SO上的任何人显然都不知道关于git status的主要问题的答案,我最后也在官方Git邮件列表上提出了问题[1]:

关于git status未检测到文件副本(文档实际上是错误的,它根本不会检测副本):

  

git-status自2005年中期以来一直使用重命名。提及副本的文档很晚才添加,   以及短版和瓷版。该代码处理diff引擎抛出的任何内容。我不认为当时有人认为你实际上不能激发寻找副本的状态。

关于git diff -C未检测到文件副本(您还需要传递--find-copies-harder):

  

默认情况下,-C仅在同一次提交中修改源文件时才查找副本。由于您没有在将其复制到copied.txt的同一提交中修改hello.txt,因此不会考虑它。

     

如果你传递-C -C(两次),或者使用--find-copies-harder,Git会考虑存储库中的所有文件。请注意,这可能会更慢,这就是它不是默认值的原因。

[1] http://marc.info/?l=git&m=141730775928542&w=2

答案 1 :(得分:1)

  

是否可以在将更改添加到索引之前让git status或git diff检测副本并在workdir中重命名?

不,如&#34; Git changing repo directory and files directory&#34;中所述 Git将检测完整(已提交)树上的重命名,而不是添加到索引的部分。

提交后,差异应检测移动/重命名:

git diff -M -C --summary @~

(用@表示HEAD)


关于副本,考虑到在该提交中修改的文件没有被修改,您必须使用&#34; --find-copies-harder&#34;选项:

C:\Users\vonc\prog\git\test\mv\test>git diff -M -C --summary --cached
 create mode 100644 copied.txt
 rename goodbye.txt => moved.txt (100%)

VS

C:\Users\vonc\prog\git\test\mv\test>git diff -M -C --find-copies-harder --summary --cached
 copy hello.txt => copied.txt (100%)
 rename goodbye.txt => moved.txt (100%)

那是:

--find-copies-harder
  

出于性能原因,默认情况下, -C选项仅在副本的原始文件在同一变更集中修改时才会找到副本。
  此标志使命令检查未修改的文件作为副本源的候选者   对于大型项目来说,这是一项非常昂贵的操作,因此请谨慎使用   提供多个-C选项具有相同的效果。


请注意,使用Git 2.17(2018年第二季度),git status输出现在更精确。

commit e4e5da2Stefan Beller (stefanbeller)(2018年2月15日) (由Junio C Hamano -- gitster --合并于commit 7676b86,2018年2月28日)

  

可以输出&#39; A&#39;来自&#39; git status --porcelain&#39;   使用&#39; --intend-to-add&#39;添加文件标志。
  通过在文档表中添加模式来明确这一点。

答案 2 :(得分:0)

这是不正确的。我误解了这个问题。

简单的答案是在

之后
cp hello.txt copied.txt
mv goodbye.txt moved.txt
git add -A

$ git status --short
A  copied.txt  <------------ NO COPY DETECTED
R  goodbye.txt -> moved.txt

Git尚未了解copied.txt的内容。请注意,git status会将其列为untracked