Skip to content

Commit 2e43a37

Browse files
committed
Merge pull request libgit2#3769 from libgit2/ethomson/rebase_inmemory_no_base
Rebase: rebase a branch with no merge base for in-memory
2 parents 4d384d6 + 9a363d1 commit 2e43a37

File tree

3 files changed

+119
-9
lines changed

3 files changed

+119
-9
lines changed

src/rebase.c

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -852,17 +852,28 @@ static int rebase_next_inmemory(
852852
git_tree *current_tree = NULL, *head_tree = NULL, *parent_tree = NULL;
853853
git_rebase_operation *operation;
854854
git_index *index = NULL;
855+
unsigned int parent_count;
855856
int error;
856857

857858
*out = NULL;
858859

859860
operation = git_array_get(rebase->operations, rebase->current);
860861

861862
if ((error = git_commit_lookup(&current_commit, rebase->repo, &operation->id)) < 0 ||
862-
(error = git_commit_tree(&current_tree, current_commit)) < 0 ||
863-
(error = git_commit_parent(&parent_commit, current_commit, 0)) < 0 ||
864-
(error = git_commit_tree(&parent_tree, parent_commit)) < 0 ||
865-
(error = git_commit_tree(&head_tree, rebase->last_commit)) < 0 ||
863+
(error = git_commit_tree(&current_tree, current_commit)) < 0)
864+
goto done;
865+
866+
if ((parent_count = git_commit_parentcount(current_commit)) > 1) {
867+
giterr_set(GITERR_REBASE, "Cannot rebase a merge commit");
868+
error = -1;
869+
goto done;
870+
} else if (parent_count) {
871+
if ((error = git_commit_parent(&parent_commit, current_commit, 0)) < 0 ||
872+
(error = git_commit_tree(&parent_tree, parent_commit)) < 0)
873+
goto done;
874+
}
875+
876+
if ((error = git_commit_tree(&head_tree, rebase->last_commit)) < 0 ||
866877
(error = git_merge_trees(&index, rebase->repo, parent_tree, head_tree, current_tree, &rebase->options.merge_options)) < 0)
867878
goto done;
868879

tests/rebase/inmemory.c

Lines changed: 56 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,20 @@
55
#include <fcntl.h>
66

77
static git_repository *repo;
8+
static git_signature *signature;
89

910
// Fixture setup and teardown
1011
void test_rebase_inmemory__initialize(void)
1112
{
1213
repo = cl_git_sandbox_init("rebase");
14+
15+
cl_git_pass(git_signature_new(&signature,
16+
"Rebaser", "rebaser@rebaser.rb", 1405694510, 0));
1317
}
1418

1519
void test_rebase_inmemory__cleanup(void)
1620
{
21+
git_signature_free(signature);
1722
cl_git_sandbox_cleanup();
1823
}
1924

@@ -53,14 +58,10 @@ void test_rebase_inmemory__can_resolve_conflicts(void)
5358
git_rebase_operation *rebase_operation;
5459
git_status_list *status_list;
5560
git_oid pick_id, commit_id, expected_commit_id;
56-
git_signature *signature;
5761
git_index *rebase_index, *repo_index;
5862
git_index_entry resolution = {{0}};
5963
git_rebase_options opts = GIT_REBASE_OPTIONS_INIT;
6064

61-
cl_git_pass(git_signature_new(&signature,
62-
"Rebaser", "rebaser@rebaser.rb", 1405694510, 0));
63-
6465
opts.inmemory = true;
6566

6667
cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/asparagus"));
@@ -104,7 +105,6 @@ void test_rebase_inmemory__can_resolve_conflicts(void)
104105
cl_git_pass(git_oid_fromstr(&expected_commit_id, "db7af47222181e548810da2ab5fec0e9357c5637"));
105106
cl_assert_equal_oid(&commit_id, &expected_commit_id);
106107

107-
git_signature_free(signature);
108108
git_status_list_free(status_list);
109109
git_annotated_commit_free(branch_head);
110110
git_annotated_commit_free(upstream_head);
@@ -114,3 +114,54 @@ void test_rebase_inmemory__can_resolve_conflicts(void)
114114
git_index_free(rebase_index);
115115
git_rebase_free(rebase);
116116
}
117+
118+
void test_rebase_inmemory__no_common_ancestor(void)
119+
{
120+
git_rebase *rebase;
121+
git_reference *branch_ref, *upstream_ref;
122+
git_annotated_commit *branch_head, *upstream_head;
123+
git_rebase_operation *rebase_operation;
124+
git_oid commit_id, expected_final_id;
125+
git_rebase_options opts = GIT_REBASE_OPTIONS_INIT;
126+
127+
opts.inmemory = true;
128+
129+
cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/barley"));
130+
cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/master"));
131+
132+
cl_git_pass(git_annotated_commit_from_ref(&branch_head, repo, branch_ref));
133+
cl_git_pass(git_annotated_commit_from_ref(&upstream_head, repo, upstream_ref));
134+
135+
cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, &opts));
136+
137+
cl_git_pass(git_rebase_next(&rebase_operation, rebase));
138+
cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
139+
NULL, NULL));
140+
141+
cl_git_pass(git_rebase_next(&rebase_operation, rebase));
142+
cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
143+
NULL, NULL));
144+
145+
cl_git_pass(git_rebase_next(&rebase_operation, rebase));
146+
cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
147+
NULL, NULL));
148+
149+
cl_git_pass(git_rebase_next(&rebase_operation, rebase));
150+
cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
151+
NULL, NULL));
152+
153+
cl_git_pass(git_rebase_next(&rebase_operation, rebase));
154+
cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
155+
NULL, NULL));
156+
157+
cl_git_pass(git_rebase_finish(rebase, signature));
158+
159+
git_oid_fromstr(&expected_final_id, "71e7ee8d4fe7d8bf0d107355197e0a953dfdb7f3");
160+
cl_assert_equal_oid(&expected_final_id, &commit_id);
161+
162+
git_annotated_commit_free(branch_head);
163+
git_annotated_commit_free(upstream_head);
164+
git_reference_free(branch_ref);
165+
git_reference_free(upstream_ref);
166+
git_rebase_free(rebase);
167+
}

