diff --git a/cmd/flux/create_source_git_test.go b/cmd/flux/create_source_git_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..5558ff1faa1388162fa86c8e07ef92f7ffdcdcd2
--- /dev/null
+++ b/cmd/flux/create_source_git_test.go
@@ -0,0 +1,131 @@
+// +build unit
+
+package main
+
+import (
+	"context"
+	"github.com/fluxcd/pkg/apis/meta"
+	sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
+	"k8s.io/apimachinery/pkg/api/errors"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/types"
+	"k8s.io/apimachinery/pkg/util/wait"
+	"sigs.k8s.io/controller-runtime/pkg/client"
+	"testing"
+	"time"
+)
+
+var pollInterval = 50 * time.Millisecond
+var testTimeout = 10 * time.Second
+
+// Update the GitRepository once created to exercise test specific behavior
+type reconcileFunc func(repo *sourcev1.GitRepository)
+
+// reconciler waits for an object to be created, then invokes a test supplied
+// function to mutate that object, simulating a controller.
+// Test should invoke run() to run the background reconciler task which
+// polls to wait for the object to exist before applying the update function.
+// Any errors from the reconciler are asserted on test completion.
+type reconciler struct {
+	client    client.Client
+	name      types.NamespacedName
+	reconcile reconcileFunc
+}
+
+// Start the background task that waits for the object to exist then applies
+// the update function.
+func (r *reconciler) run(t *testing.T) {
+	result := make(chan error)
+	go func() {
+		defer close(result)
+		err := wait.PollImmediate(
+			pollInterval,
+			testTimeout,
+			r.conditionFunc)
+		result <- err
+	}()
+	t.Cleanup(func() {
+		if err := <-result; err != nil {
+			t.Errorf("Failure from test reconciler: '%v':", err.Error())
+		}
+	})
+}
+
+// A ConditionFunction that waits for the named GitRepository to be created,
+// then sets the ready condition to true.
+func (r *reconciler) conditionFunc() (bool, error) {
+	var repo sourcev1.GitRepository
+	if err := r.client.Get(context.Background(), r.name, &repo); err != nil {
+		if errors.IsNotFound(err) {
+			return false, nil // Keep polling until object is created
+		}
+		return true, err
+	}
+	r.reconcile(&repo)
+	err := r.client.Status().Update(context.Background(), &repo)
+	return true, err
+}
+
+func TestCreateSourceGit(t *testing.T) {
+	// Default command used for multiple tests
+	var command = "create source git podinfo --url=https://github.com/stefanprodan/podinfo --branch=master --timeout=" + testTimeout.String()
+
+	cases := []struct {
+		name      string
+		args      string
+		assert    assertFunc
+		reconcile reconcileFunc
+	}{
+		{
+			"NoArgs",
+			"create source git",
+			assertError("GitRepository source name is required"),
+			nil,
+		}, {
+			"Succeeded",
+			command,
+			assertGoldenFile("testdata/create_source_git/success.golden"),
+			func(repo *sourcev1.GitRepository) {
+				meta.SetResourceCondition(repo, meta.ReadyCondition, metav1.ConditionTrue, sourcev1.GitOperationSucceedReason, "succeeded message")
+				repo.Status.Artifact = &sourcev1.Artifact{
+					Path:     "some-path",
+					Revision: "v1",
+				}
+			},
+		}, {
+			"Failed",
+			command,
+			assertError("failed message"),
+			func(repo *sourcev1.GitRepository) {
+				meta.SetResourceCondition(repo, meta.ReadyCondition, metav1.ConditionFalse, sourcev1.URLInvalidReason, "failed message")
+			},
+		}, {
+			"NoArtifact",
+			command,
+			assertError("GitRepository source reconciliation completed but no artifact was found"),
+			func(repo *sourcev1.GitRepository) {
+				// Updated with no artifact
+				meta.SetResourceCondition(repo, meta.ReadyCondition, metav1.ConditionTrue, sourcev1.GitOperationSucceedReason, "succeeded message")
+			},
+		},
+	}
+	for _, tc := range cases {
+		t.Run(tc.name, func(t *testing.T) {
+			ns := allocateNamespace("podinfo")
+			setupTestNamespace(ns, t)
+			if tc.reconcile != nil {
+				r := reconciler{
+					client:    testEnv.client,
+					name:      types.NamespacedName{Namespace: ns, Name: "podinfo"},
+					reconcile: tc.reconcile,
+				}
+				r.run(t)
+			}
+			cmd := cmdTestCase{
+				args:   tc.args + " -n=" + ns,
+				assert: tc.assert,
+			}
+			cmd.runTestCmd(t)
+		})
+	}
+}
diff --git a/cmd/flux/main_test.go b/cmd/flux/main_test.go
index 570e0302e4ba57e7ef2fcf0afc5caa05b7058264..f8e13165e33efa5c9f1889fd0a23c2b1b3bb55be 100644
--- a/cmd/flux/main_test.go
+++ b/cmd/flux/main_test.go
@@ -14,6 +14,7 @@ import (
 	"text/template"
 	"time"
 
+	"github.com/fluxcd/flux2/internal/utils"
 	"github.com/google/go-cmp/cmp"
 	"github.com/mattn/go-shellwords"
 	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
@@ -132,7 +133,9 @@ func NewTestEnvKubeManager(testClusterMode TestClusterMode) (*testEnvKubeManager
 
 		tmpFilename := filepath.Join("/tmp", "kubeconfig-"+time.Nanosecond.String())
 		os.WriteFile(tmpFilename, kubeConfig, 0644)
-		k8sClient, err := client.NewWithWatch(cfg, client.Options{})
+		k8sClient, err := client.NewWithWatch(cfg, client.Options{
+			Scheme: utils.NewScheme(),
+		})
 		if err != nil {
 			return nil, err
 		}
@@ -158,7 +161,9 @@ func NewTestEnvKubeManager(testClusterMode TestClusterMode) (*testEnvKubeManager
 		if err != nil {
 			return nil, err
 		}
-		k8sClient, err := client.NewWithWatch(cfg, client.Options{})
+		k8sClient, err := client.NewWithWatch(cfg, client.Options{
+			Scheme: utils.NewScheme(),
+		})
 		if err != nil {
 			return nil, err
 		}
diff --git a/cmd/flux/main_unit_test.go b/cmd/flux/main_unit_test.go
index a26a928ce9c23deb915375db7270e74c00babb71..31de6b24f8bd1a6c1f974c9ff5517672a3a4c7dd 100644
--- a/cmd/flux/main_unit_test.go
+++ b/cmd/flux/main_unit_test.go
@@ -3,7 +3,10 @@
 package main
 
 import (
+	"context"
 	"fmt"
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"os"
 	"testing"
 )
@@ -32,3 +35,14 @@ func TestMain(m *testing.M) {
 
 	os.Exit(code)
 }
+
+func setupTestNamespace(namespace string, t *testing.T) {
+	ns := &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: namespace}}
+	err := testEnv.client.Create(context.Background(), ns)
+	if err != nil {
+		t.Fatalf("Failed to create namespace: %v", err)
+	}
+	t.Cleanup(func() {
+		_ = testEnv.client.Delete(context.Background(), ns)
+	})
+}
diff --git a/cmd/flux/testdata/create_source_git/success.golden b/cmd/flux/testdata/create_source_git/success.golden
new file mode 100644
index 0000000000000000000000000000000000000000..374924960c964151475f3ee5a96353b8d5c2b95f
--- /dev/null
+++ b/cmd/flux/testdata/create_source_git/success.golden
@@ -0,0 +1,6 @@
+✚ generating GitRepository source
+► applying GitRepository source
+✔ GitRepository source created
+◎ waiting for GitRepository source reconciliation
+✔ GitRepository source reconciliation completed
+✔ fetched revision: v1