aboutsummaryrefslogtreecommitdiffstats
path: root/Documentation
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2025-11-24 15:46:40 -0800
committerJunio C Hamano <gitster@pobox.com>2025-11-24 15:46:40 -0800
commit9370a6be79e89112486e99ff75db43e3c15841e5 (patch)
tree68c2609a477422028e30c5916e649bacfbd51529 /Documentation
parentd91d79f26d5f2fb0468f42bf5d44356dce15a414 (diff)
parent336ac90c06ec757f613faae4ffc6c32578a99cd1 (diff)
downloadgit-9370a6be79e89112486e99ff75db43e3c15841e5.tar.gz
Merge branch 'sa/replay-atomic-ref-updates'
"git replay" (experimental) learned to perform ref updates itself in a transaction by default, instead of emitting where each refs should point at and leaving the actual update to another command. * sa/replay-atomic-ref-updates: replay: add replay.refAction config option replay: make atomic ref updates the default behavior replay: use die_for_incompatible_opt2() for option validation
Diffstat (limited to 'Documentation')
-rw-r--r--Documentation/config/replay.adoc11
-rw-r--r--Documentation/git-replay.adoc63
2 files changed, 52 insertions, 22 deletions
diff --git a/Documentation/config/replay.adoc b/Documentation/config/replay.adoc
new file mode 100644
index 0000000000..7d549d2f0e
--- /dev/null
+++ b/Documentation/config/replay.adoc
@@ -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.
diff --git a/Documentation/git-replay.adoc b/Documentation/git-replay.adoc
index 0b12bf8aa4..dcb26e8a8e 100644
--- a/Documentation/git-replay.adoc
+++ b/Documentation/git-replay.adoc
@@ -9,15 +9,16 @@ git-replay - EXPERIMENTAL: Replay commits on a new base, works with bare repos t
SYNOPSIS
--------
[verse]
-(EXPERIMENTAL!) 'git replay' ([--contained] --onto <newbase> | --advance <branch>) <revision-range>...
+(EXPERIMENTAL!) 'git replay' ([--contained] --onto <newbase> | --advance <branch>) [--ref-action[=<mode>]] <revision-range>...
DESCRIPTION
-----------
Takes ranges of commits and replays them onto a new location. Leaves
-the working tree and the index untouched, and updates no references.
-The output of this command is meant to be used as input to
-`git update-ref --stdin`, which would update the relevant branches
+the working tree and the index untouched. By default, updates the
+relevant references using an atomic transaction (all refs update or
+none). Use `--ref-action=print` to avoid automatic ref updates and
+instead get update commands that can be piped to `git update-ref --stdin`
(see the OUTPUT section below).
THIS COMMAND IS EXPERIMENTAL. THE BEHAVIOR MAY CHANGE.
@@ -29,18 +30,29 @@ OPTIONS
Starting point at which to create the new commits. May be any
valid commit, and not just an existing branch name.
+
-When `--onto` is specified, the update-ref command(s) in the output will
-update the branch(es) in the revision range to point at the new
-commits, similar to the way how `git rebase --update-refs` updates
-multiple branches in the affected range.
+When `--onto` is specified, the branch(es) in the revision range will be
+updated to point at the new commits, similar to the way `git rebase --update-refs`
+updates multiple branches in the affected range.
--advance <branch>::
Starting point at which to create the new commits; must be a
branch name.
+
-When `--advance` is specified, the update-ref command(s) in the output
-will update the branch passed as an argument to `--advance` to point at
-the new commits (in other words, this mimics a cherry-pick operation).
+The history is replayed on top of the <branch> and <branch> is updated to
+point at the tip of the resulting history. This is different from `--onto`,
+which uses the target only as a starting point without updating it.
+
+--ref-action[=<mode>]::
+ Control how references are updated. The mode can be:
++
+--
+ * `update` (default): Update refs directly using an atomic transaction.
+ All refs are updated or none are (all-or-nothing behavior).
+ * `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
@@ -54,8 +66,11 @@ include::rev-list-options.adoc[]
OUTPUT
------
-When there are no conflicts, the output of this command is usable as
-input to `git update-ref --stdin`. It is of the form:
+By default, or with `--ref-action=update`, this command produces no output on
+success, as refs are updated directly using an atomic transaction.
+
+When using `--ref-action=print`, the output is usable as input to
+`git update-ref --stdin`. It is of the form:
update refs/heads/branch1 ${NEW_branch1_HASH} ${OLD_branch1_HASH}
update refs/heads/branch2 ${NEW_branch2_HASH} ${OLD_branch2_HASH}
@@ -81,6 +96,14 @@ To simply rebase `mybranch` onto `target`:
------------
$ git replay --onto target origin/main..mybranch
+------------
+
+The refs are updated atomically and no output is produced on success.
+
+To see what would be updated without actually updating:
+
+------------
+$ git replay --ref-action=print --onto target origin/main..mybranch
update refs/heads/mybranch ${NEW_mybranch_HASH} ${OLD_mybranch_HASH}
------------
@@ -88,33 +111,29 @@ To cherry-pick the commits from mybranch onto target:
------------
$ git replay --advance target origin/main..mybranch
-update refs/heads/target ${NEW_target_HASH} ${OLD_target_HASH}
------------
Note that the first two examples replay the exact same commits and on
top of the exact same new base, they only differ in that the first
-provides instructions to make mybranch point at the new commits and
-the second provides instructions to make target point at them.
+updates mybranch to point at the new commits and the second updates
+target to point at them.
What if you have a stack of branches, one depending upon another, and
you'd really like to rebase the whole set?
------------
$ git replay --contained --onto origin/main origin/main..tipbranch
-update refs/heads/branch1 ${NEW_branch1_HASH} ${OLD_branch1_HASH}
-update refs/heads/branch2 ${NEW_branch2_HASH} ${OLD_branch2_HASH}
-update refs/heads/tipbranch ${NEW_tipbranch_HASH} ${OLD_tipbranch_HASH}
------------
+All three branches (`branch1`, `branch2`, and `tipbranch`) are updated
+atomically.
+
When calling `git replay`, one does not need to specify a range of
commits to replay using the syntax `A..B`; any range expression will
do:
------------
$ git replay --onto origin/main ^base branch1 branch2 branch3
-update refs/heads/branch1 ${NEW_branch1_HASH} ${OLD_branch1_HASH}
-update refs/heads/branch2 ${NEW_branch2_HASH} ${OLD_branch2_HASH}
-update refs/heads/branch3 ${NEW_branch3_HASH} ${OLD_branch3_HASH}
------------
This will simultaneously rebase `branch1`, `branch2`, and `branch3`,