@@ -582,6 +582,100 @@ static void update_refs_for_switch(struct checkout_opts *opts,
582
582
report_tracking (new );
583
583
}
584
584
585
+ struct rev_list_args {
586
+ int argc ;
587
+ int alloc ;
588
+ const char * * argv ;
589
+ };
590
+
591
+ static void add_one_rev_list_arg (struct rev_list_args * args , const char * s )
592
+ {
593
+ ALLOC_GROW (args -> argv , args -> argc + 1 , args -> alloc );
594
+ args -> argv [args -> argc ++ ] = s ;
595
+ }
596
+
597
+ static int add_one_ref_to_rev_list_arg (const char * refname ,
598
+ const unsigned char * sha1 ,
599
+ int flags ,
600
+ void * cb_data )
601
+ {
602
+ add_one_rev_list_arg (cb_data , refname );
603
+ return 0 ;
604
+ }
605
+
606
+
607
+ static void describe_one_orphan (struct strbuf * sb , struct commit * commit )
608
+ {
609
+ struct pretty_print_context ctx = { 0 };
610
+
611
+ parse_commit (commit );
612
+ strbuf_addstr (sb , " - " );
613
+ pretty_print_commit (CMIT_FMT_ONELINE , commit , sb , & ctx );
614
+ strbuf_addch (sb , '\n' );
615
+ }
616
+
617
+ #define ORPHAN_CUTOFF 4
618
+ static void suggest_reattach (struct commit * commit , struct rev_info * revs )
619
+ {
620
+ struct commit * c , * last = NULL ;
621
+ struct strbuf sb = STRBUF_INIT ;
622
+ int lost = 0 ;
623
+ while ((c = get_revision (revs )) != NULL ) {
624
+ if (lost < ORPHAN_CUTOFF )
625
+ describe_one_orphan (& sb , c );
626
+ last = c ;
627
+ lost ++ ;
628
+ }
629
+ if (ORPHAN_CUTOFF < lost ) {
630
+ int more = lost - ORPHAN_CUTOFF ;
631
+ if (more == 1 )
632
+ describe_one_orphan (& sb , last );
633
+ else
634
+ strbuf_addf (& sb , " ... and %d more.\n" , more );
635
+ }
636
+
637
+ fprintf (stderr ,
638
+ "Warning: you are leaving %d commit%s behind, "
639
+ "not connected to\n"
640
+ "any of your branches:\n\n"
641
+ "%s\n"
642
+ "If you want to keep them by creating a new branch, "
643
+ "this may be a good time\nto do so with:\n\n"
644
+ " git branch new_branch_name %s\n\n" ,
645
+ lost , ((1 < lost ) ? "s" : "" ),
646
+ sb .buf ,
647
+ sha1_to_hex (commit -> object .sha1 ));
648
+ strbuf_release (& sb );
649
+ }
650
+
651
+ /*
652
+ * We are about to leave commit that was at the tip of a detached
653
+ * HEAD. If it is not reachable from any ref, this is the last chance
654
+ * for the user to do so without resorting to reflog.
655
+ */
656
+ static void orphaned_commit_warning (struct commit * commit )
657
+ {
658
+ struct rev_list_args args = { 0 , 0 , NULL };
659
+ struct rev_info revs ;
660
+
661
+ add_one_rev_list_arg (& args , "(internal)" );
662
+ add_one_rev_list_arg (& args , sha1_to_hex (commit -> object .sha1 ));
663
+ add_one_rev_list_arg (& args , "--not" );
664
+ for_each_ref (add_one_ref_to_rev_list_arg , & args );
665
+ add_one_rev_list_arg (& args , "--" );
666
+ add_one_rev_list_arg (& args , NULL );
667
+
668
+ init_revisions (& revs , NULL );
669
+ if (setup_revisions (args .argc - 1 , args .argv , & revs , NULL ) != 1 )
670
+ die ("internal error: only -- alone should have been left" );
671
+ if (prepare_revision_walk (& revs ))
672
+ die ("internal error in revision walk" );
673
+ if (!(commit -> object .flags & UNINTERESTING ))
674
+ suggest_reattach (commit , & revs );
675
+ else
676
+ describe_detached_head ("Previous HEAD position was" , commit );
677
+ }
678
+
585
679
static int switch_branches (struct checkout_opts * opts , struct branch_info * new )
586
680
{
587
681
int ret = 0 ;
@@ -609,13 +703,8 @@ static int switch_branches(struct checkout_opts *opts, struct branch_info *new)
609
703
if (ret )
610
704
return ret ;
611
705
612
- /*
613
- * If we were on a detached HEAD, but have now moved to
614
- * a new commit, we want to mention the old commit once more
615
- * to remind the user that it might be lost.
616
- */
617
706
if (!opts -> quiet && !old .path && old .commit && new -> commit != old .commit )
618
- describe_detached_head ( "Previous HEAD position was" , old .commit );
707
+ orphaned_commit_warning ( old .commit );
619
708
620
709
update_refs_for_switch (opts , & old , new );
621
710
0 commit comments