Skip to content

g1t/apps/docs/src/content/docs/guides/git.md

241 lines9,945 bytesCodeBlame
1---
2title: Git
3description: Remotes, credentials, private repositories and limits.
4---
5
6g1t speaks git's smart HTTP protocol. Any git client works.
7
8## Remotes
9
10```text
11https://g1t.sh/<workspace>/<repo>.git
12```
13
14Public repositories can be cloned without signing in:
15
16```sh
17git clone https://g1t.sh/flagon-io/g1t.git
18```
19
20If the workspace is [renamed](/guides/workspaces/#rename-a-workspace), the
21old remote redirects to the new one for 90 days. Git follows the redirect
22and warns about it; point the remote at the new address:
23
24```sh
25git remote set-url origin https://g1t.sh/<new-workspace>/<repo>.git
26```
27
28## Authentication
29
30Pushing, and reading private repositories, needs credentials. Use your
31username, and as the password either your account password or an
32[access token](https://g1t.sh/settings/tokens). Tokens are recommended: they can be revoked
33individually and they also work for the API.
34
35To avoid typing it each time, let git store it:
36
37```sh
38git config --global credential.helper store
39```
40
41## Creating a repository by pushing
42
43Pushing to a repository that does not exist, in a workspace you belong to,
44creates it as a private repository, so nothing pushed by mistake is
45published. To make it public, see
46[change who can see a repository](/guides/managing-repositories/#change-who-can-see-a-repository).
47
48```sh
49git push https://g1t.sh/<workspace>/new-repo.git main
50```
51
52## Private repositories
53
54A private repository is visible only to people with a
55[role](/guides/access-and-roles/) on it. Cloning and fetching need
56Read, and pushing needs Write. To
57everyone else it looks exactly like a repository that does not exist, both
58on the site and to git.
59
60On the site, an address you cannot see gives the same page either way, with
61status 404:
62
63| You are | The page says |
64| --- | --- |
65| Signed out | **Nothing here**: this page doesn't exist, or it's private; sign in if it's yours. **Sign in** brings you back to the same address. |
66| Signed in | **Nothing here**: this page doesn't exist, or you don't have access to it, with which account you are signed in as and a link to switch account. If you should have access, ask someone with the Admin role on it to add you. |
67
68Issues, pull requests and workspace pages work the same way. The sidebar
69does not open the project or workspace the address names, so nothing on
70the page hints at whether it exists; a missing file, commit or issue in a
71project you can see keeps that project's sidebar. A profile that does not
72exist says **No one on g1t goes by that name**, since profiles are public.
73
74## Download a ZIP
75
76On a repository's **Files** page, **Code** → **Download ZIP** downloads the
77branch shown as one zip, its files in a folder named `<repo>-<branch>`. It
78works for anyone who can see the repository, and for any branch, tag or
79commit at `g1t.sh/<workspace>/<repo>/archive/<ref>.zip`. A ZIP holds the
80files, not the history; clone for that. A repository with more than 10,000
81files or over 24 MB is too large to download this way, so clone it instead.
82
83## Browsing without an account
84
85Public projects, Explore, Search and profiles are open to everyone, in the
86same sidebar members use. Signed out, the sidebar has Explore and Search,
87and in a project its Code, Issues, Pull requests, Agents, Workflows and
88Deployments; pages only people with a role on the repository see, such as
89Security and Settings, are left out. **Sign in** and **Sign up** sit at the bottom, and both bring you
90back to the page you were on.
91
92## Protected branches
93
94A repository can protect its default branch under **Settings → Branches and
95merging**. Pushing to it is then refused for everyone, whatever their role, and for agents, and
96git says why:
97
98```text
99 ! [remote rejected] main -> main (main is protected: push a branch and open a pull request)
100```
101
102Changes reach a protected branch only by merging a pull request. The first
103push to an empty repository is still allowed.
104
105The same page sets what a merge needs: the
106[required status checks](/guides/pull-requests/#required-status-checks)
107and approvals.
108
109## Branches
110
111Push any branch to a repository you can write to, and open a
112[pull request](/concepts/overview/#pull-requests) from it on the
113repository's **Pull requests** tab.
114
115```sh
116git switch -c my-change
117git push origin my-change
118```
119
120A repository's **Branches** tab, `g1t.sh/<workspace>/<repo>/branches`, lists
121every branch: the default one first, then those with a commit in the last 90
122days (**Active**), then the rest (**Stale**). Each shows its last commit, how
123many commits it is ahead of and behind the default branch, the pull request
124open on it with its checks, and its preview when it has one. A count with a
125`+` ran past how far back g1t reads, 40 commits on the branch and 120 on the
126default. Search narrows the list by name.
127
128The **Tags** tab lists tags newest first, up to 100, each with its commit
129and a ZIP of its files.
130
131On **Files**, each file and folder shows the commit that last changed it and
132when, from up to 300 commits of the branch's history; one changed before
133that shows none. The branch menu at the top switches branch and keeps the
134folder or file you are on.
135
136## Pull request forks
137
138A pull request that was not opened from a branch has its own remote:
139
140```text
141https://g1t.sh/pulls/<pull request id>.git
142```
143
144Only whoever opened the pull request can push to it, or, for one g1t
145made, whoever asked for it. Pushes to a fork
146update the pull request's head commit on its page.
147
148## Limits
149
150### Size limits
151
152Repositories are stored in Cloudflare Artifacts. g1t checks its limits
153before a push is stored, and declines a push that would cross one. git
154prints the reason beside each branch (`! [remote rejected] main (…)`), and
155what to do as `remote:` lines. Nothing in a declined push is stored.
156
157| Limit | Size | What happens past it |
158| --- | --- | --- |
159| A file | 32 MB | The push is declined, naming the file's size. |
160| A repository, with its pull requests' forks | 950 MB, as g1t counts what was pushed (the store holds 1 GB) | The push is declined; once full, pushes are refused with the reason before any data is sent. |
161| A push that push protection can scan before it lands | Most pushes; very large ones are scanned after they land | A very large push goes through and is scanned after it lands; secrets found are open alerts. To have it checked first, push in parts, oldest commits first. |
162| A push | 100 MB | Refused by the network with HTTP `413` before g1t sees it. |
163
164To push a large history in parts:
165
166```sh
167git rev-list --reverse HEAD | awk 'NR % 500 == 0' | xargs -I{} git push origin {}:refs/heads/main
168git push origin main
169```
170
171Each push sends only what the one before did not.
172
173### When the store is busy
174
175If Cloudflare Artifacts is rate limiting g1t or not answering, g1t tries
176reads again for a moment, then answers git with HTTP `429` (rate limited)
177or `503` (unavailable) and a `Retry-After` header saying how many seconds
178to wait. Pushes are never tried again on your behalf: run `git push`
179again. On g1t.sh the page says the git storage is busy instead of failing,
180and [status.g1t.sh](https://status.g1t.sh) shows **Git storage**.
181
182### Git operations
183
184Each clone, fetch and push is a git operation. Every workspace has 50,000
185a month included. Past that, a workspace on the g1t plan pays $0.18 per
1861,000, and a free workspace is never charged: past 50,000 in a month, its
187git requests past 60 in an hour are answered `429` with when to try again,
188until the month turns. Counting starts on 2026-10-14. See
189[git operations](/guides/usage-and-billing/#git-operations).
190
191What these limits mean in practice, and what to do instead, is on
192[What g1t can't do yet](/about/limitations/#git).
193
194## Where a slow request's time went
195
196Every answer g1t gives git carries a `Server-Timing` header: how many
197milliseconds each step of the request took. To see it, run git with its
198HTTP trace on:
199
200```sh
201GIT_TRACE_CURL=1 git ls-remote https://g1t.sh/<owner>/<repo>.git 2>&1 | grep -i server-timing
202```
203
204| Step | What it is |
205| --- | --- |
206| `repo` | Finding the repository, and checking your credentials if you sent any |
207| `moved` | Only for an address with no repository: looking for a renamed workspace or a transferred repository to send you to |
208| `access` | Deciding whether you may fetch from or push to it |
209| `kept` | A free workspace's limits, and looking for a ref listing and a store credential made a moment ago |
210| `mint` | Only when no credential was kept: the git store making one for the request |
211| `store` | The git store's answer; for a push, checking it for secrets first |
212| `refs` | Only for a push: recording that the repository's refs changed |
213| `total` | Everything g1t did |
214| `repos` | The same, measured where your request arrived |
215
216Two entries say how a step went rather than how long it took:
217
218| Entry | Values |
219| --- | --- |
220| `refs;desc=` | `hit-colo` or `hit-shared` when the ref listing came from g1t's cache, `miss` when the git store was asked |
221| `cred;desc=` | `isolate` or `shared` for a store credential made a moment ago, `mint` for a new one |
222
223The ref listing git asks for first on every clone and fetch is kept for up
224to a minute, and only the same question about the same refs gets the same
225answer: a push, a merge or any other change to a repository's branches and
226tags makes the next fetch ask the git store again. A change can take up to
2275 seconds to reach every fetch.
228
229Include the header when you report a slow clone, fetch or push.
230
231## SSH
232
233Git over SSH is not available yet. Use HTTPS, which works for clone,
234fetch and push everywhere SSH would.
235
236Why: git over SSH needs raw TCP connections on port 22, and g1t runs
237entirely on Cloudflare's network. Accepting inbound TCP traffic directly
238into Workers is in a beta from Cloudflare that g1t has applied for and is
239waiting on. SSH keys can already be added under
240[Settings → SSH keys](https://g1t.sh/settings/keys),
241and will be used once SSH is on.