diff --git a/pkg/config/errors.go b/pkg/config/errors.go
index 887c93676..f71b62387 100644
--- a/pkg/config/errors.go
+++ b/pkg/config/errors.go
@@ -67,7 +67,7 @@ type ErrMutuallyExclusiveCheckout struct {
 }
 
 func (e ErrMutuallyExclusiveCheckout) Error() string {
-	return "Checkout mutually exclusive, use either: commit-hash, branch or tag."
+	return "Checkout mutually exclusive, use either: commit-hash, branch, tag, or ref."
 }
 
 // ErrRepositoryNotFound is returned if repository is empty
diff --git a/pkg/config/options.go b/pkg/config/options.go
index a1368a960..8c5044e21 100644
--- a/pkg/config/options.go
+++ b/pkg/config/options.go
@@ -22,8 +22,6 @@ import (
 
 	"k8s.io/cli-runtime/pkg/printers"
 	"sigs.k8s.io/yaml"
-
-	"opendev.org/airship/airshipctl/pkg/errors"
 )
 
 // ContextOptions holds all configurable options for context
@@ -44,7 +42,6 @@ type ManifestOptions struct {
 	Branch       string
 	CommitHash   string
 	Tag          string
-	RemoteRef    string
 	Force        bool
 	IsPhase      bool
 	TargetPath   string
@@ -152,9 +149,6 @@ func (o *ManifestOptions) Validate() error {
 	if o.Name == "" {
 		return ErrMissingManifestName{}
 	}
-	if o.RemoteRef != "" {
-		return errors.ErrNotImplemented{What: "repository checkout by RemoteRef"}
-	}
 	if o.IsPhase && o.RepoName == "" {
 		return ErrMissingRepositoryName{}
 	}
diff --git a/pkg/config/repo.go b/pkg/config/repo.go
index 6cd0e9658..7d8ee6505 100644
--- a/pkg/config/repo.go
+++ b/pkg/config/repo.go
@@ -18,6 +18,7 @@ import (
 	"fmt"
 
 	"github.com/go-git/go-git/v5"
+	gitconfig "github.com/go-git/go-git/v5/config"
 	"github.com/go-git/go-git/v5/plumbing"
 	"github.com/go-git/go-git/v5/plumbing/transport"
 	"github.com/go-git/go-git/v5/plumbing/transport/http"
@@ -49,6 +50,8 @@ type Repository struct {
 	Auth *RepoAuth `json:"auth,omitempty"`
 	// CheckoutOptions holds options to checkout repository
 	CheckoutOptions *RepoCheckout `json:"checkout,omitempty"`
+	// FetchOptions holds options for fetching remote refs
+	FetchOptions *RepoFetch `json:"fetch,omitempty"`
 }
 
 // RepoAuth struct describes method of authentication against given repository
@@ -77,17 +80,27 @@ type RepoCheckout struct {
 	Branch string `json:"branch"`
 	// Tag is the tag name to checkout
 	Tag string `json:"tag"`
-	// RemoteRef is not supported currently TODO
-	// RemoteRef is used for remote checkouts such as gerrit change requests/github pull request
+	// Ref is the ref to checkout
 	// for example refs/changes/04/691202/5
-	// TODO Add support for fetching remote refs
-	RemoteRef string `json:"remoteRef,omitempty"`
+	Ref string `json:"ref,omitempty"`
 	// ForceCheckout is a boolean to indicate whether to use the `--force` option when checking out
 	ForceCheckout bool `json:"force"`
 	// LocalBranch is a boolean to indicate whether the Branch is local one. False by default
 	LocalBranch bool `json:"localBranch"`
 }
 
+// RepoFetch holds information on which remote ref to fetch
+type RepoFetch struct {
+	// RemoteRefSpec is used for remote fetches such as gerrit change
+	// requests and github pull requests. The format of the refspec is an
+	// optional +, followed by <src>:<dst>, where <src> is the pattern for
+	// references on the remote side and <dst> is where those references
+	// will be written locally. The + tells Git to update the reference
+	// even if it isn't a fast-forward.
+	// eg.: refs/changes/04/691202/5:refs/changes/04/691202/5
+	RemoteRefSpec string `json:"remoteRefSpec,omitempty"`
+}
+
 // RepoCheckout methods
 
 func (c *RepoCheckout) String() string {
@@ -102,7 +115,7 @@ func (c *RepoCheckout) String() string {
 // repository checkout and returns Error for incorrect values
 // returns nil when there are no errors
 func (c *RepoCheckout) Validate() error {
-	possibleValues := []string{c.CommitHash, c.Branch, c.Tag, c.RemoteRef}
+	possibleValues := []string{c.CommitHash, c.Branch, c.Tag, c.Ref}
 	var count int
 	for _, val := range possibleValues {
 		if val != "" {
@@ -112,8 +125,14 @@ func (c *RepoCheckout) Validate() error {
 	if count > 1 {
 		return ErrMutuallyExclusiveCheckout{}
 	}
-	if c.RemoteRef != "" {
-		return errors.ErrNotImplemented{What: "repository checkout by RemoteRef"}
+	return nil
+}
+
+// Validate verifies that the remote refspec is valid. If a remote refspec was
+// not supplied, Validate does nothing.
+func (rf *RepoFetch) Validate() error {
+	if rf.RemoteRefSpec != "" {
+		return gitconfig.RefSpec(rf.RemoteRefSpec).Validate()
 	}
 	return nil
 }
@@ -238,6 +257,8 @@ func (repo *Repository) ToCheckoutOptions() *git.CheckoutOptions {
 			co.Branch = plumbing.NewTagReferenceName(repo.CheckoutOptions.Tag)
 		case repo.CheckoutOptions.CommitHash != "":
 			co.Hash = plumbing.NewHash(repo.CheckoutOptions.CommitHash)
+		case repo.CheckoutOptions.Ref != "":
+			co.Branch = plumbing.ReferenceName(repo.CheckoutOptions.Ref)
 		}
 	}
 	return co
@@ -257,7 +278,14 @@ func (repo *Repository) ToCloneOptions(auth transport.AuthMethod) *git.CloneOpti
 // ToFetchOptions returns an instance of git.FetchOptions for given authentication
 // FetchOptions describes how a fetch should be performed
 func (repo *Repository) ToFetchOptions(auth transport.AuthMethod) *git.FetchOptions {
-	return &git.FetchOptions{Auth: auth}
+	var refSpecs []gitconfig.RefSpec
+	if repo.FetchOptions != nil && repo.FetchOptions.RemoteRefSpec != "" {
+		refSpecs = []gitconfig.RefSpec{gitconfig.RefSpec(repo.FetchOptions.RemoteRefSpec)}
+	}
+	return &git.FetchOptions{
+		Auth:     auth,
+		RefSpecs: refSpecs,
+	}
 }
 
 // URL returns the repository URL in a string format
diff --git a/pkg/document/pull/pull.go b/pkg/document/pull/pull.go
index 284aeba7c..fdda273c8 100644
--- a/pkg/document/pull/pull.go
+++ b/pkg/document/pull/pull.go
@@ -31,7 +31,6 @@ func Pull(cfgFactory config.Factory, noCheckout bool) error {
 }
 
 func cloneRepositories(cfg *config.Config, noCheckout bool) error {
-	// Clone main repository
 	currentManifest, err := cfg.CurrentContextManifest()
 	log.Debugf("Reading current context manifest information from %s", cfg.LoadedConfigPath())
 	if err != nil {
@@ -39,17 +38,17 @@ func cloneRepositories(cfg *config.Config, noCheckout bool) error {
 	}
 
 	// Clone repositories
-	for repoName, extraRepoConfig := range currentManifest.Repositories {
-		err := extraRepoConfig.Validate()
+	for repoName, repoConfig := range currentManifest.Repositories {
+		err := repoConfig.Validate()
 		if err != nil {
 			return err
 		}
-		repository, err := repo.NewRepository(currentManifest.GetTargetPath(), extraRepoConfig)
+		repository, err := repo.NewRepository(currentManifest.GetTargetPath(), repoConfig)
 		if err != nil {
 			return err
 		}
 		log.Printf("Downloading %s repository %s from %s into %s",
-			repoName, repository.Name, extraRepoConfig.URL(), currentManifest.GetTargetPath())
+			repoName, repository.Name, repoConfig.URL(), currentManifest.GetTargetPath())
 		err = repository.Download(noCheckout)
 		if err != nil {
 			return err
diff --git a/pkg/document/repo/repo.go b/pkg/document/repo/repo.go
index ef4a68a69..04431b9ba 100644
--- a/pkg/document/repo/repo.go
+++ b/pkg/document/repo/repo.go
@@ -115,6 +115,19 @@ func (repo *Repository) Checkout() error {
 	return tree.Checkout(co)
 }
 
+// Fetch fetches remote refs
+func (repo *Repository) Fetch() error {
+	if !repo.Driver.IsOpen() {
+		return ErrNoOpenRepo{}
+	}
+	auth, err := repo.ToAuth()
+	if err != nil {
+		return fmt.Errorf("failed to build auth options for repository %v: %w", repo.Name, err)
+	}
+	fo := repo.ToFetchOptions(auth)
+	return repo.Driver.Fetch(fo)
+}
+
 // Open the repository
 func (repo *Repository) Open() error {
 	log.Debugf("Attempting to open repository %s", repo.Name)
@@ -155,5 +168,11 @@ func (repo *Repository) Download(noCheckout bool) error {
 	if noCheckout {
 		return nil
 	}
+
+	err := repo.Fetch()
+	if err != nil && err != git.NoErrAlreadyUpToDate {
+		return fmt.Errorf("failed to fetch refs for repository %v: %w", repo.Name, err)
+	}
+
 	return repo.Checkout()
 }
diff --git a/pkg/document/repo/repo_test.go b/pkg/document/repo/repo_test.go
index 815cc87bd..0c4e4a62b 100644
--- a/pkg/document/repo/repo_test.go
+++ b/pkg/document/repo/repo_test.go
@@ -63,7 +63,8 @@ func TestDownload(t *testing.T) {
 		CloneOptions: &git.CloneOptions{
 			URL: fx.DotGit().Root(),
 		},
-		URLString: fx.DotGit().Root(),
+		FetchOptions: &git.FetchOptions{Auth: nil},
+		URLString:    fx.DotGit().Root(),
 	}
 
 	fs := memfs.New()