| 1 | --- |
| 2 | title: Forking a repository |
| 3 | description: Copy a repository into your own workspace, keep it up to date with the one it came from, and propose changes back. |
| 4 | --- |
| 5 | |
| 6 | Forking copies a repository into a workspace of yours as a new repository |
| 7 | that remembers where it came from: its **parent**. The fork is yours. You |
| 8 | can push to it, change its settings and run its workflows, and the parent |
| 9 | is untouched until you open a pull request into it and someone there merges |
| 10 | it. |
| 11 | |
| 12 | Fork a repository to contribute to one you cannot push to, or to start your |
| 13 | own line of work from someone else's code. To work on an issue in a |
| 14 | repository you can already write to, you do not need a fork: open a pull |
| 15 | request from a branch, or let it [make a working copy](/concepts/forks/#working-copies-for-pull-requests). |
| 16 | |
| 17 | See [Forks](/concepts/forks/) for what a fork is, who can see it and what |
| 18 | happens to it when its parent changes. |
| 19 | |
| 20 | ## Who can fork |
| 21 | |
| 22 | - **A public repository**: anyone signed in, into any workspace where they |
| 23 | can create a public repository. |
| 24 | - **A private repository**: anyone who can read it, once its admins allow |
| 25 | forking (see [Allow forking a private repository](#allow-forking-a-private-repository)), |
| 26 | into a workspace where they can create a private repository. |
| 27 | |
| 28 | Your email address must be confirmed. An access token made for a workflow |
| 29 | run or an agent's run cannot fork. |
| 30 | |
| 31 | ## Fork a repository |
| 32 | |
| 33 | 1. Open the repository and choose **Fork** in its header. |
| 34 | 2. Pick the **workspace** to fork it into. Only workspaces where you can |
| 35 | create a repository of its kind are listed. |
| 36 | 3. Keep its **name**, or give the fork another. Its project starts with |
| 37 | the parent project's **description**; change it later on the fork's |
| 38 | **Settings → General**. |
| 39 | 4. Leave **Copy the `<default>` branch only** on to copy just the default |
| 40 | branch, or turn it off to copy every branch and tag. |
| 41 | 5. Choose **Create fork**. |
| 42 | |
| 43 | You land on the fork. Under its name, its header says **forked from** and |
| 44 | links to the parent. |
| 45 | |
| 46 | From the CLI, `g1t repo fork` forks the current repository, or the one you |
| 47 | name, into your personal workspace unless you say `--workspace`. With |
| 48 | `--clone` it clones the fork and adds the parent as the remote `upstream`: |
| 49 | |
| 50 | ```sh |
| 51 | g1t repo fork acme/rocket --workspace ada-labs --clone |
| 52 | ``` |
| 53 | |
| 54 | From the API, call |
| 55 | [`POST /repos/{owner}/{name}/forks`](/reference/api/repositories/fork-repo/): |
| 56 | |
| 57 | ```sh |
| 58 | curl -X POST https://api.g1t.sh/repos/acme/rocket/forks \ |
| 59 | -H "Authorization: Bearer $G1T_TOKEN" \ |
| 60 | -H "Content-Type: application/json" \ |
| 61 | -d '{"workspace": "ada-labs", "default_branch_only": true}' |
| 62 | ``` |
| 63 | |
| 64 | `workspace`, `name` and `default_branch_only` may each be left out: your |
| 65 | personal workspace, the parent's name, and the default branch only. Over MCP, it is the `repository` tool's `fork` |
| 66 | action. |
| 67 | |
| 68 | ### What the fork gets |
| 69 | |
| 70 | | Copied | Not copied | |
| 71 | | --- | --- | |
| 72 | | The default branch, or every branch and tag | Issues, pull requests, comments and labels | |
| 73 | | Its project's description, to the fork's project | Settings, rulesets and branch protection | |
| 74 | | | Secrets, variables and webhooks | |
| 75 | | | Environments, projects, deployments and custom domains | |
| 76 | | | Releases, packages and stars | |
| 77 | |
| 78 | Issues are off in a new fork, and so are its workflows: a fork runs none of |
| 79 | the workflows it copied until someone turns them on (see |
| 80 | [Turn on workflows](#turn-on-workflows)). Deployments stay off until you set |
| 81 | up the fork's own project. |
| 82 | |
| 83 | ### When forking is refused |
| 84 | |
| 85 | | Response | Why | What to do | |
| 86 | | --- | --- | --- | |
| 87 | | `403 forbidden` | The repository is private and its admins have not allowed forking, or you cannot create a repository of its kind in the workspace. | Ask its admins to allow forking, or pick another workspace. | |
| 88 | | `409 conflict` | The workspace already has a repository with that name, or a recently deleted one holds it. | Give the fork another `name`. | |
| 89 | | `402 payment_required` | The fork is private, the workspace is on no plan, and its private repositories would hold more than a free workspace's 1 GB. | Start the g1t plan in the workspace, or fork into another. | |
| 90 | | `422 invalid` | The name is not valid, no workspace was named and you belong to several, or the repository is a pull request's working copy. | Name a workspace, or fork the repository the working copy belongs to. | |
| 91 | |
| 92 | ## Sync a fork |
| 93 | |
| 94 | A fork does not follow its parent by itself. Syncing brings one of its |
| 95 | branches up to date with the parent's branch of the same name; the fork's |
| 96 | default branch follows the parent's default branch, whatever each is |
| 97 | called. |
| 98 | |
| 99 | On the fork's **Code** page, a bar names the parent's branch the branch you |
| 100 | are looking at follows. Choose **Sync fork**, then **Update branch**; the |
| 101 | bar then says what happened. |
| 102 | |
| 103 | From the CLI, in a clone of the fork: |
| 104 | |
| 105 | ```sh |
| 106 | g1t repo sync # the default branch |
| 107 | g1t repo sync --branch release/2.x |
| 108 | ``` |
| 109 | |
| 110 | From the API, call |
| 111 | [`POST /repos/{owner}/{name}/merge-upstream`](/reference/api/repositories/sync-fork/) |
| 112 | on the fork, with `branch` or without it for the default branch: |
| 113 | |
| 114 | ```sh |
| 115 | curl -X POST https://api.g1t.sh/repos/ada-labs/rocket/merge-upstream \ |
| 116 | -H "Authorization: Bearer $G1T_TOKEN" \ |
| 117 | -H "Content-Type: application/json" \ |
| 118 | -d '{"branch": "main"}' |
| 119 | ``` |
| 120 | |
| 121 | Syncing needs the Write role on the fork and read access to its parent. What |
| 122 | happens depends on the branch: |
| 123 | |
| 124 | | `status` | The branch | What changed | |
| 125 | | --- | --- | --- | |
| 126 | | `up_to_date` | Already had every commit of the parent's branch. | Nothing. | |
| 127 | | `fast_forwarded` | Was only behind. | It now points where the parent's does. | |
| 128 | | `merged` | Had commits of its own, and the two sides' changes do not clash: different files, or different lines of the same file. | A merge commit joins them. | |
| 129 | | `conflicted` | Had commits of its own, and both sides changed the same lines (or one deleted a file the other changed, or both changed a binary file), in the files listed in `conflicts`. | Nothing. | |
| 130 | |
| 131 | The answer also says how many commits the branch was `behind` and `ahead`. |
| 132 | A conflicted branch is yours to merge: pull the parent's branch into your |
| 133 | clone, settle the conflicts and push. |
| 134 | |
| 135 | ```sh |
| 136 | git pull upstream main |
| 137 | git push origin main |
| 138 | ``` |
| 139 | |
| 140 | Syncing moves the branch on g1t. Pull it into your clone afterwards with |
| 141 | `git pull origin <branch>`. The fork's rules hold as for any push: a |
| 142 | protected branch is not moved by syncing. |
| 143 | |
| 144 | ## Propose changes to the parent |
| 145 | |
| 146 | Push a branch to your fork and open a pull request from it into the parent. |
| 147 | |
| 148 | 1. On the fork's **Code** page, choose **Contribute** on the bar that names |
| 149 | the parent's branch. |
| 150 | 2. The base is the parent's default branch; pick another of its branches if |
| 151 | you were asked to. |
| 152 | 3. Write a title and description and choose **Create pull request**. |
| 153 | |
| 154 | From the CLI, in a clone of the fork whose `upstream` is the parent, |
| 155 | `g1t pr create` opens the pull request on the parent and pushes the branch |
| 156 | to your fork (`origin`). `--head-repo OWNER/NAME` names the fork when the |
| 157 | remotes are set up differently. |
| 158 | |
| 159 | ```sh |
| 160 | git switch -c fix-link |
| 161 | git commit -am "Fix the broken link" |
| 162 | g1t pr create --fill |
| 163 | ``` |
| 164 | |
| 165 | From the API, create the pull request on the parent with the fork in |
| 166 | `head_repo` and its branch in `branch`: |
| 167 | |
| 168 | ```sh |
| 169 | curl -X POST https://api.g1t.sh/repos/acme/rocket/pulls \ |
| 170 | -H "Authorization: Bearer $G1T_TOKEN" \ |
| 171 | -H "Content-Type: application/json" \ |
| 172 | -d '{"head_repo": "ada-labs/rocket", "branch": "fix-link", "title": "Fix the broken link"}' |
| 173 | ``` |
| 174 | |
| 175 | The pull request lives on the parent and is reviewed, checked and merged |
| 176 | there, under the parent's rules. Its checks are the **parent's** workflows, |
| 177 | run under the parent's settings, and a pull request from someone outside |
| 178 | the parent's workspace waits for approval as the parent's |
| 179 | [approval policy](/guides/actions/#pull-requests-from-outside) says. |
| 180 | Whoever opened it, its runs get none of the parent's secrets and no token |
| 181 | that can write to the parent: anyone who can push to the fork can change the |
| 182 | code they run. Pushing to the branch in your fork updates the pull request. |
| 183 | |
| 184 | ## Allow forking a private repository |
| 185 | |
| 186 | A private repository cannot be forked until its admins allow it. |
| 187 | |
| 188 | 1. Open the repository's **Settings → Repository**. |
| 189 | 2. Under **Forking**, turn on **Allow forking**. |
| 190 | |
| 191 | From the API, send `allow_forking` to |
| 192 | [`PATCH /repos/{owner}/{name}`](/reference/api/repositories/update-repo/); |
| 193 | it needs the Admin role. Forks of a private repository are private, and stay |
| 194 | private. Clearing the setting stops new forks; forks already made stay, but |
| 195 | a private fork whose maker can no longer read the parent is deleted (and |
| 196 | can be restored for 30 days by its workspace's owners). |
| 197 | |
| 198 | Public repositories can always be forked. |
| 199 | |
| 200 | ## Turn on workflows |
| 201 | |
| 202 | A fork's workflows are off when it is made, so nothing it copied runs on |
| 203 | your account until you decide it should. In the fork's |
| 204 | **Settings → Actions**, turn on **Run workflows**. Only someone who manages |
| 205 | the fork's settings (the Admin role) can. See |
| 206 | [Turn workflows on or off](/guides/actions/#turn-workflows-on-or-off). |
| 207 | |
| 208 | ## List a repository's forks |
| 209 | |
| 210 | The repository's **Forks** page lists the forks you can see, newest first. |
| 211 | From the CLI, `g1t repo forks`; from the API, |
| 212 | [`GET /repos/{owner}/{name}/forks`](/reference/api/repositories/list-forks/). |
| 213 | |
| 214 | ## Detach a fork |
| 215 | |
| 216 | Detaching makes a fork an ordinary repository with no parent. Do it when the |
| 217 | fork has become its own project, or to change who can see it: a fork stays |
| 218 | exactly as visible as its parent until it is detached. |
| 219 | |
| 220 | 1. Open the fork's **Settings → Repository**. |
| 221 | 2. Under **Danger zone**, choose **Detach fork**, type the fork's full name |
| 222 | (`<workspace>/<name>`) to confirm, and choose **Detach fork**. |
| 223 | |
| 224 | From the CLI, `g1t repo detach`; from the API, |
| 225 | [`POST /repos/{owner}/{name}/detach`](/reference/api/repositories/detach-fork/). |
| 226 | It needs the Admin role on the fork. |
| 227 | |
| 228 | A detached fork keeps its code, settings and the pull requests it already |
| 229 | opened into the parent, which stay open there. It can no longer be synced or |
| 230 | open new pull requests into the parent, and its workflows and issues stay |
| 231 | off unless someone had turned them on. It cannot be attached again. |