--- /dev/null
+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.
* `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
#include "git-compat-util.h"
#include "builtin.h"
+#include "config.h"
#include "environment.h"
#include "hex.h"
#include "lockfile.h"
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,
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;
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);
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