【问题标题】:Git - Find which apps in repo have changedGit - 查找 repo 中哪些应用程序已更改
【发布时间】:2019-07-12 11:32:19
【问题描述】:
我有一个非常大的存储库,其中包含许多应用程序/服务。例如,有用 C# 编写的 Windows 服务、JS/HTML Web 客户端、节点应用程序和其他应用程序。
当我标记一个新版本时,我想以编程方式找到哪些需要部署,基于与前一个标记的差异。
对于某些应用程序,它就像检查存储库子文件夹中的更改一样简单。例如,Web 客户端都在src/clients/web 中。但是 C# 服务使用一些共享的 C# 库,这些库不在这些服务的文件夹中。这些依赖关系会随着时间而改变,所以我只能真正依赖csproj 文件中的引用。
这个问题有一般(或部分)解决方案吗?
【问题讨论】:
-
您可以大胆地为此编写脚本。使用“git diff --name-only ”,您将获得在标签之间更改的所有文件的列表。从那里开始,您可以运行列表中的任何正则表达式来找出适合每个项目重新部署标准的内容。
标签:
git
deployment
continuous-integration
continuous-deployment
【解决方案1】:
该问题的更通用解决方案是使用:
这样,当您将新标签放入父存储库时,您可以:
- 首先执行
git submodule update -remote 以确保您拥有所有子模块的最后一个(主)
- 重新编译/测试以确保这是您要标记的正确状态
- 使用前一个标签执行
git diff 以立即查看哪个子存储库已更改。
【解决方案2】:
有一个蛮力解决方案,就是构建两次,寻找改变的文件时间戳:
git checkout <old tag>
msbuild ...
record_all_final_outputs_timestamps > old_timestamps.txt
git checkout <new tag>
msbuild ...
record_all_final_outputs_timestamps > new_timestamps.txt
diff old_timestamps.txt new_timestamps.txt
差异将显示在增量构建后实际更改的所有库。 C# 的构建速度相对较快,这可能使这种方法可以接受。
【解决方案3】:
只要所有可能表明需要重新部署的文件都被 git 跟踪,这实际上很容易。正如 Yazeed Sabri 在 cmets 中已经提到的,您可以通过执行以下命令获取修改、添加或删除文件的完整列表:
git diff --name-only <oldtag> <newtag>
添加-z 以使用NUL 字节而不是默认换行符分隔文件名;这也可以防止 git 在路径名中引用任何“不寻常”的字符。
您可以通过提供一个或多个路径来进一步细化文件列表:
git diff --name-only <oldtag> <newtag> -- <path_1> <path_2> <path_n>
这只会返回您提供的<path>s 之一以下的文件。请注意,命令行上的<path>s 是相对于当前工作目录的,但是git diff 输出的路径是相对于git 存储库的根目录。
如果您只对某事发生了变化感兴趣,而不是究竟是什么,您可以将git diff 设为静音并像这样使用其退出状态(shell):
if ! git diff --quiet "$oldtag" "$newtag" -- src/app_1 app_1.csproj
then
redeploy app_1
fi
注意这里的!; git diff --quiet 如果在给定标签之间提供的路径没有改变,则以 0 退出(= 在 shell 逻辑中成功),但我们希望在它们发生改变时重新部署。 (此行为与标准 Linux diff 命令一致。)
【解决方案4】:
我会使用@VonC 建议的布局,但是对于您拥有的 repo,核心命令就是您想要的,git diff-tree 不会自动为您递归,因此它只会列出哪些顶级条目已更改:
git diff-tree @ @~
如果您不需要检查哪些条目是目录,则可能使用--name-only。要在您还拥有要忽略的顶级文件的仓库中执行上述操作,
git diff-tree @ @~ | awk '$1":"$2 ~ /:04/'