# Document bootstrap and add backend test

`c535fc6`→[main](/content/gh/entireio/git-sync/commits/main/index.html)·

Soph·3mo ago·2 files·+59 added/-2 removed

## Sessions

f09ed59d22ebView transcript

## Changes

2

- MREADME.md+12/-2

- internal/syncer

- Mgit_http_backend_test.go+47

```text
11 unmodified lines

12
13
14
15
16
17
18
40 unmodified lines

59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
43 unmodified lines

117
118
119
110
120
121
122
123
1 unmodified line

125
126
127
118
128
129
130
131

11 unmodified lines
- `git-sync probe`: inspect a source remote, and optionally a target remote
- `git-sync fetch`: exercise source-side fetch negotiation without pushing
- `git-sync bootstrap`: seed an empty target with create-only relay behavior
- `git-sync plan`: compute source-to-target ref actions without pushing
- `git-sync sync`: execute the planned changes against the target

40 unmodified lines

https://github.com/target-org/target-repo.git
```

Bootstrap an empty target without using the normal local object-store sync path:

```bash
go run ./cmd/git-sync bootstrap \
  --stats \
  https://github.com/source-org/source-repo.git \
  https://github.com/target-org/target-repo.git
```

Sync specific branches:

```text
43 unmodified lines
  <source-url>
```

Add `--json` to `probe`, `fetch`, `plan`, or `sync` to emit machine-readable output instead of the default text format.
Add `--json` to `probe`, `fetch`, `bootstrap`, `plan`, or `sync` to emit machine-readable output instead of the default text format.

The JSON interface is intentionally stable:

1 unmodified line

- refs and hashes are serialized as strings, not raw byte arrays
- `probe` returns top-level keys such as `source_url`, `target_url`, `protocol`, `ref_prefixes`, `source_capabilities`, `target_capabilities`, `refs`, and `stats`
- `fetch` returns top-level keys such as `source_url`, `protocol`, `wants`, `haves`, `fetched_objects`, and `stats`
- `plan` and `sync` return top-level keys such as `plans`, `pushed`, `skipped`, `blocked`, `deleted`, `dry_run`, `protocol`, and `stats`
- `bootstrap`, `plan`, and `sync` return top-level keys such as `plans`, `pushed`, `skipped`, `blocked`, `deleted`, `dry_run`, `protocol`, and `stats`
- each item in `plans` includes stable string fields such as `branch`, `source_ref`, `target_ref`, `source_hash`, `target_hash`, `kind`, `action`, and `reason`

Probe both source and target remotes to inspect source fetch capabilities and target `receive-pack` capabilities:

```text
MREADME.md+12/-2
```

```go
assertGitRefEqual(t, sourceBare, targetBare, plumbing.NewBranchReferenceName(testBranch))

func TestBootstrap_GitHTTPBackendSync(t *testing.T) {
	if os.Getenv(gitHTTPBackendEnv) == "" {
		t.Skip("set GITSYNC_E2E_GIT_HTTP_BACKEND=1 to run git-http-backend integration test")
	}

if _, err := exec.LookPath("git"); err != nil {
		t.Skipf("git not available: %v", err)
	}

root := t.TempDir()
	sourceBare := filepath.Join(root, "source.git")
	targetBare := filepath.Join(root, "target.git")
	worktree := filepath.Join(root, "work")

runGit(t, root, "init", "--bare", sourceBare)
	runGit(t, root, "init", "--bare", targetBare)
	runGit(t, targetBare, "config", "http.receivepack", "true")
	runGit(t, root, "init", "-b", testBranch, worktree)
	runGit(t, worktree, "config", "user.name", "git-sync test")
	runGit(t, worktree, "config", "user.email", "git-sync@example.com")

writeFile(t, filepath.Join(worktree, "README.md"), "bootstrap\n")
	runGit(t, worktree, "add", "README.md")
	runGit(t, worktree, "commit", "-m", "initial")
	runGit(t, worktree, "remote", "add", "origin", sourceBare)
	runGit(t, worktree, "push", "origin", "HEAD:refs/heads/"+testBranch)

server := newGitHTTPBackendServer(t, root)
	defer server.Close()

sourceURL := server.RepoURL("source.git")
	targetURL := server.RepoURL("target.git")

result, err := Bootstrap(context.Background(), Config{
		Source: Endpoint{URL: sourceURL},
		Target: Endpoint{URL: targetURL},
	})
	if err != nil {
		t.Fatalf("bootstrap sync failed: %v", err)
	}
	if result.Pushed != 1 || result.Blocked != 0 {
		t.Fatalf("unexpected bootstrap result: %+v", result)
	}

assertGitRefEqual(t, sourceBare, targetBare, plumbing.NewBranchReferenceName(testBranch))
}

type gitHTTPBackendServer struct {
	server *httptest.Server
	root   string
}
```
