replay: add replay.refAction config option

Add a configuration variable to control the default behavior of git replay
for updating references. This allows users who prefer the traditional
pipeline output to set it once in their config instead of passing
--ref-action=print with every command.

The config variable uses string values that mirror the behavior modes:
  * replay.refAction = update (default): atomic ref updates
  * replay.refAction = print: output commands for pipeline

Helped-by: Junio C Hamano <gitster@pobox.com>
Helped-by: Elijah Newren <newren@gmail.com>
Helped-by: Christian Couder <christian.couder@gmail.com>
Helped-by: Phillip Wood <phillip.wood123@gmail.com>
Signed-off-by: Siddharth Asthana <siddharthasthana31@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Siddharth Asthana
2025-11-06 00:46:01 +05:30
committed by Junio C Hamano
parent 15cd4ef1f4
commit 336ac90c06
4 changed files with 79 additions and 4 deletions

View File

@@ -0,0 +1,11 @@
replay.refAction::
Specifies the default mode for handling reference updates in
`git replay`. The value can be:
+
--
* `update`: Update refs directly using an atomic transaction (default behavior).
* `print`: Output update-ref commands for pipeline use.
--
+
This setting can be overridden with the `--ref-action` command-line option.
When not configured, `git replay` defaults to `update` mode.

View File

@@ -51,6 +51,8 @@ which uses the target only as a starting point without updating it.
* `print`: Output update-ref commands for pipeline use. This is the
traditional behavior where output can be piped to `git update-ref --stdin`.
--
+
The default mode can be configured via the `replay.refAction` configuration variable.
<revision-range>::
Range of commits to replay. More than one <revision-range> can

View File

@@ -8,6 +8,7 @@
#include "git-compat-util.h"
#include "builtin.h"
#include "config.h"
#include "environment.h"
#include "hex.h"
#include "lockfile.h"
@@ -298,6 +299,22 @@ static enum ref_action_mode parse_ref_action_mode(const char *ref_action, const
die(_("invalid %s value: '%s'"), source, ref_action);
}
static enum ref_action_mode get_ref_action_mode(struct repository *repo, const char *ref_action)
{
const char *config_value = NULL;
/* Command line option takes precedence */
if (ref_action)
return parse_ref_action_mode(ref_action, "--ref-action");
/* Check config value */
if (!repo_config_get_string_tmp(repo, "replay.refAction", &config_value))
return parse_ref_action_mode(config_value, "replay.refAction");
/* Default to update mode */
return REF_ACTION_UPDATE;
}
static int handle_ref_update(enum ref_action_mode mode,
struct ref_transaction *transaction,
const char *refname,
@@ -332,7 +349,7 @@ int cmd_replay(int argc,
const char *onto_name = NULL;
int contained = 0;
const char *ref_action = NULL;
enum ref_action_mode ref_mode = REF_ACTION_UPDATE;
enum ref_action_mode ref_mode;
struct rev_info revs;
struct commit *last_commit = NULL;
@@ -378,9 +395,8 @@ int cmd_replay(int argc,
die_for_incompatible_opt2(!!advance_name_opt, "--advance",
contained, "--contained");
/* Parse ref action mode */
if (ref_action)
ref_mode = parse_ref_action_mode(ref_action, "--ref-action");
/* Parse ref action mode from command line or config */
ref_mode = get_ref_action_mode(repo, ref_action);
advance_name = xstrdup_or_null(advance_name_opt);

View File

@@ -268,4 +268,50 @@ test_expect_success 'reflog message for --advance mode' '
test_cmp expect-reflog reflog-msg
'
test_expect_success 'replay.refAction=print config option' '
# Store original state
START=$(git rev-parse topic2) &&
test_when_finished "git branch -f topic2 $START" &&
# Test with config set to print
test_config replay.refAction print &&
git replay --onto main topic1..topic2 >output &&
test_line_count = 1 output &&
test_grep "^update refs/heads/topic2 " output
'
test_expect_success 'replay.refAction=update config option' '
# Store original state
START=$(git rev-parse topic2) &&
test_when_finished "git branch -f topic2 $START" &&
# Test with config set to update
test_config replay.refAction update &&
git replay --onto main topic1..topic2 >output &&
test_must_be_empty output &&
# Verify ref was updated
git log --format=%s topic2 >actual &&
test_write_lines E D M L B A >expect &&
test_cmp expect actual
'
test_expect_success 'command-line --ref-action overrides config' '
# Store original state
START=$(git rev-parse topic2) &&
test_when_finished "git branch -f topic2 $START" &&
# Set config to update but use --ref-action=print
test_config replay.refAction update &&
git replay --ref-action=print --onto main topic1..topic2 >output &&
test_line_count = 1 output &&
test_grep "^update refs/heads/topic2 " output
'
test_expect_success 'invalid replay.refAction value' '
test_config replay.refAction invalid &&
test_must_fail git replay --onto main topic1..topic2 2>error &&
test_grep "invalid.*replay.refAction.*value" error
'
test_done