replay: add --advance or 'cherry-pick' mode

There is already a 'rebase' mode with `--onto`. Let's add an 'advance' or
'cherry-pick' mode with `--advance`. This new mode will make the target
branch advance as we replay commits onto it.

The replayed commits should have a single tip, so that it's clear where
the target branch should be advanced. If they have more than one tip,
this new mode will error out.

Co-authored-by: Christian Couder <chriscool@tuxfamily.org>
Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Elijah Newren
2023-11-24 12:10:41 +01:00
committed by Junio C Hamano
parent 3916ec307e
commit 22d99f012f
3 changed files with 243 additions and 17 deletions

View File

@ -9,7 +9,7 @@ git-replay - EXPERIMENTAL: Replay commits on a new base, works with bare repos t
SYNOPSIS
--------
[verse]
(EXPERIMENTAL!) 'git replay' --onto <newbase> <revision-range>...
(EXPERIMENTAL!) 'git replay' (--onto <newbase> | --advance <branch>) <revision-range>...
DESCRIPTION
-----------
@ -29,14 +29,25 @@ OPTIONS
Starting point at which to create the new commits. May be any
valid commit, and not just an existing branch name.
+
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 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.
--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).
<revision-range>::
Range of commits to replay; see "Specifying Ranges" in
linkgit:git-rev-parse and the "Commit Limiting" options below.
Range of commits to replay. More than one <revision-range> can
be passed, but in `--advance <branch>` mode, they should have
a single tip, so that it's clear where <branch> should point
to. See "Specifying Ranges" in linkgit:git-rev-parse and the
"Commit Limiting" options below.
include::rev-list-options.txt[]
@ -51,7 +62,9 @@ input to `git update-ref --stdin`. It is of the form:
update refs/heads/branch3 ${NEW_branch3_HASH} ${OLD_branch3_HASH}
where the number of refs updated depends on the arguments passed and
the shape of the history being replayed.
the shape of the history being replayed. When using `--advance`, the
number of refs updated is always one, but for `--onto`, it can be one
or more (rebasing multiple branches simultaneously is supported).
EXIT STATUS
-----------
@ -71,6 +84,18 @@ $ git replay --onto target origin/main..mybranch
update refs/heads/mybranch ${NEW_mybranch_HASH} ${OLD_mybranch_HASH}
------------
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.
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: