@@ -196,6 +196,115 @@ void test_rebase_setup__merge_onto_and_upstream(void)
196196 git_rebase_free (rebase );
197197}
198198
199+ /* git checkout beef && git rebase --merge --onto master gravy veal */
200+ void test_rebase_setup__merge_onto_upstream_and_branch (void )
201+ {
202+ git_rebase * rebase ;
203+ git_reference * upstream_ref , * branch_ref , * onto_ref ;
204+ git_annotated_commit * upstream_head , * branch_head , * onto_head ;
205+ git_reference * head ;
206+ git_commit * head_commit ;
207+ git_oid head_id ;
208+ git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT ;
209+
210+ checkout_opts .checkout_strategy = GIT_CHECKOUT_FORCE ;
211+
212+ cl_assert_equal_i (GIT_REPOSITORY_STATE_NONE , git_repository_state (repo ));
213+
214+ cl_git_pass (git_repository_set_head (repo , "refs/heads/beef" ));
215+ cl_git_pass (git_checkout_head (repo , & checkout_opts ));
216+
217+ cl_git_pass (git_reference_lookup (& branch_ref , repo , "refs/heads/veal" ));
218+ cl_git_pass (git_reference_lookup (& upstream_ref , repo , "refs/heads/gravy" ));
219+ cl_git_pass (git_reference_lookup (& onto_ref , repo , "refs/heads/master" ));
220+
221+ cl_git_pass (git_annotated_commit_from_ref (& branch_head , repo , branch_ref ));
222+ cl_git_pass (git_annotated_commit_from_ref (& upstream_head , repo , upstream_ref ));
223+ cl_git_pass (git_annotated_commit_from_ref (& onto_head , repo , onto_ref ));
224+
225+ cl_git_pass (git_rebase_init (& rebase , repo , branch_head , upstream_head , onto_head , NULL ));
226+
227+ git_oid_fromstr (& head_id , "efad0b11c47cb2f0220cbd6f5b0f93bb99064b00" );
228+ cl_git_pass (git_repository_head (& head , repo ));
229+ cl_git_pass (git_reference_peel ((git_object * * )& head_commit , head , GIT_OBJ_COMMIT ));
230+ cl_assert_equal_oid (& head_id , git_commit_id (head_commit ));
231+
232+ cl_assert_equal_file ("f87d14a4a236582a0278a916340a793714256864\n" , 41 , "rebase/.git/ORIG_HEAD" );
233+
234+ cl_assert_equal_i (GIT_REPOSITORY_STATE_REBASE_MERGE , git_repository_state (repo ));
235+
236+ cl_assert_equal_file ("3e8989b5a16d5258c935d998ef0e6bb139cc4757\n" , 41 , "rebase/.git/rebase-merge/cmt.1" );
237+ cl_assert_equal_file ("4cacc6f6e740a5bc64faa33e04b8ef0733d8a127\n" , 41 , "rebase/.git/rebase-merge/cmt.2" );
238+ cl_assert_equal_file ("f87d14a4a236582a0278a916340a793714256864\n" , 41 , "rebase/.git/rebase-merge/cmt.3" );
239+ cl_assert_equal_file ("3\n" , 2 , "rebase/.git/rebase-merge/end" );
240+ cl_assert_equal_file ("efad0b11c47cb2f0220cbd6f5b0f93bb99064b00\n" , 41 , "rebase/.git/rebase-merge/onto" );
241+ cl_assert_equal_file ("master\n" , 7 , "rebase/.git/rebase-merge/onto_name" );
242+ cl_assert_equal_file ("f87d14a4a236582a0278a916340a793714256864\n" , 41 , "rebase/.git/rebase-merge/orig-head" );
243+
244+ git_commit_free (head_commit );
245+ git_reference_free (head );
246+ git_annotated_commit_free (upstream_head );
247+ git_annotated_commit_free (branch_head );
248+ git_annotated_commit_free (onto_head );
249+ git_reference_free (upstream_ref );
250+ git_reference_free (branch_ref );
251+ git_reference_free (onto_ref );
252+ git_rebase_free (rebase );
253+ }
254+
255+ /* git checkout beef && git rebase --merge --onto `git rev-parse master`
256+ * `git rev-parse veal` `git rev-parse gravy`
257+ */
258+ void test_rebase_setup__merge_onto_upstream_and_branch_by_id (void )
259+ {
260+ git_rebase * rebase ;
261+ git_oid upstream_id , branch_id , onto_id ;
262+ git_annotated_commit * upstream_head , * branch_head , * onto_head ;
263+ git_reference * head ;
264+ git_commit * head_commit ;
265+ git_oid head_id ;
266+ git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT ;
267+
268+ checkout_opts .checkout_strategy = GIT_CHECKOUT_FORCE ;
269+
270+ cl_assert_equal_i (GIT_REPOSITORY_STATE_NONE , git_repository_state (repo ));
271+
272+ cl_git_pass (git_repository_set_head (repo , "refs/heads/beef" ));
273+ cl_git_pass (git_checkout_head (repo , & checkout_opts ));
274+
275+ cl_git_pass (git_oid_fromstr (& upstream_id , "f87d14a4a236582a0278a916340a793714256864" ));
276+ cl_git_pass (git_oid_fromstr (& branch_id , "d616d97082eb7bb2dc6f180a7cca940993b7a56f" ));
277+ cl_git_pass (git_oid_fromstr (& onto_id , "efad0b11c47cb2f0220cbd6f5b0f93bb99064b00" ));
278+
279+ cl_git_pass (git_annotated_commit_lookup (& upstream_head , repo , & upstream_id ));
280+ cl_git_pass (git_annotated_commit_lookup (& branch_head , repo , & branch_id ));
281+ cl_git_pass (git_annotated_commit_lookup (& onto_head , repo , & onto_id ));
282+
283+ cl_git_pass (git_rebase_init (& rebase , repo , branch_head , upstream_head , onto_head , NULL ));
284+
285+ git_oid_fromstr (& head_id , "efad0b11c47cb2f0220cbd6f5b0f93bb99064b00" );
286+ cl_git_pass (git_repository_head (& head , repo ));
287+ cl_git_pass (git_reference_peel ((git_object * * )& head_commit , head , GIT_OBJ_COMMIT ));
288+ cl_assert_equal_oid (& head_id , git_commit_id (head_commit ));
289+
290+ cl_assert_equal_file ("d616d97082eb7bb2dc6f180a7cca940993b7a56f\n" , 41 , "rebase/.git/ORIG_HEAD" );
291+
292+ cl_assert_equal_i (GIT_REPOSITORY_STATE_REBASE_MERGE , git_repository_state (repo ));
293+
294+ cl_assert_equal_file ("d616d97082eb7bb2dc6f180a7cca940993b7a56f\n" , 41 , "rebase/.git/rebase-merge/cmt.1" );
295+ cl_assert_equal_file ("1\n" , 2 , "rebase/.git/rebase-merge/end" );
296+ cl_assert_equal_file ("efad0b11c47cb2f0220cbd6f5b0f93bb99064b00\n" , 41 , "rebase/.git/rebase-merge/onto" );
297+ cl_assert_equal_file ("efad0b11c47cb2f0220cbd6f5b0f93bb99064b00\n" , 41 , "rebase/.git/rebase-merge/onto_name" );
298+ cl_assert_equal_file ("d616d97082eb7bb2dc6f180a7cca940993b7a56f\n" , 41 , "rebase/.git/rebase-merge/orig-head" );
299+
300+ git_commit_free (head_commit );
301+ git_reference_free (head );
302+ git_annotated_commit_free (upstream_head );
303+ git_annotated_commit_free (branch_head );
304+ git_annotated_commit_free (onto_head );
305+ git_rebase_free (rebase );
306+ }
307+
199308/* Ensure merge commits are dropped in a rebase */
200309/* git checkout veal && git rebase --merge master */
201310void test_rebase_setup__branch_with_merges (void )
@@ -342,6 +451,102 @@ void test_rebase_setup__merge_null_branch_uses_HEAD(void)
342451 git_rebase_free (rebase );
343452}
344453
454+ /* git checkout b146bd7608eac53d9bf9e1a6963543588b555c64 && git rebase --merge master */
455+ void test_rebase_setup__merge_from_detached (void )
456+ {
457+ git_rebase * rebase ;
458+ git_reference * upstream_ref ;
459+ git_annotated_commit * branch_head , * upstream_head ;
460+ git_reference * head ;
461+ git_commit * head_commit ;
462+ git_oid branch_id , head_id ;
463+
464+ cl_assert_equal_i (GIT_REPOSITORY_STATE_NONE , git_repository_state (repo ));
465+
466+ cl_git_pass (git_reference_lookup (& upstream_ref , repo , "refs/heads/master" ));
467+
468+ cl_git_pass (git_oid_fromstr (& branch_id , "b146bd7608eac53d9bf9e1a6963543588b555c64" ));
469+
470+ cl_git_pass (git_annotated_commit_lookup (& branch_head , repo , & branch_id ));
471+ cl_git_pass (git_annotated_commit_from_ref (& upstream_head , repo , upstream_ref ));
472+
473+ cl_git_pass (git_rebase_init (& rebase , repo , branch_head , upstream_head , NULL , NULL ));
474+
475+ cl_assert_equal_i (GIT_REPOSITORY_STATE_REBASE_MERGE , git_repository_state (repo ));
476+
477+ git_oid_fromstr (& head_id , "efad0b11c47cb2f0220cbd6f5b0f93bb99064b00" );
478+ cl_git_pass (git_repository_head (& head , repo ));
479+ cl_git_pass (git_reference_peel ((git_object * * )& head_commit , head , GIT_OBJ_COMMIT ));
480+ cl_assert_equal_oid (& head_id , git_commit_id (head_commit ));
481+
482+ cl_assert_equal_file ("b146bd7608eac53d9bf9e1a6963543588b555c64\n" , 41 , "rebase/.git/ORIG_HEAD" );
483+
484+ cl_assert_equal_file ("da9c51a23d02d931a486f45ad18cda05cf5d2b94\n" , 41 , "rebase/.git/rebase-merge/cmt.1" );
485+ cl_assert_equal_file ("8d1f13f93c4995760ac07d129246ac1ff64c0be9\n" , 41 , "rebase/.git/rebase-merge/cmt.2" );
486+ cl_assert_equal_file ("3069cc907e6294623e5917ef6de663928c1febfb\n" , 41 , "rebase/.git/rebase-merge/cmt.3" );
487+ cl_assert_equal_file ("588e5d2f04d49707fe4aab865e1deacaf7ef6787\n" , 41 , "rebase/.git/rebase-merge/cmt.4" );
488+ cl_assert_equal_file ("b146bd7608eac53d9bf9e1a6963543588b555c64\n" , 41 , "rebase/.git/rebase-merge/cmt.5" );
489+ cl_assert_equal_file ("5\n" , 2 , "rebase/.git/rebase-merge/end" );
490+ cl_assert_equal_file ("efad0b11c47cb2f0220cbd6f5b0f93bb99064b00\n" , 41 , "rebase/.git/rebase-merge/onto" );
491+ cl_assert_equal_file ("master\n" , 7 , "rebase/.git/rebase-merge/onto_name" );
492+ cl_assert_equal_file ("b146bd7608eac53d9bf9e1a6963543588b555c64\n" , 41 , "rebase/.git/rebase-merge/orig-head" );
493+
494+ git_commit_free (head_commit );
495+ git_reference_free (head );
496+ git_annotated_commit_free (branch_head );
497+ git_annotated_commit_free (upstream_head );
498+ git_reference_free (upstream_ref );
499+ git_rebase_free (rebase );
500+ }
501+
502+ /* git checkout beef && git rebase --merge efad0b11c47cb2f0220cbd6f5b0f93bb99064b00 */
503+ void test_rebase_setup__merge_branch_by_id (void )
504+ {
505+ git_rebase * rebase ;
506+ git_reference * branch_ref ;
507+ git_annotated_commit * branch_head , * upstream_head ;
508+ git_reference * head ;
509+ git_commit * head_commit ;
510+ git_oid head_id , upstream_id ;
511+
512+ cl_assert_equal_i (GIT_REPOSITORY_STATE_NONE , git_repository_state (repo ));
513+
514+ cl_git_pass (git_reference_lookup (& branch_ref , repo , "refs/heads/beef" ));
515+
516+ cl_git_pass (git_oid_fromstr (& upstream_id , "efad0b11c47cb2f0220cbd6f5b0f93bb99064b00" ));
517+
518+ cl_git_pass (git_annotated_commit_from_ref (& branch_head , repo , branch_ref ));
519+ cl_git_pass (git_annotated_commit_lookup (& upstream_head , repo , & upstream_id ));
520+
521+ cl_git_pass (git_rebase_init (& rebase , repo , branch_head , upstream_head , NULL , NULL ));
522+
523+ cl_assert_equal_i (GIT_REPOSITORY_STATE_REBASE_MERGE , git_repository_state (repo ));
524+
525+ git_oid_fromstr (& head_id , "efad0b11c47cb2f0220cbd6f5b0f93bb99064b00" );
526+ cl_git_pass (git_repository_head (& head , repo ));
527+ cl_git_pass (git_reference_peel ((git_object * * )& head_commit , head , GIT_OBJ_COMMIT ));
528+ cl_assert_equal_oid (& head_id , git_commit_id (head_commit ));
529+
530+ cl_assert_equal_file ("b146bd7608eac53d9bf9e1a6963543588b555c64\n" , 41 , "rebase/.git/ORIG_HEAD" );
531+
532+ cl_assert_equal_file ("da9c51a23d02d931a486f45ad18cda05cf5d2b94\n" , 41 , "rebase/.git/rebase-merge/cmt.1" );
533+ cl_assert_equal_file ("8d1f13f93c4995760ac07d129246ac1ff64c0be9\n" , 41 , "rebase/.git/rebase-merge/cmt.2" );
534+ cl_assert_equal_file ("3069cc907e6294623e5917ef6de663928c1febfb\n" , 41 , "rebase/.git/rebase-merge/cmt.3" );
535+ cl_assert_equal_file ("588e5d2f04d49707fe4aab865e1deacaf7ef6787\n" , 41 , "rebase/.git/rebase-merge/cmt.4" );
536+ cl_assert_equal_file ("b146bd7608eac53d9bf9e1a6963543588b555c64\n" , 41 , "rebase/.git/rebase-merge/cmt.5" );
537+ cl_assert_equal_file ("5\n" , 2 , "rebase/.git/rebase-merge/end" );
538+ cl_assert_equal_file ("efad0b11c47cb2f0220cbd6f5b0f93bb99064b00\n" , 41 , "rebase/.git/rebase-merge/onto" );
539+ cl_assert_equal_file ("efad0b11c47cb2f0220cbd6f5b0f93bb99064b00\n" , 41 , "rebase/.git/rebase-merge/onto_name" );
540+ cl_assert_equal_file ("b146bd7608eac53d9bf9e1a6963543588b555c64\n" , 41 , "rebase/.git/rebase-merge/orig-head" );
541+
542+ git_commit_free (head_commit );
543+ git_reference_free (head );
544+ git_annotated_commit_free (branch_head );
545+ git_annotated_commit_free (upstream_head );
546+ git_reference_free (branch_ref );
547+ git_rebase_free (rebase );
548+ }
549+
345550static int rebase_is_blocked (void )
346551{
347552 git_rebase * rebase = NULL ;
0 commit comments