简体   繁体   English

如何在变基期间为所有提交运行测试

[英]How to run tests for all commits during a rebase

I have a feature branch with plenty of commits.我有一个有大量提交的功能分支。

A---B---C     master
 \
  \-B'---C'---D'...---Z'  feature

I am working on feature but another developer has created commits B and C .我正在开发feature但另一位开发人员创建了提交BC Now I want to rebase feature on commit C , but I and/or automerge introduced errors during the rebase.现在我想在提交C上重新设置feature ,但是我和/或 automerge 在重新设置期间引入了错误。 My project has very good test coverage and I can run the tests from console using ant rebuild test , and now I want git to tell me which commit is the first commit that breaks my test so I can fix that commit.我的项目具有非常好的测试覆盖率,我可以使用ant rebuild test从控制台运行ant rebuild test ,现在我希望 git 告诉我哪个提交是第一个破坏我的测试的提交,以便我可以修复该提交。 How can I do that?我怎样才能做到这一点?

While you are on branch feature execute:当您在分支feature执行:

git rebase --interactive --exec "ant rebuild test" C

This will cause git to start again on commit C, replay your work on top and it will run your tests after each commit it applies during replay phase.这将导致 git 在提交 C 时再次启动,在顶部重放您的工作,并且它将在重放阶段应用的每次提交后运行您的测试。

Hopefully your ant task will have a non-zero exit code if your tests fail.如果您的测试失败,希望您的 ant 任务将有一个非零退出代码。 In this case git will stop as soon as the tests fail.在这种情况下,只要测试失败,git 就会停止。 You are immediately in the right position to amend you commit so that the tests will be happy again.您可以立即修改您的承诺,以便测试再次快乐。 After you have amended just execute git rebase --continue as usual and git will continue to check all you commits.在您修改之后,只需像往常一样执行git rebase --continue ,git 将继续检查您提交的所有内容。

To add to the OP yankee 's excellent answer , Git 2.5+ will provide a more robust git rebase --interactive --exec experience, especially in case of a failed exec.为了增加OP yankee 的出色答案,Git 2.5+ 将提供更强大的git rebase --interactive --exec体验,尤其是在 exec失败的情况下。
Actually, see the new --reschedule-failed-exec of Git 2.21 in the last part of this answer.实际上,请参阅本答案最后一部分中Git 2.21--reschedule-failed-exec

See commit b12d3e9 [22 May 2015], and commit 1d968ca [22 May 2015] by Matthieu Moy ( moy ) .请参阅提交 b12d3e9 [2015 年 5 月 22 日],以及由Matthieu Moy ( moy ) 提交的 1d968ca [2015 年 5 月 22 日]。
(Merged by Junio C Hamano -- gitster -- in commit a6be52e , 01 Jun 2015) (由Junio C gitster合并-- gitster -- in commit a6be52e ,2015 年 6 月 1 日)

The ' exec ' command is sending the current commit to stopped-sha , which is supposed to contain the original commit (before rebase). ' exec ' 命令正在将当前提交发送到stopped-sha ,它应该包含原始提交(在变基之前)。
As a result, if an ' exec ' command fails, the next ' git rebase --continue ' will send the current commit as to the post-rewrite hook.因此,如果 ' exec ' 命令失败,下一个 ' git rebase --continue ' 将发送关于 post-rewrite 钩子的当前提交。


The full documentation:完整的文档:

rebase -i : fix post-rewrite hook with failed exec command rebase -i :使用失败的exec命令修复post-rewrite钩子

Usually, when ' git rebase ' stops before completing the rebase, it is to give the user an opportunity to edit a commit (eg with the ' edit ' command).通常,当 ' git rebase ' 在完成 rebase 之前停止时,它是给用户一个机会来编辑提交(例如使用 ' edit ' 命令)。
In such cases, ' git rebase ' leaves the sha1 of the commit being rewritten in "$state_dir"/stopped-sha , and subsequent ' git rebase --continue ' will call the post-rewrite hook with this sha1 as <old-sha1> argument to the post-rewrite hook.在这种情况下,' git rebase ' 将在"$state_dir"/stopped-sha中重写的提交的 sha1 留下,随后的 ' git rebase --continue ' 将使用此 sha1 作为<old-sha1>调用post-rewrite钩子<old-sha1> post-rewrite钩子的参数。

