代码之家  ›  专栏  ›  技术社区  ›  M. Justin Marwan Alsabbagh

我如何找到Git commit,它跨文件重命名和重新排序添加了特定的Gradle构建依赖项?

  •  0
  • M. Justin Marwan Alsabbagh  · 技术社区  · 4 年前

    我在一个多项目中工作 Gradle 使用 Spring Boot 和Java,并使用 Git .其中一个子项目依赖于特定的库(我们称之为 com.example:mylib ),在该特定子项目的 build.gradle 文件这个库是不久前添加的,我想找到添加它的提交,这样我就可以了解添加它的原因,以及是否仍然需要它。在我的库代码中没有导入,但是自从Spring Boot auto-configuration 部分基于类路径上的库,我的代码中缺少直接使用并不足以确定库是否被使用或如何使用。

    为了给这个场景增加一点难度,自项目开始以来,已经发生了各种各样的项目重组:子项目已被重命名、移动到子项目等多次。构建文件本身也进行了重组和重新排序。此外,Gradle文件已从 Groovy ( 建筑格拉德尔 )到 Kotlin ( build.gradle.kts )然后又回来了。

    建筑格拉德尔

    // ...
    dependencies {
        // ...
        compile 'com.example:mylib'
        // ...
    }
    // ...
    

    建筑格雷德尔。kts

    // ...
    dependencies {
        // ...
        implementation("com.example:mylib:1.0.5")
        // ...
    }
    // ...
    

    我知道一些手动方法,我可以追溯并找到变化。例如,我可以使用 git blame 然后,通过对行的更改,在重命名和重组过程中手动切换文件。但是,当有很多变化时,这些方法可能会有点耗时和乏味。

    如何快速轻松地找到添加库的提交?

    1 回复  |  直到 4 年前
        1
  •  1
  •   M. Justin Marwan Alsabbagh    4 年前

    git bisect 可用于以自动方式快速查找更改。

    鉴于此 develop 具有库依赖性,并且 abc123 是添加库依赖项之前的提交,以下内容将查找添加依赖项的提交:

    git bisect start
    git bisect new develop
    git bisect old abc123
    echo "! grep -rI --include \*.gradle\* mylib ." > /tmp/bisect.sh 
    chmod u+x /tmp/bisect.sh 
    git bisect run /tmp/bisect.sh
    git bisect reset
    

    git bisect start 开始新的对分会话。然后,我们需要确定至少一个旧的和一个新的提交,也就是说,一个在更改前提交(“旧”)和一个在更改后提交(“新”)。 git bisect new develop 指定 发展 作为“新”承诺,以及 git bisect old abc123 将“abc123”指定为“旧”提交。(请注意,标准术语是坏的/好的,不是新的/旧的,但由于这更像是一种变化而不是破损,我选择使用 alternate terms “旧的”&“新”而非标准条款。)

    Git随后将采用二进制搜索算法,在旧&的搜索过程中大约一半时间切换到提交;新的承诺。

    输出:

    Bisecting: 818 revisions left to test after this (roughly 10 steps)
    [1234567890abcdef1234567890abcdef12345678] Committed some stuff
    

    此时,您可以手动将此提交标识为旧的或新的( git bisect old / git bisect new ),通过Git二进制搜索到引入更改的提交。然而,我们可以通过让Git使用脚本通过使用 git bisect run <scriptname.sh> .如果脚本返回时退出代码为0,则将其标识为“旧”;如果它的代码介于1和127之间(125除外),则它是“新的”。

    对于这种情况,我们可以使用命令 grep -rI --include \*.gradle\* mylib . .这个用 grep 递归查找与模式匹配的任何非二进制文件 *.gradle* 包含术语“mylib”。这将匹配 build.gradle build.gradle.kts ,但跳过许多我们不关心的其他文件(从而加快了过程)。

    然而,grep命令返回我们想要的相反的退出代码。它在匹配时返回一个成功的(“旧”)响应,但我们希望它是一个失败的(“新”)响应。通过使用 ! 保留字: ! grep -rI --include \*.gradle\* mylib . .

    此命令存储到 /tmp/bisect.sh 脚本并使其可执行:

    echo "! grep -rI --include \*.gradle\* mylib ." > /tmp/bisect.sh 
    chmod u+x /tmp/bisect.sh 
    

    现在我们有了脚本,我们将其传递给 git bisect run 要获取添加依赖项的提交,请执行以下操作:

    git bisect run /tmp/bisect.sh
    

    输出:

    abcdefg1234567890abcdefg1234567890abcdef is the first new commit
    commit abcdefg1234567890abcdefg1234567890abcdef
    Author: John Doe <john.doe@example.com>
    Date:   Tue May 26 17:37:25 2020 -0400
    
        adding a new library for fun and profit
        
        1. add the library
        2. ???
        3. profit
    
     subproject1/build.gradle                           |   6 +-
     .../nested/subpackage/MyAwesomeClass.java          |  37 -------
     .../nested/subpackage/LessAwesomeClass.java        | 118 +++++++++++++++++++++
     .../nested/BoilerplateJunk.java                    |  32 ++++--
     subproject1/src/main/resources/application.yaml    |  12 +++
     .../another/subpackage/Whatever.java               |  28 +++++
     6 files changed, 189 insertions(+), 44 deletions(-)
    

    最后,我们打电话 git bisect reset 结束对分会话,并切换回开始对分会话之前的分支。

        2
  •  1
  •   M. Justin Marwan Alsabbagh    4 年前

    git log -S

    git log -S myLib
    

    -S<string>

    查找更改文件中指定字符串(即添加/删除)出现次数的差异。供编剧使用。

    当您正在寻找一个确切的代码块(如结构)并想知道该块自最初产生以来的历史时,它很有用:反复使用该功能将前图像中感兴趣的块反馈到 -S ,然后继续,直到你得到第一个版本的块。

    二进制文件也会被搜索。

    如果只想输出第一次添加依赖项的版本,可以通过一些命令管道来完成。一种方法是:

    git log -S mylib --pretty=format:"%H" | tail -1 | xargs git log -1 --stat
    

    输出:

    commit abcdefg1234567890abcdefg1234567890abcdef
    Author: John Doe <john.doe@example.com>
    Date:   Tue May 26 17:37:25 2020 -0400
    
        adding a new library for fun and profit
        
        1. add the library
        2. ???
        3. profit
    
     subproject1/build.gradle                           |   6 +-
     .../nested/subpackage/MyAwesomeClass.java          |  37 -------
     .../nested/subpackage/LessAwesomeClass.java        | 118 +++++++++++++++++++++
     .../nested/BoilerplateJunk.java                    |  32 ++++--
     subproject1/src/main/resources/application.yaml    |  12 +++
     .../another/subpackage/Whatever.java               |  28 +++++
     6 files changed, 189 insertions(+), 44 deletions(-)