@@ -572,6 +572,40 @@ static int interactive_checkout(const char *revision, const char **pathspec,
572572 return run_add_interactive (revision , "--patch=checkout" , pathspec );
573573}
574574
575+ struct tracking_name_data {
576+ const char * name ;
577+ char * remote ;
578+ int unique ;
579+ };
580+
581+ static int check_tracking_name (const char * refname , const unsigned char * sha1 ,
582+ int flags , void * cb_data )
583+ {
584+ struct tracking_name_data * cb = cb_data ;
585+ const char * slash ;
586+
587+ if (prefixcmp (refname , "refs/remotes/" ))
588+ return 0 ;
589+ slash = strchr (refname + 13 , '/' );
590+ if (!slash || strcmp (slash + 1 , cb -> name ))
591+ return 0 ;
592+ if (cb -> remote ) {
593+ cb -> unique = 0 ;
594+ return 0 ;
595+ }
596+ cb -> remote = xstrdup (refname );
597+ return 0 ;
598+ }
599+
600+ static const char * unique_tracking_name (const char * name )
601+ {
602+ struct tracking_name_data cb_data = { name , NULL , 1 };
603+ for_each_ref (check_tracking_name , & cb_data );
604+ if (cb_data .unique )
605+ return cb_data .remote ;
606+ free (cb_data .remote );
607+ return NULL ;
608+ }
575609
576610int cmd_checkout (int argc , const char * * argv , const char * prefix )
577611{
@@ -630,8 +664,6 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
630664 opts .new_branch = argv0 + 1 ;
631665 }
632666
633- if (opts .track == BRANCH_TRACK_UNSPECIFIED )
634- opts .track = git_branch_track ;
635667 if (conflict_style ) {
636668 opts .merge = 1 ; /* implied */
637669 git_xmerge_config ("merge.conflictstyle" , conflict_style , NULL );
@@ -655,6 +687,11 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
655687 * With no paths, if <something> is a commit, that is to
656688 * switch to the branch or detach HEAD at it.
657689 *
690+ * With no paths, if <something> is _not_ a commit, no -t nor -b
691+ * was given, and there is a tracking branch whose name is
692+ * <something> in one and only one remote, then this is a short-hand
693+ * to fork local <something> from that remote tracking branch.
694+ *
658695 * Otherwise <something> shall not be ambiguous.
659696 * - If it's *only* a reference, treat it like case (1).
660697 * - If it's only a path, treat it like case (2).
@@ -677,7 +714,20 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
677714 if (get_sha1 (arg , rev )) {
678715 if (has_dash_dash ) /* case (1) */
679716 die ("invalid reference: %s" , arg );
680- goto no_reference ; /* case (3 -> 2) */
717+ if (!patch_mode &&
718+ opts .track == BRANCH_TRACK_UNSPECIFIED &&
719+ !opts .new_branch &&
720+ !check_filename (NULL , arg ) &&
721+ argc == 1 ) {
722+ const char * remote = unique_tracking_name (arg );
723+ if (!remote || get_sha1 (remote , rev ))
724+ goto no_reference ;
725+ opts .new_branch = arg ;
726+ arg = remote ;
727+ /* DWIMmed to create local branch */
728+ }
729+ else
730+ goto no_reference ;
681731 }
682732
683733 /* we can't end up being in (2) anymore, eat the argument */
@@ -715,6 +765,10 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
715765 }
716766
717767no_reference :
768+
769+ if (opts .track == BRANCH_TRACK_UNSPECIFIED )
770+ opts .track = git_branch_track ;
771+
718772 if (argc ) {
719773 const char * * pathspec = get_pathspec (prefix , argv );
720774
0 commit comments