首页 > 解决方案 > 如何找到跨文件重命名和重新排序添加特定 Gradle 构建依赖项的 Git 提交?

问题描述

我正在使用Spring Boot和 Java实现一个多项目Gradle项目,并使用Git进行版本控制。其中一个子项目依赖于特定的库(我们称之为),在该特定子项目的文件中声明。这个库是不久前添加的,我想找到添加它的提交,以便我可以了解添加它的原因以及是否仍然需要它。我的代码中没有库的导入,但是由于 Spring Boot 的自动配置部分基于类路径上的库,因此在我的代码中没有直接使用不足以确定是否使用或如何使用该库.com.example:mylibbuild.gradle

为了给这种情况增加一个皱纹,自项目启动以来发生了各种项目重组:子项目已多次重命名,移至子项目等。构建文件本身也进行了重组和重新排序。此外,Gradle 文件已从Groovy ( build.gradle) 切换到Kotlin ( build.gradle.kts),然后又切换回来。

构建.gradle

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

构建.gradle.kts

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

我知道一些手动方法可以追溯并找到更改。例如,我可以使用git blame并重新完成对线路的更改,在重命名和重组发生时手动切换文件。但是当发生大量更改时,这些方法可能会有点耗时且乏味。

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

标签: gitgit-bisect

解决方案


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指定develop为“新”提交,并将git bisect old abc123“abc123”指定为“旧”提交。(请注意,标准术语是坏/好,不是新/旧,但由于这更多的是变化而不是破损,我选择使用替代术语“旧”和“新”而不是标准术语。 )

然后,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.gradleand 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结束 bisect 会话并更改回我们开始 bisect 会话之前所在的分支。


推荐阅读