Skip to content

Commit 363d54f

Browse files
committed
Merge branch 'ah/rebase-keep-base-fix' into maint
"git rebase --keep-base <upstream> <branch-to-rebase>" computed the commit to rebase onto incorrectly, which has been corrected. source: <[email protected]> * ah/rebase-keep-base-fix: rebase: use correct base for --keep-base when a branch is given
2 parents d777ef9 + 9e5ebe9 commit 363d54f

File tree

3 files changed

+60
-29
lines changed

3 files changed

+60
-29
lines changed

Documentation/git-rebase.txt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -215,9 +215,10 @@ leave out at most one of A and B, in which case it defaults to HEAD.
215215

216216
--keep-base::
217217
Set the starting point at which to create the new commits to the
218-
merge base of <upstream> <branch>. Running
218+
merge base of <upstream> and <branch>. Running
219219
'git rebase --keep-base <upstream> <branch>' is equivalent to
220-
running 'git rebase --onto <upstream>... <upstream>'.
220+
running
221+
'git rebase --onto <upstream>...<branch> <upstream> <branch>'.
221222
+
222223
This option is useful in the case where one is developing a feature on
223224
top of an upstream branch. While the feature is being worked on, the

builtin/rebase.c

Lines changed: 28 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1583,33 +1583,6 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
15831583
options.upstream_arg = "--root";
15841584
}
15851585

1586-
/* Make sure the branch to rebase onto is valid. */
1587-
if (keep_base) {
1588-
strbuf_reset(&buf);
1589-
strbuf_addstr(&buf, options.upstream_name);
1590-
strbuf_addstr(&buf, "...");
1591-
options.onto_name = xstrdup(buf.buf);
1592-
} else if (!options.onto_name)
1593-
options.onto_name = options.upstream_name;
1594-
if (strstr(options.onto_name, "...")) {
1595-
if (get_oid_mb(options.onto_name, &merge_base) < 0) {
1596-
if (keep_base)
1597-
die(_("'%s': need exactly one merge base with branch"),
1598-
options.upstream_name);
1599-
else
1600-
die(_("'%s': need exactly one merge base"),
1601-
options.onto_name);
1602-
}
1603-
options.onto = lookup_commit_or_die(&merge_base,
1604-
options.onto_name);
1605-
} else {
1606-
options.onto =
1607-
lookup_commit_reference_by_name(options.onto_name);
1608-
if (!options.onto)
1609-
die(_("Does not point to a valid commit '%s'"),
1610-
options.onto_name);
1611-
}
1612-
16131586
/*
16141587
* If the branch to rebase is given, that is the branch we will rebase
16151588
* branch_name -- branch/commit being rebased, or
@@ -1659,6 +1632,34 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
16591632
} else
16601633
BUG("unexpected number of arguments left to parse");
16611634

1635+
/* Make sure the branch to rebase onto is valid. */
1636+
if (keep_base) {
1637+
strbuf_reset(&buf);
1638+
strbuf_addstr(&buf, options.upstream_name);
1639+
strbuf_addstr(&buf, "...");
1640+
strbuf_addstr(&buf, branch_name);
1641+
options.onto_name = xstrdup(buf.buf);
1642+
} else if (!options.onto_name)
1643+
options.onto_name = options.upstream_name;
1644+
if (strstr(options.onto_name, "...")) {
1645+
if (get_oid_mb(options.onto_name, &merge_base) < 0) {
1646+
if (keep_base)
1647+
die(_("'%s': need exactly one merge base with branch"),
1648+
options.upstream_name);
1649+
else
1650+
die(_("'%s': need exactly one merge base"),
1651+
options.onto_name);
1652+
}
1653+
options.onto = lookup_commit_or_die(&merge_base,
1654+
options.onto_name);
1655+
} else {
1656+
options.onto =
1657+
lookup_commit_reference_by_name(options.onto_name);
1658+
if (!options.onto)
1659+
die(_("Does not point to a valid commit '%s'"),
1660+
options.onto_name);
1661+
}
1662+
16621663
if (options.fork_point > 0) {
16631664
struct commit *head =
16641665
lookup_commit_reference(the_repository,

t/t3416-rebase-onto-threedots.sh

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,20 @@ test_expect_success 'rebase --keep-base main from topic' '
129129
test_cmp expect actual
130130
'
131131

132+
test_expect_success 'rebase --keep-base main topic from main' '
133+
git checkout main &&
134+
git branch -f topic G &&
135+
136+
git rebase --keep-base main topic &&
137+
git rev-parse C >base.expect &&
138+
git merge-base main HEAD >base.actual &&
139+
test_cmp base.expect base.actual &&
140+
141+
git rev-parse HEAD~2 >actual &&
142+
git rev-parse C^0 >expect &&
143+
test_cmp expect actual
144+
'
145+
132146
test_expect_success 'rebase --keep-base main from side' '
133147
git reset --hard &&
134148
git checkout side &&
@@ -153,6 +167,21 @@ test_expect_success 'rebase -i --keep-base main from topic' '
153167
test_cmp expect actual
154168
'
155169

170+
test_expect_success 'rebase -i --keep-base main topic from main' '
171+
git checkout main &&
172+
git branch -f topic G &&
173+
174+
set_fake_editor &&
175+
EXPECT_COUNT=2 git rebase -i --keep-base main topic &&
176+
git rev-parse C >base.expect &&
177+
git merge-base main HEAD >base.actual &&
178+
test_cmp base.expect base.actual &&
179+
180+
git rev-parse HEAD~2 >actual &&
181+
git rev-parse C^0 >expect &&
182+
test_cmp expect actual
183+
'
184+
156185
test_expect_success 'rebase -i --keep-base main from side' '
157186
git reset --hard &&
158187
git checkout side &&

0 commit comments

Comments
 (0)