【问题标题】:Example to understand git blame -M / -C理解 git blame -M / -C 的例子
【发布时间】:2015-03-26 17:30:38
【问题描述】:

我正在努力了解 git blame -Mgit blame -C 的工作原理。

我创建了两个文件:

文件A:

A
B
C

文件B:

D
E
F

并将它们添加(并提交)到我的存储库(哈希1234)。然后我把FileB的内容复制到FileA,这样就变成了这样:

文件A:

A
B
C
D
E
F

并提交更改(哈希4567)。

然后我跑了git blame -C FileA

我期望的输出:

1234 A
1234 B
1234 C
1234 D
1234 E
1234 F

却得到了:

1234 A
1234 B
1234 C
4567 D
4567 E
4567 F

当我将块 D E F 移动到 FileA 并执行 git blame -M FileA 时也是如此。

是我误解了-C-M 的用途,还是在构建测试文件时遗漏了什么?

更新 1:-C-M 的值设置为 3 都没有帮助,处理更大的文本也没有帮助(尝试了 3 段 lorem ipsum)

【问题讨论】:

    标签: git blame


    【解决方案1】:

    来自git help blame

       -C|<num>|
           In addition to -M, detect lines moved or copied from other files that were modified in the same commit. This is
           useful when you reorganize your program and move code around across files. When this option is given twice, the
           command additionally looks for copies from other files in the commit that creates the file. When this option is given
           three times, the command additionally looks for copies from other files in any commit.
    
           <num> is optional but it is the lower bound on the number of alphanumeric characters that git must detect as
           moving/copying between files for it to associate those lines with the parent commit. **And the default value is 40**. If
           there are more than one -C options given, the <num> argument of the last -C will take effect.
    

    注意默认值是40?您的示例仅显示 6 个(或可能 9 个)字符的变化,远低于 40 个的阈值...

    我怀疑您的测试输入不足以让算法检测到文本移动...

    编辑:那里还有关于“在同一提交中修改的其他文件”的内容。所以这里有一个例子:

    $ git init /tmp/foo
    Initialized empty Git repository in /tmp/foo/.git/
    $ cd /tmp/foo
    $ cp /etc/motd file1
    $ cp /etc/magic file2
    $ cp /etc/os-release file3
    $ git add file1 file2 file3
    $ git commit -m baseline
    [master (root-commit) 36a1d7] baseline
     3 files changed, 19 insertions(+)
     create mode 100644 file1
     create mode 100644 file2
     create mode 100644 file3
    $ head -5 file2 >> file1
    $ head -5 file3 >> file1
    $ sed -i 1,5d file3
    $ git add file1 file3
    $ git commit -m second
    [master b7a683] second
     2 files changed, 8 insertions(+), 5 deletions(-)
    $ git log --pretty=oneline
     b7a683 (HEAD, master) second
     36a1d7 baseline
    $ git blame file1
     ^36a1d7 (Joe User 2015-03-26 17:19:10 -0500  1) 
     ^36a1d7 (Joe User 2015-03-26 17:19:10 -0500  2) The programs included with the Debian GNU/Linux system are free software;
     ^36a1d7 (Joe User 2015-03-26 17:19:10 -0500  3) the exact distribution terms for each program are described in the
     ^36a1d7 (Joe User 2015-03-26 17:19:10 -0500  4) individual files in /usr/share/doc/*/copyright.
     ^36a1d7 (Joe User 2015-03-26 17:19:10 -0500  5) 
     ^36a1d7 (Joe User 2015-03-26 17:19:10 -0500  6) Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
     ^36a1d7 (Joe User 2015-03-26 17:19:10 -0500  7) permitted by applicable law.
     b7a6839 (Joe User 2015-03-26 17:21:41 -0500  8) # Magic local data for file(1) command.
     b7a6839 (Joe User 2015-03-26 17:21:41 -0500  9) # Insert here your local magic data. Format is described in magic(5).
     b7a6839 (Joe User 2015-03-26 17:21:41 -0500 10) 
     b7a6839 (Joe User 2015-03-26 17:21:41 -0500 11) PRETTY_NAME="Debian GNU/Linux 7 (wheezy)"
     b7a6839 (Joe User 2015-03-26 17:21:41 -0500 12) NAME="Debian GNU/Linux"
     b7a6839 (Joe User 2015-03-26 17:21:41 -0500 13) VERSION_ID="7"
     b7a6839 (Joe User 2015-03-26 17:21:41 -0500 14) VERSION="7 (wheezy)"
     b7a6839 (Joe User 2015-03-26 17:21:41 -0500 15) ID=debian
    $ git blame -C file1
     ^36a1d7 file1 (Joe User 2015-03-26 17:19:10 -0500  1) 
     ^36a1d7 file1 (Joe User 2015-03-26 17:19:10 -0500  2) The programs included with the Debian GNU/Linux system are free software;
     ^36a1d7 file1 (Joe User 2015-03-26 17:19:10 -0500  3) the exact distribution terms for each program are described in the
     ^36a1d7 file1 (Joe User 2015-03-26 17:19:10 -0500  4) individual files in /usr/share/doc/*/copyright.
     ^36a1d7 file1 (Joe User 2015-03-26 17:19:10 -0500  5) 
     ^36a1d7 file1 (Joe User 2015-03-26 17:19:10 -0500  6) Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
     ^36a1d7 file1 (Joe User 2015-03-26 17:19:10 -0500  7) permitted by applicable law.
     b7a6839 file1 (Joe User 2015-03-26 17:21:41 -0500  8) # Magic local data for file(1) command.
     b7a6839 file1 (Joe User 2015-03-26 17:21:41 -0500  9) # Insert here your local magic data. Format is described in magic(5).
     b7a6839 file1 (Joe User 2015-03-26 17:21:41 -0500 10) 
     ^36a1d7 file3 (Joe User 2015-03-26 17:19:10 -0500 11) PRETTY_NAME="Debian GNU/Linux 7 (wheezy)"
     ^36a1d7 file3 (Joe User 2015-03-26 17:19:10 -0500 12) NAME="Debian GNU/Linux"
     ^36a1d7 file3 (Joe User 2015-03-26 17:19:10 -0500 13) VERSION_ID="7"
     ^36a1d7 file3 (Joe User 2015-03-26 17:19:10 -0500 14) VERSION="7 (wheezy)"
     ^36a1d7 file3 (Joe User 2015-03-26 17:19:10 -0500 15) ID=debian
    

    请注意,没有-Cgit blame 只是将新行归因于第二次提交。但是有了它,它会将最后 5 行归因于第一次提交的 file3,因为 1) 那是它们的来源,2) 段足够大,以及 3) file3 在第二次提交中也被修改了。无法识别来自file2 的行,因为虽然段足够大,但file2 在第二次提交中没有被修改。

    另外,请注意-M(检测文件内的内容移动)和-C(检测不同文件之间的移动/复制)之间的区别。

    【讨论】:

    • 我也读过,但我对“字符”一词感到困惑,因为我认为它会逐行跟踪块。尝试使用更大的文本也不起作用(生成 3 段 lorem ipsum 文本并将一个块从一个文件复制到另一个文件)无论我选择的 的值是什么
    • 好的。我可以为 git blame -C 重建您的示例。但是你我无法重建检测到的文件之间的移动
    • 文档还说:When this option is given three times, the command additionally looks for copies from other files in any commit.。如果我做对了,git blame -CCC 应该检测到不一定包含在同一个提交中的文件的副本,对吗?也不适合我
    猜你喜欢
    • 2019-12-20
    • 2017-05-10
    • 2012-05-21
    • 2018-08-30
    • 2022-01-22
    • 2016-07-18
    • 2016-04-19
    • 2021-10-27
    • 1970-01-01
    相关资源
    最近更新 更多