【问题标题】:Git blame -C -C does not seem to workGit 责备 -C -C 似乎不起作用
【发布时间】:2018-10-26 22:47:54
【问题描述】:

在git documentation of the blame command 中它说(强调我的):

C[]

除了 -M 之外,检测从在同一提交中修改的其他文件移动或复制的行。当您重新组织程序并跨文件移动代码时,这很有用。 当这个选项被给出两次时,该命令另外在创建文件的提交中查找来自其他文件的副本。 当这个选项被给出三次时,该命令另外在任何一个中查找来自其他文件的副本。犯罪。 [...]

首先,“创建文件的提交中的其他文件”是什么意思? 它是否查找在添加文件的同一提交中修改的文件?还是它会查找仅存在于添加文件的提交树中的所有文件?

我尝试了一个示例,在该示例中,我在同一个提交中创建了一个非空文件(名为 source)和一个空文件(名称 dest)。在接下来的提交中,我做了一些不相关的事情。在第三次也是最后一次提交中,我将几行从source 复制到dest。结果如下图(内容比较大,尽量不要混淆git的算法,对此我深表歉意):

$ git init
$ cat source
--incremental         Show blame entries as we find them, incrementally
-b                    Show blank SHA-1 for boundary commits (Default: off)
--root                Do not treat root commits as boundaries (Default: off)
--show-stats          Show work cost statistics
--score-debug         Show output score for blame entries
-f, --show-name       Show original filename (Default: auto)
-n, --show-number     Show original linenumber (Default: off)
-p, --porcelain       Show in a format designed for machine consumption
--line-porcelain      Show porcelain format with per-line commit information
-c                    Use the same output mode as git-annotate (Default: off)
-t                    Show raw timestamp (Default: off)
-l                    Show long commit SHA1 (Default: off)
-s                    Suppress author name and timestamp (Default: off)
-e, --show-email      Show author email instead of name (Default: off)
-w                    Ignore whitespace differences
--minimal             Spend extra cycles to find better match
-S <file>             Use revisions from <file> instead of calling git-rev-list
--contents <file>     Use <file>'s contents as the final image
-C[<score>]           Find line copies within and across files
-M[<score>]           Find line movements within and across files
-L <n,m>              Process only line range n,m, counting from 1
--abbrev[=<n>]        use <n> digits to display SHA-1s

$ cat dest
first initial line in dest
second initial line in dest

$ git add source dest
$ git commit -m "Add source and dest files"
$ touch new-file
$ git add new-file
$ git commit -m "Add irrelevant file"
$ (copy some lines from source to dest)
$ cat dest
first initial line in dest
--show-stats          Show work cost statistics
--score-debug         Show output score for blame entries
-f, --show-name       Show original filename (Default: auto)
-n, --show-number     Show original linenumber (Default: off)
-p, --porcelain       Show in a format designed for machine consumption
--line-porcelain      Show porcelain format with per-line commit information
-c                    Use the same output mode as git-annotate (Default: off)
-t                    Show raw timestamp (Default: off)
-l                    Show long commit SHA1 (Default: off)
-s                    Suppress author name and timestamp (Default: off)
-e, --show-email      Show author email instead of name (Default: off)
-w                    Ignore whitespace differences
--minimal             Spend extra cycles to find better match
-S <file>             Use revisions from <file> instead of calling git-rev-list
--contents <file>     Use <file>'s contents as the final image
second initial line in dest

$ git add dest
$ git commit -m "Copy lines from source to dest"
$ git log --pretty=oneline
6b0f18daaf83ec83d3f53b4a43f4188de3ce87e6 copy lines from source to dest
f1d66ad3dacb8e589747ed02b42d9135081b3704 Add irrelevant file
2b8275dc73ffd88d7adb6f90a2050ef14088019a Add source and dest files

