@@ -518,15 +518,56 @@ func (r RemoteTrackingRef) String() string {
518518
519519// ParseRemoteTrackingRef parses a string of the form "refs/remotes/<remote>/<branch>" into
520520// a RemoteTrackingBranch struct. If the string does not match this format, an error is returned.
521+ //
522+ // For now, we assume that refnames are of the format "<remote>/<branch>", where
523+ // the remote is a single path component, and branch may have many path components e.g.
524+ // "origin/my/branch" is valid as: {Remote: "origin", Branch: "my/branch"}
525+ // but "my/origin/branch" would parse incorrectly as: {Remote: "my", Branch: "origin/branch"}
526+ // I don't believe there is a way to fix this without providing the list of remotes to this function.
527+ //
528+ // It becomes particularly confusing if you have something like:
529+ //
530+ // ```
531+ // [remote "foo"]
532+ // url = https://github.com/williammartin/test-repo.git
533+ // fetch = +refs/heads/*:refs/remotes/foo/*
534+ // [remote "foo/bar"]
535+ // url = https://github.com/williammartin/test-repo.git
536+ // fetch = +refs/heads/*:refs/remotes/foo/bar/*
537+ // [branch "bar/baz"]
538+ // remote = foo
539+ // merge = refs/heads/bar/baz
540+ // [branch "baz"]
541+ // remote = foo/bar
542+ // merge = refs/heads/baz
543+ // ```
544+ //
545+ // These @{push} refs would resolve identically:
546+ //
547+ // ```
548+ // ➜ git rev-parse --symbolic-full-name baz@{push}
549+ // refs/remotes/foo/bar/baz
550+
551+ // ➜ git rev-parse --symbolic-full-name bar/baz@{push}
552+ // refs/remotes/foo/bar/baz
553+ // ```
554+ //
555+ // When using this ref, git assumes it means `remote: foo` `branch: bar/baz`.
521556func ParseRemoteTrackingRef (s string ) (RemoteTrackingRef , error ) {
522- parts := strings .Split (s , "/" )
523- if len (parts ) != 4 || parts [0 ] != "refs" || parts [1 ] != "remotes" {
557+ prefix := "refs/remotes/"
558+ if ! strings .HasPrefix (s , prefix ) {
559+ return RemoteTrackingRef {}, fmt .Errorf ("remote tracking branch must have format refs/remotes/<remote>/<branch> but was: %s" , s )
560+ }
561+
562+ refName := strings .TrimPrefix (s , prefix )
563+ refNameParts := strings .SplitN (refName , "/" , 2 )
564+ if len (refNameParts ) != 2 {
524565 return RemoteTrackingRef {}, fmt .Errorf ("remote tracking branch must have format refs/remotes/<remote>/<branch> but was: %s" , s )
525566 }
526567
527568 return RemoteTrackingRef {
528- Remote : parts [ 2 ],
529- Branch : parts [ 3 ],
569+ Remote : refNameParts [ 0 ],
570+ Branch : refNameParts [ 1 ],
530571 }, nil
531572}
532573
0 commit comments