Skip to content

Commit c461113

Browse files
newrenchriscool
authored andcommitted
replay: add --contained to rebase contained branches
Let's add a `--contained` option that can be used along with `--onto` to rebase all the branches contained in the <revision-range> argument. Co-authored-by: Christian Couder <[email protected]> Signed-off-by: Elijah Newren <[email protected]> Signed-off-by: Christian Couder <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 22d99f0 commit c461113

File tree

3 files changed

+52
-3
lines changed

3 files changed

+52
-3
lines changed

Documentation/git-replay.txt

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ git-replay - EXPERIMENTAL: Replay commits on a new base, works with bare repos t
99
SYNOPSIS
1010
--------
1111
[verse]
12-
(EXPERIMENTAL!) 'git replay' (--onto <newbase> | --advance <branch>) <revision-range>...
12+
(EXPERIMENTAL!) 'git replay' ([--contained] --onto <newbase> | --advance <branch>) <revision-range>...
1313

1414
DESCRIPTION
1515
-----------
@@ -96,6 +96,16 @@ top of the exact same new base, they only differ in that the first
9696
provides instructions to make mybranch point at the new commits and
9797
the second provides instructions to make target point at them.
9898

99+
What if you have a stack of branches, one depending upon another, and
100+
you'd really like to rebase the whole set?
101+
102+
------------
103+
$ git replay --contained --onto origin/main origin/main..tipbranch
104+
update refs/heads/branch1 ${NEW_branch1_HASH} ${OLD_branch1_HASH}
105+
update refs/heads/branch2 ${NEW_branch2_HASH} ${OLD_branch2_HASH}
106+
update refs/heads/tipbranch ${NEW_tipbranch_HASH} ${OLD_tipbranch_HASH}
107+
------------
108+
99109
When calling `git replay`, one does not need to specify a range of
100110
commits to replay using the syntax `A..B`; any range expression will
101111
do:

builtin/replay.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,7 @@ int cmd_replay(int argc, const char **argv, const char *prefix)
258258
const char *advance_name = NULL;
259259
struct commit *onto = NULL;
260260
const char *onto_name = NULL;
261+
int contained = 0;
261262

262263
struct rev_info revs;
263264
struct commit *last_commit = NULL;
@@ -268,7 +269,9 @@ int cmd_replay(int argc, const char **argv, const char *prefix)
268269
int ret = 0;
269270

270271
const char * const replay_usage[] = {
271-
N_("(EXPERIMENTAL!) git replay (--onto <newbase> | --advance <branch>) <revision-range>..."),
272+
N_("(EXPERIMENTAL!) git replay "
273+
"([--contained] --onto <newbase> | --advance <branch>) "
274+
"<revision-range>..."),
272275
NULL
273276
};
274277
struct option replay_options[] = {
@@ -278,6 +281,8 @@ int cmd_replay(int argc, const char **argv, const char *prefix)
278281
OPT_STRING(0, "onto", &onto_name,
279282
N_("revision"),
280283
N_("replay onto given commit")),
284+
OPT_BOOL(0, "contained", &contained,
285+
N_("advance all branches contained in revision-range")),
281286
OPT_END()
282287
};
283288

@@ -289,6 +294,10 @@ int cmd_replay(int argc, const char **argv, const char *prefix)
289294
usage_with_options(replay_usage, replay_options);
290295
}
291296

297+
if (advance_name && contained)
298+
die(_("options '%s' and '%s' cannot be used together"),
299+
"--advance", "--contained");
300+
292301
repo_init_revisions(the_repository, &revs, prefix);
293302

294303
/*
@@ -377,7 +386,8 @@ int cmd_replay(int argc, const char **argv, const char *prefix)
377386
continue;
378387
while (decoration) {
379388
if (decoration->type == DECORATION_REF_LOCAL &&
380-
strset_contains(update_refs, decoration->name)) {
389+
(contained || strset_contains(update_refs,
390+
decoration->name))) {
381391
printf("update %s %s %s\n",
382392
decoration->name,
383393
oid_to_hex(&last_commit->object.oid),

t/t3650-replay-basics.sh

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,4 +114,33 @@ test_expect_success 'replay fails when both --advance and --onto are omitted' '
114114
test_must_fail git replay topic1..topic2 >result
115115
'
116116

117+
test_expect_success 'using replay to also rebase a contained branch' '
118+
git replay --contained --onto main main..topic3 >result &&
119+
120+
test_line_count = 2 result &&
121+
cut -f 3 -d " " result >new-branch-tips &&
122+
123+
git log --format=%s $(head -n 1 new-branch-tips) >actual &&
124+
test_write_lines F C M L B A >expect &&
125+
test_cmp expect actual &&
126+
127+
git log --format=%s $(tail -n 1 new-branch-tips) >actual &&
128+
test_write_lines H G F C M L B A >expect &&
129+
test_cmp expect actual &&
130+
131+
printf "update refs/heads/topic1 " >expect &&
132+
printf "%s " $(head -n 1 new-branch-tips) >>expect &&
133+
git rev-parse topic1 >>expect &&
134+
printf "update refs/heads/topic3 " >>expect &&
135+
printf "%s " $(tail -n 1 new-branch-tips) >>expect &&
136+
git rev-parse topic3 >>expect &&
137+
138+
test_cmp expect result
139+
'
140+
141+
test_expect_success 'using replay on bare repo to also rebase a contained branch' '
142+
git -C bare replay --contained --onto main main..topic3 >result-bare &&
143+
test_cmp expect result-bare
144+
'
145+
117146
test_done

0 commit comments

Comments
 (0)