The case of ' git rebase ' stopping because of a failed ' exec ' command is different: it gives the opportunity to the user to examine or fix the failure, but does not stop saying "here's a commit to edit, use --continue when you're done" . “的情况下git rebase ”,因为一个失败的“停止exec ”命令不同的是:它提供了机会,用户检查或修复失败,但并不能阻止说:“这里是一个致力于编辑,使用--continue时你完成了”
So, there's no reason to call the post-rewrite hook for 'exec' commands.因此,没有理由为“exec”命令调用post-rewrite挂钩。
If the user did rewrite the commit, it would be with ' git commit --amend ' which already called the post-rewrite hook.如果用户确实重写了提交,它将使用 ' git commit --amend ',它已经调用了post-rewrite钩子。

Fix the behavior to:将行为修正为:

  • leave no stopped-sha file in case of failed exec command ,exec命令失败的情况下不留下stopped-sha文件
  • and teach ' git rebase --continue ' to skip record_in_rewritten if no stopped-sha file is found.并教 ' git rebase --continue ' 跳过record_in_rewritten如果没有找到stopped-sha文件。

To facilitate managing failed exec directives associated to a rebase, Git 2.21 (Q1 2019) introduces --reschedule-failed-exec , with " git rebase -i ", which learned to re-execute a command given with ' exec ' to run after it failed the last time.为了便于管理与 rebase 关联的失败 exec 指令,Git 2.21(2019 年第一季度)引入了--reschedule-failed-exec和“ git rebase -i ”,它学会了重新执行用“ exec ”给出的命令以运行上次失败了。

See commit 81ef8ee , commit 969de3f , commit d421afa (10 Dec 2018) by Johannes Schindelin ( dscho ) .请参阅Johannes Schindelin ( dscho ) 的commit 81ef8eecommit 969de3fcommit d421afa (2018 年 12 月 10 日
(Merged by Junio C Hamano -- gitster -- in commit d9d9ab0 , 29 Jan 2019) (由Junio C gitster -- gitster --d9d9ab0 提交中合并,2019 年 1 月 29 日)

rebase : introduce --reschedule-failed-exec rebase :引入--reschedule-failed-exec

A common use case for the --exec option is to verify that each commit in a topic branch compiles cleanly, via git rebase -x make <base> . --exec选项的一个常见用例是通过git rebase -x make <base>验证主题分支中的每个提交是否编译干净。

However, when an exec in such a rebase fails, it is not re-scheduled, which in this instance is not particularly helpful.但是,当这种 rebase 中的exec失败时,它不会重新调度,这在这种情况下不是特别有用。

Let's offer a flag to reschedule failed exec commands.让我们提供一个标志来重新安排失败的exec命令。

Based on an idea by Paul Morelle .基于Paul Morelle 的一个想法。

The git rebase man page now includes: git rebase手册页现在包括:

 --reschedule-failed-exec::
--no-reschedule-failed-exec::

Automatically reschedule exec commands that failed.自动重新安排失败的exec命令。
This only makes sense in interactive mode (or when an --exec option was provided).这仅在交互模式下(或提供--exec选项时)才有意义。

And:和:

rebase : introduce a shortcut for --reschedule-failed-exec rebase : 为--reschedule-failed-exec引入快捷方式

It is a bit cumbersome to write out the --reschedule-failed-exec option before -x <cmd> all the time; --reschedule-failed-exec-x <cmd>之前写出--reschedule-failed-exec选项有点麻烦; let's introduce a convenient option to do both at the same time: -y <cmd> .让我们介绍一个方便的选项来同时进行: -y <cmd>

Note: the first committed in reverted in See commit e11ff89 (06 Feb 2019), and commit 81ef8ee (10 Dec 2018) by Johannes Schindelin ( dscho ) .注意:第一个提交的提交提交 e11ff89 (2019 年 2 月 6 日)和Johannes Schindelin ( dscho ) 提交的 81ef8ee (2018 年 12 月 10 日
(Merged by Junio C Hamano -- gitster -- in commit b966813 , 09 Feb 2019) (由Junio C gitster合并-- gitster -- in commit b966813 ,2019 年 2 月 9 日)

Revert "rebase: introduce a shortcut for --reschedule-failed-exec"恢复“rebase:为--reschedule-failed-exec引入快捷方式”

This patch was contributed only as a tentative "we could introduce a convenient short option if we do not want to change the default behavior in the long run" patch, opening the discussion whether other people agree with deprecating the current behavior in favor of the rescheduling behavior.这个补丁只是作为一个试探性的“如果我们不想改变长期的默认行为,我们可以引入一个方便的短选项”补丁,开始讨论其他人是否同意弃用当前行为以支持重新安排行为。

But the consensus on the Git mailing list was that it would make sense to show a warning in the near future, and flip the default rebase.rescheduleFailedExec to reschedule failed exec commands by default.但是 Git 邮件列表上的共识是,在不久的将来显示警告是有意义的,并且默认情况下翻转默认的rebase.rescheduleFailedExec以重新安排失败的exec命令。

So let's back out that patch that added the -y short option that we agreed was not necessary or desirable.因此,让我们退出那个添加了-y短选项的补丁,我们同意这不是必需的或不可取的。


Also in Git 2.21 (Feb. 2019): " git rebase -x $cmd " did not reject multi-line command, even though the command is incapable of handling such a command.同样在 Git 2.21(2019 年 2 月)中:“ git rebase -x $cmd ”没有拒绝多行命令,即使该命令无法处理这样的命令。
It now is rejected upfront.它现在被预先拒绝。

See commit c762aad (29 Jan 2019) by Phillip Wood ( phillipwood ) .请参阅Phillip Wood ( phillipwood ) 提交的 c762aad (2019 年 1 月 29 日)
(Merged by Junio C Hamano -- gitster -- in commit 96e6547 , 07 Feb 2019) (由Junio C gitster合并gitster 提交 96e6547,2019年 2 月 7 日)

rebase -x : sanity check command rebase -x : 健全性检查命令

If the user gives an empty argument to --exec then git creates a todo list that it cannot parse.如果用户给--exec一个空参数,那么 git 会创建一个它无法解析的待办事项列表。 The rebase starts to run before erroring out with:在出现错误之前,rebase 开始运行:

 error: missing arguments for exec
error: invalid line 2: exec
You can fix this with 'git rebase --edit-todo' and then run 'git rebase --continue'.
Or you can abort the rebase with 'git rebase --abort'.

Instead check for empty commands before starting the rebase.而是在开始变基之前检查空命令。

Also check that the command does not contain any newlines as the todo-list format is unable to cope with multiline commands.还要检查该命令是否不包含任何换行符,因为 todo-list 格式无法处理多行命令。
Note that this changes the behavior, before this change one could do:请注意,在此更改之前,这会更改行为:

 git rebase --exec='echo one
exec echo two'

and it would insert two exec lines in the todo list, now it will error out.它会在todo列表中插入两个 exec 行,现在它会出错。


With Git 2.23, the configuration variable rebase.rescheduleFailedExec should be effective only while running an interactive rebase and should not affect anything when running an non-interactive one, which was not the case.在 Git 2.23 中,配置变量rebase.rescheduleFailedExec仅在运行交互式变基时才有效,而在运行非交互式变基时不应影响任何事情,事实并非如此。
This has been corrected.这已得到纠正。

See commit 906b639 (01 Jul 2019) by Johannes Schindelin ( dscho ) .请参阅Johannes Schindelin ( dscho ) 的提交 906b639 (2019 年 7 月 1 日
(Merged by Junio C Hamano -- gitster -- in commit 64096fb , 11 Jul 2019) (由Junio C gitster合并gitster 提交 64096fb ,2019 年 7 月 11 日)

rebase --am : ignore rebase.rescheduleFailedExec rebase --am : 忽略rebase.rescheduleFailedExec

The exec command is specific to the interactive backend, therefore it does not make sense for non-interactive rebases to heed that config setting. exec命令特定于交互式后端,因此非交互式 rebase 关注该配置设置没有意义。

We still want to error out if a non-interactive rebase is started with --reschedule-failed-exec , of course.当然,如果非交互式 rebase 以--reschedule-failed-exec启动,我们仍然希望出错。

Reported by Vas Sudanagunta via commit 969de3f .Vas Sudanagunta通过提交 969de3f 报告


" git rebase --[no-]reschedule-failed-exec " ( man ) did not work well with its configuration variable, which has been corrected with Git 2.32 (Q2 2021). git rebase --[no-]reschedule-failed-exec( man )不能很好地与其配置变量配合使用,这已在 Git 2.32(2021 年第二季度)中得到纠正。

See commit e5b32bf , commit cd663df (09 Apr 2021) by Ævar Arnfjörð Bjarmason ( avar ) .请参阅Ævar Arnfjörð Bjarmason ( avar ) 提交的 e5b32bfcd663df (2021 年 4 月 9 日
(Merged by Junio C Hamano -- gitster -- in commit 0377ac9 , 07 May 2021) (由Junio C gitster合并-- gitster -- in commit 0377ac9 ,2021 年 5 月 7 日)

rebase : don't override --no-reschedule-failed-exec with config rebase : 不要用配置覆盖 --no-reschedule-failed-exec

Signed-off-by: Ævar Arnfjörð Bjarmason签字人:Ævar Arnfjörð Bjarmason

Fix a bug in how --no-reschedule-failed-exec interacts with rebase.rescheduleFailedExec=true being set in the config.修复--no-reschedule-failed-exec如何与配置中设置的 rebase.rescheduleFailedExec=true 交互的错误。
Before this change the --no-reschedule-failed-exec config option would be overridden by the config.在此更改之前,-- --no-reschedule-failed-exec配置选项将被配置覆盖。

This bug happened because of the particulars of how "rebase" works vs这个错误的发生是因为“rebase”的工作原理与
most other git commands when it comes to parsing options and config:在解析选项和配置时,大多数其他 git 命令:

When we read the config and parse the CLI options we correctly prefer the --no-reschedule-failed-exec option over rebase.rescheduleFailedExec=true in the config.当我们阅读配置并解析 CLI 选项时,我们正确地更喜欢配置中的--no-reschedule-failed-exec选项而不是rebase.rescheduleFailedExec=true
So far so good.到现在为止还挺好。

However the --reschedule-failed-exec option doesn't take effect when the rebase starts (we'd just create a ".git/rebase-merge/reschedule-failed-exec" file if it was true).然而,当 rebase 开始时--reschedule-failed-exec选项不会生效(如果它是真的,我们只需要创建一个“.git/rebase-merge/reschedule-failed-exec”文件)。
It only takes effect when the exec command fails, at which point we'll reschedule the failed "exec" command.它仅在 exec 命令失败时生效,此时我们将重新安排失败的“exec”命令。

Since we only wrote out the positive ".git/rebase-merge/reschedule-failed-exec" under --reschedule-failed-exec , but nothing with --no-reschedule-failed-exec we'll forget that we asked not to reschedule failed "exec", and would happily re-read the config and see that rebase.rescheduleFailedExec=true is set.由于我们只在--reschedule-failed-exec下写出了肯定的“.git/rebase-merge/reschedule-failed-exec”,但没有--reschedule-failed-exec --no-reschedule-failed-exec我们会忘记我们没有问过重新安排失败的“exec”,并且很乐意重新阅读配置并看到rebase.rescheduleFailedExec=true已设置。

So the config will effectively override the user having explicitly disabled the option on the command-line.因此,配置将有效地覆盖在命令行上明确禁用该选项的用户。

Even more confusingly: Since rebase accepts different options based on its state there wasn't even a way to get around this with " rebase --continue --no-reschedule-failed-exec ( man ) (but you could of course set the config with " rebase -c ... ").更令人困惑的是:由于 rebase 根据其状态接受不同的选项,因此甚至没有办法通过“ rebase --continue --no-reschedule-failed-exec ( man )来解决这个问题(但你当然可以设置使用“ rebase -c ... ”进行配置)。

I think the least bad way out of this is to declare that for such options and config whatever we decide at the beginning of the rebase goes.我认为最不坏的方法是声明这些选项和配置我们在 rebase 开始时决定的任何内容。
So we'll now always create either a "reschedule-failed-exec" or a "no-reschedule-failed-exec file at the start, not just the former if we decided we wanted the feature.因此,我们现在将始终在开始时创建“reschedule-failed-exec”或“no-reschedule-failed-exec”文件,如果我们决定需要该功能,则不只是前者。

With this new worldview you can no longer change the setting once a rebase has started except by manually removing the state files discussed above.有了这个新的世界观,你不能再在 rebase 开始后更改设置,除非手动删除上面讨论的状态文件。
I think making it work like that is the the least confusing thing we can do.我认为让它像那样工作是我们能做的最不令人困惑的事情。

In the future we might want to learn to change the setting in the middle by combining " --edit-todo " with " --[no-]reschedule-failed-exec ", we currently don't support combining those options, or any other way to change the state in the middle of the rebase short of manually editing the files in " .git/rebase-merge/* ".将来我们可能希望通过将“ --edit-todo ”与“ --[no-]reschedule-failed-exec ”组合来学习更改中间设置,我们目前不支持组合这些选项,或者除了手动编辑“ .git/rebase-merge/* ”中的文件外,任何其他在变基过程中更改状态的方法。

The bug being fixed here originally came about because of a combination of the behavior of the code added in d421afa (" rebase : introduce --reschedule-failed-exec ", 2018-12-10, Git v2.21.0-rc0 -- merge listed in batch #4 ) and the addition of the config variable in 969de3f (" rebase : add a config option to default to --reschedule-failed-exec ", 2018-12-10, Git v2.21.0-rc0 -- merge listed in batch #4 ).该漏洞被固定在这里最初出现,因为中添加的代码的行为相结合的d421afa (“ rebase :引进--reschedule-failed-exec ”,2018年12月10日,Git的v2.21.0-RC0 - 合并第 4 批中列出)和在969de3f 中添加 config 变量(“ rebase : add a config option to default to --reschedule-failed-exec “, 2018-12-10, Git v2.21.0-rc0 -- merge第 4 批中列出)。

git rebase now includes in its man page : git rebase现在包含在其手册页中

Even though this option applies once a rebase is started, it's set for the whole rebase at the start based on either the rebase.rescheduleFailedExec configuration (see git config or " CONFIGURATION " below) or whether this option is provided.尽管此选项在 rebase 启动后适用,但它会根据rebase.rescheduleFailedExec配置(请参阅下面的git config或“ CONFIGURATION ”)或是否提供此选项在开始时为整个 rebase 设置。
Otherwise an explicit --no-reschedule-failed-exec at the start would be overridden by the presence of rebase.rescheduleFailedExec=true configuration.否则,开始时显式的--no-reschedule-failed-exec将被rebase.rescheduleFailedExec=true配置覆盖。

Introduced in Git 2.9 , you can now execute a command for each commit using the -x option without having to also add --interactive .Git 2.9 中引入,您现在可以使用-x选项为每次提交执行命令,而无需添加--interactive

Instead of running git rebase -i --exec "cmd1 && cmd2 && ..." , you can now run git rebase -x "cmd1 && cmd2 && ..." .而不是运行git rebase -i --exec "cmd1 && cmd2 && ..." ,您现在可以运行git rebase -x "cmd1 && cmd2 && ..."

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM