【问题标题】:Git run shell command for each commitGit 为每个提交运行 shell 命令
【发布时间】:2015-01-15 00:21:18
【问题描述】:

我想浏览一系列提交并在每个提交上执行一个 shell 命令。如果命令失败,我希望步行停止,否则继续前进。我看过filter-branch,但我不想重新编写提交,只需检查它们即可。 for-each-ref 似乎不允许您指定要操作的范围。

我的具体问题是我创建了一堆提交,我想确保每个提交都是可构建的。我想做类似的事情:

git foreach origin/master..master 'git submodule update && make clean && make'

我当然可以编写一个 shell 脚本来执行此操作,但这似乎是 git 可能有一个不错的方法。

【问题讨论】:

  • 你考虑过使用 Python 吗?也许 GitPython 可能是一个解决方案。查看此帖子:stackoverflow.com/questions/1456269/…
  • 您是否知道 origin/master 是好的而 master 是坏的(或相反),或者您只是想测试它们之间的所有内容而不知道在任何特定位置存在故障?
  • @CharlesDuffy,后者。我从一个工作点开始,做了很多有效的改变。然后我从一堆未提交的工作更改中进行了几次细粒度的提交,并希望确保所有中间提交都是可构建的。

标签: git shell


【解决方案1】:

您可以使用带有 exec 选项的交互式 rebase。

git rebase -i --exec <build command> <first sha you want to test>~

--exec 在最终历史记录中创建提交的每一行之后附加“exec”。将被解释为一个或多个 shell 命令。

重新排序和编辑提交通常会创建未经测试的中间 脚步。您可能想检查您的历史编辑没有中断 通过运行测试或至少在中间重新编译任何东西 使用“exec”命令(快捷键“x”)记录历史记录。

当命令失败时交互式变基将停止(即退出 非 0 状态)为您提供解决问题的机会。

【讨论】:

  • 我坚持使用 1.7.10 的 git 版本没有 --exec 命令行选项,所以我在每个选择命令之后手动插入了“x make”,它很有效。谢谢。
  • 如果 rebase 的范围包括合并,您可能还需要选项 -p&--preserve-merges
  • 它就像 HEAD~1,它表示要再往前返回,这样您就可以实际选择要测试的 SHA。标准 git 修订规范
  • 因为它正在做 rebase SHA 会改变,所以很好的是分配一个 temp 分支来保留旧的提交。在它的基础上进行rebase,我们可以在旧的基础上添加。
【解决方案2】:

你可能想要rev-list

#!/usr/bin/env bash
# test_commits.sh

while read -r rev; do
    git checkout "$rev"
    if ! git submodule update && make clean && make; then
        >&2 echo "Commit $rev failed"
        exit 1
    fi
done < <(git rev-list "$1")

然后你就可以用它了

./test_commits.sh origin/master..master

【讨论】:

  • 需要更多引号以避免字符串拆分和全局扩展。 "$1""$rev" 等。在字符串拆分和迭代之前收集来自 git rev-list 的所有输出也意味着比 while read -r rev; do ...; done &lt; &lt;(git rev-list "$1") 更多的前期延迟,后者在读取内容时流入内容而不是收集整个流并预先解析它。 (由于明显的原因,这种方法对于非常大的修订列表也更节省内存)。
  • (也就是说,虽然 shell 最佳实践还有改进的余地,但这绝对是这里最好的答案,并且有我的 +1)。
  • @CharlesDuffy - 我从来不知道在阅读列表内容时会以这种方式流式传输 - 谢谢!
【解决方案3】:

这是一个使用xargs 的很酷的单行代码。

git rev-list @{upstream}..HEAD | xargs -n1 -I{} sh -c 'git checkout {} && git submodule update && make clean && make'

您可能还想将 --reverse 选项传递给 rev-list,以便最后一次结帐是 HEAD。

【讨论】:

  • 根据您想要返回多远,如果您不想有一个废弃的 reflog,最好在此之前备份 .git/logs/HEAD
猜你喜欢
  • 2021-08-06
  • 2020-05-16
  • 1970-01-01
  • 2011-05-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-04
相关资源
最近更新 更多