我的repo中有几个文件,我用git mv
重命名了它们。在做git status
时,我看到了正确的:
On branch lnxkrnl-chg123-just-to-annoy-linus
Your branch is up-to-date with 'origin/lnxkrnl-chg123-just-to-annoy-linus
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
renamed: file1.service -> RobinHood.service
renamed: file1.sh -> RobinHood.sh
然后我按照预期编辑这些文件:
On branch lnxkrnl-chg123-just-to-annoy-linus
Your branch is up-to-date with 'origin/lnxkrnl-chg123-just-to-annoy-linus'.
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
renamed: file1.service -> RobinHood.service
renamed: file1.sh -> RobinHood.sh
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: RobinHood.service
modified: RobinHood.sh
现在,当我实际添加这些新文件用于登台时,其中一个似乎是智能处理而另一个则没有。我会告诉读者他们如何定义&#34;智能&#34;,足以说他们看起来被区别对待,尽管他们都对他们执行了相同的操作:
On branch lnxkrnl-chg123-just-to-annoy-linus
Your branch is up-to-date with 'origin/lnxkrnl-chg123-just-to-annoy-linus'.
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
renamed: file1.service -> RobinHood.service
new file: RobinHood.sh
deleted: file1.sh
服务文件的提交更改似乎是一个简单的重命名,虽然我确实改变了文件内容(虽然只是一个小的方式,只是在几行上改变了一些文本)。
shell脚本的提交更改(已编辑得更多,添加了许多新行)是删除/新操作。
为什么git
在这里有所区别?我认为显示类似的内容会更有意义:
renamed & edited: file1.service -> RobinHood.service
renamed & edited: file1.sh -> RobinHood.sh
但是,即使没有这种详细程度,我也希望git
以相同的方式处理相同的操作。
我在Ubuntu 16.04下使用的git版本是2.7.4。
答案 0 :(得分:3)
Git实际上知道文件已重命名。无论您如何暂存和提交重命名,即是否使用git mv
,都是如此。 Git所做的事情 - 对于提交的git diff
/ git show
,以及您尚未提交的git status
事件都是如此 - guess 。< / p>
当你只做 的事情是重命名一些文件或文件时,Git可以做出非常准确的猜测。也就是说,它每次都会正确。 1 那是因为它猜测的方式环顾四周:“嗯,我有文件A
,{ {1}}和B
之前。我现在有C
,A
和B
。我想知道......我知道{{1}我们现在看看D
中的内容。哦,嘿,看,C
现在的内容正是D
之前的内容!我打赌用户重命名为D
到C
!“
但是,如果您开始更改内容,则会变得更难。在您的情况下,Git发现C
和D
都已消失。同时,它看到这些文件file1.service
和file1.sh
是新的。因此,它将所有已经消失的文件中的 used 与所有新添加的文件中的内容进行比较。它们都不再与完全匹配。但其中一些看起来很可疑相似。
因此,Git为每个文件对计算“相似性索引”。碰巧的是,旧的(现在已经消失的)RobinHood.service
与旧RobinHood.sh
“非常相似”(至少50%)。所以它选择那对称为重命名。
与此同时,RobinHood.service
和file1.service
现在是 dis - 相似(低于相同的50%相似度要求),Git决定这些是完全不同的文件。您必须刚删除第一个,然后从头开始创建第二个。
1 好吧,每次几乎。特别是,如果您有两个相同的文件file1.sh
和RobinHood.sh
,并将它们重命名为C3
和PO
,Git可能会认为您将R2
重命名为{ {1}}和D2
到C3
,或者可能认为您已将R2
重命名为PO
而D2
重命名为PO
。但是,如果R2
和C3
是绝对的,100%,逐位相同,为什么哪个旧的哪个成为新的呢?
D2
实际上运行两个 C3
s 这在PO
输出中有点复杂,因为git status
实际上在内部运行了两个 git diff
命令,一个用来比较git status
提交到索引,以及将索引与工作树进行比较的索引。在您git status
之前,git diff --name-status --find-renames
提交版本与索引版本完全匹配。索引版本具有不同的名称,因此Git将这些视为重命名。然后,索引版本具有与工作树版本相同的名称,因此Git假定它们是相同的文件(不需要重命名检测)。只有当您通过HEAD
将工作树版本重新复制到索引版本时,才会将这两个阶段“比较HEAD与索引,然后将索引与工作树进行比较”分崩离析。
出于同样的原因,如果您git add
自行重命名,然后HEAD
修改,您将稍后通过逐步执行每个提交 - 能够恢复,以编程方式,重命名的事实。如果您git add
重命名和更改,Git以后不会恢复重命名(因为它现在没有恢复)。