$ git blame dest
^2b8275d -  1) first initial line in dest
6b0f18da -  2)     --show-stats          Show work cost statistics
6b0f18da -  3)     --score-debug         Show output score for blame entries
6b0f18da -  4)     -f, --show-name       Show original filename (Default: auto)
6b0f18da -  5)     -n, --show-number     Show original linenumber (Default: off)
6b0f18da -  6)     -p, --porcelain       Show in a format designed for machine consumption
6b0f18da -  7)     --line-porcelain      Show porcelain format with per-line commit information
6b0f18da -  8)     -c                    Use the same output mode as git-annotate (Default: off)
6b0f18da -  9)     -t                    Show raw timestamp (Default: off)
6b0f18da - 10)     -l                    Show long commit SHA1 (Default: off)
6b0f18da - 11)     -s                    Suppress author name and timestamp (Default: off)
6b0f18da - 12)     -e, --show-email      Show author email instead of name (Default: off)
6b0f18da - 13)     -w                    Ignore whitespace differences
6b0f18da - 14)     --minimal             Spend extra cycles to find better match
6b0f18da - 15)     -S <file>             Use revisions from <file> instead of calling git-rev-list
6b0f18da - 16)     --contents <file>     Use <file>'s contents as the final image
^2b8275d - 17) second initial line in dest
$ git blame -C dest
^2b8275d -  1) first initial line in dest
6b0f18da -  2)     --show-stats          Show work cost statistics
6b0f18da -  3)     --score-debug         Show output score for blame entries
6b0f18da -  4)     -f, --show-name       Show original filename (Default: auto)
6b0f18da -  5)     -n, --show-number     Show original linenumber (Default: off)
6b0f18da -  6)     -p, --porcelain       Show in a format designed for machine consumption
6b0f18da -  7)     --line-porcelain      Show porcelain format with per-line commit information
6b0f18da -  8)     -c                    Use the same output mode as git-annotate (Default: off)
6b0f18da -  9)     -t                    Show raw timestamp (Default: off)
6b0f18da - 10)     -l                    Show long commit SHA1 (Default: off)
6b0f18da - 11)     -s                    Suppress author name and timestamp (Default: off)
6b0f18da - 12)     -e, --show-email      Show author email instead of name (Default: off)
6b0f18da - 13)     -w                    Ignore whitespace differences
6b0f18da - 14)     --minimal             Spend extra cycles to find better match
6b0f18da - 15)     -S <file>             Use revisions from <file> instead of calling git-rev-list
6b0f18da - 16)     --contents <file>     Use <file>'s contents as the final image
^2b8275d - 17) second initial line in dest
$ git blame -C -C dest
^2b8275d -  1) first initial line in dest
6b0f18da -  2)     --show-stats          Show work cost statistics
6b0f18da -  3)     --score-debug         Show output score for blame entries
6b0f18da -  4)     -f, --show-name       Show original filename (Default: auto)
6b0f18da -  5)     -n, --show-number     Show original linenumber (Default: off)
6b0f18da -  6)     -p, --porcelain       Show in a format designed for machine consumption
6b0f18da -  7)     --line-porcelain      Show porcelain format with per-line commit information
6b0f18da -  8)     -c                    Use the same output mode as git-annotate (Default: off)
6b0f18da -  9)     -t                    Show raw timestamp (Default: off)
6b0f18da - 10)     -l                    Show long commit SHA1 (Default: off)
6b0f18da - 11)     -s                    Suppress author name and timestamp (Default: off)
6b0f18da - 12)     -e, --show-email      Show author email instead of name (Default: off)
6b0f18da - 13)     -w                    Ignore whitespace differences
6b0f18da - 14)     --minimal             Spend extra cycles to find better match
6b0f18da - 15)     -S <file>             Use revisions from <file> instead of calling git-rev-list
6b0f18da - 16)     --contents <file>     Use <file>'s contents as the final image
^2b8275d - 17) second initial line in dest
$ git blame -C -C -C dest
^2b8275d dest   -  1) first initial line in dest
^2b8275d source -  2)     --show-stats          Show work cost statistics
^2b8275d source -  3)     --score-debug         Show output score for blame entries
^2b8275d source -  4)     -f, --show-name       Show original filename (Default: auto)
^2b8275d source -  5)     -n, --show-number     Show original linenumber (Default: off)
^2b8275d source -  6)     -p, --porcelain       Show in a format designed for machine consumption
^2b8275d source -  7)     --line-porcelain      Show porcelain format with per-line commit information
^2b8275d source -  8)     -c                    Use the same output mode as git-annotate (Default: off)
^2b8275d source -  9)     -t                    Show raw timestamp (Default: off)
^2b8275d source - 10)     -l                    Show long commit SHA1 (Default: off)
^2b8275d source - 11)     -s                    Suppress author name and timestamp (Default: off)
^2b8275d source - 12)     -e, --show-email      Show author email instead of name (Default: off)
^2b8275d source - 13)     -w                    Ignore whitespace differences
^2b8275d source - 14)     --minimal             Spend extra cycles to find better match
^2b8275d source - 15)     -S <file>             Use revisions from <file> instead of calling git-rev-list
^2b8275d source - 16)     --contents <file>     Use <file>'s contents as the final image
^2b8275d dest   - 17) second initial line in dest

可以看出,git blame -C -C dest 没有意识到dest 中的新行源自source,这是在与dest 相同的提交中使用这些行创建的文件。但是,git blame -C -C -C dest 给出了预期的输出。

我是不是做错了什么?

谢谢。

编辑:

我相信

[...] 当这个选项被给出两次时,该命令另外在创建文件的提交中查找来自其他文件的副本。 [...]

意味着git 将查找在实际创建文件的提交中仅发生的行副本(来自其他文件),而不是它会从其他文件(文件存在于创建文件的提交中)。这个误会和我的第一个问题有关。

【问题讨论】:

  • 重新编辑:是的,这就是-C 的意思:检查提交中创建新文件的其他文件,以查看是否从现有文件中复制了新文件的某些部分.

标签: git git-blame


【解决方案1】:

似乎是git 的一个假设,即您无法从不存在的东西中复制。如果您首先在之前的提交中创建源文件,那么 -C -C 应该可以工作。如果你在当前提交中也修改了它,那么只有-C 也会起作用。

如果git 没有以这种方式工作,他们将不得不关注在提交中应用更改的顺序,这可能会使代码更加复杂(在您的示例中:哪个文件是从和复制到的行?git怎么知道,因为它们都是在同一个提交中创建的?)。

根据您自己的实验结果回答您的第一个问题:

当这个选项被给出两次时,命令会额外寻找 从创建文件的提交中的其他文件复制

表示在创建文件的提交之前存在于树中的任何文件。

而-C -C -C 检查所有提交,因此也检查创建文件的提交。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-03-03
    • 2010-12-08
    • 2014-05-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多