在git documentation of the blame
command它说(强调我的):
C [< num>]
除了-M之外,检测从同一提交中修改的其他文件移动或复制的行。当您重新组织程序并跨文件移动代码时,这非常有用。 当此选项被给出两次时,该命令还会在创建文件的提交中查找其他文件的副本。当此选项被给出三次时,该命令还会查找其他文件中的副本。承诺。 [...]
首先,提交中创建文件"的其他文件是什么?意思? 它是否查找在添加文件的同一提交中修改的文件?或者它是否查找仅添加文件的提交树中存在的所有文件?
我尝试了一个示例,其中我在同一个提交中创建了一个非空文件(名为source
)和一个空文件(名称dest
)。在以下提交中,我做了一些无关紧要的事情。在第三次和最后一次提交中,我将几行从source
复制到dest
。结果如下所示(内容相当大,试着不要混淆git' s算法,我为此道歉):
$ 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
,这是一个使用与{{{1}相同的提交中的那些行创建的文件1}}。但是,dest
给出了预期的输出。
我做错了吗?
谢谢。
编辑:
我相信
[...]当给出此选项两次时,该命令还会在创建文件的提交中查找其他文件的副本。 [...]
表示git blame -C -C -C dest
将在实际创建文件的提交中查找发生仅的行副本(来自其他文件),而不是从其他文件中查找行副本(创建文件的提交中存在的文件)。这种误解与我的第一个问题有关。
答案 0 :(得分:0)
似乎是git
的一个假设,即您无法从不存在的内容中复制。如果您是在上一次提交中首先创建源文件,那么-C -C
应该可以工作。如果您还在当前提交中对其进行了修改,则只有-C
也将起作用。
如果git
不能以这种方式工作,那么他们将不得不考虑提交中更改的应用顺序,这可能会使代码变得更加冗长(在您的示例中:文件是从行复制到的行,由于它们都是在同一提交中创建的,git怎么会知道呢?
要根据自己的实验结果回答您的第一个问题:
两次给出此选项时,命令还会查找 从创建文件的提交中的其他文件复制
表示在创建文件的提交之前 树中存在的所有文件。
-C -C -C
会检查所有提交,因此也会检查创建文件的提交。