tests/rebase/merge.c

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -525,6 +525,54 @@ void test_rebase_merge__finish_with_ids(void)
525525
git_rebase_free(rebase);
526526
}
527527

528+
void test_rebase_merge__no_common_ancestor(void)
529+
{
530+
git_rebase *rebase;
531+
git_reference *branch_ref, *upstream_ref;
532+
git_annotated_commit *branch_head, *upstream_head;
533+
git_rebase_operation *rebase_operation;
534+
git_oid commit_id, expected_final_id;
535+
536+
cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/barley"));
537+
cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/master"));
538+
539+
cl_git_pass(git_annotated_commit_from_ref(&branch_head, repo, branch_ref));
540+
cl_git_pass(git_annotated_commit_from_ref(&upstream_head, repo, upstream_ref));
541+
542+
cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, NULL));
543+
544+
cl_git_pass(git_rebase_next(&rebase_operation, rebase));
545+
cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
546+
NULL, NULL));
547+
548+
cl_git_pass(git_rebase_next(&rebase_operation, rebase));
549+
cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
550+
NULL, NULL));
551+
552+
cl_git_pass(git_rebase_next(&rebase_operation, rebase));
553+
cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
554+
NULL, NULL));
555+
556+
cl_git_pass(git_rebase_next(&rebase_operation, rebase));
557+
cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
558+
NULL, NULL));
559+
560+
cl_git_pass(git_rebase_next(&rebase_operation, rebase));
561+
cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
562+
NULL, NULL));
563+
564+
cl_git_pass(git_rebase_finish(rebase, signature));
565+
566+
git_oid_fromstr(&expected_final_id, "71e7ee8d4fe7d8bf0d107355197e0a953dfdb7f3");
567+
cl_assert_equal_oid(&expected_final_id, &commit_id);
568+
569+
git_annotated_commit_free(branch_head);
570+
git_annotated_commit_free(upstream_head);
571+
git_reference_free(branch_ref);
572+
git_reference_free(upstream_ref);
573+
git_rebase_free(rebase);
574+
}
575+
528576
static void test_copy_note(
529577
const git_rebase_options *opts,
530578
bool should_exist)

0 commit comments

Comments
 (0)