Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ Each display name is scoped to a single {% data variables.product.prodname_githu

Choose a name that will avoid conflicts and will help users identify custom properties from the external system. If you're publishing an app on behalf of a third-party system, you may want to respond to conflicts or allow users to choose their own display name as part of the setup flow on your system.

The display name must between 1 and 15 characters and contain only letters and numbers. For all requirements, see the [Register an app installation for external properties](/rest/orgs/custom-properties#register-an-app-installation-for-external-custom-properties) endpoint of the REST API.
The display name must be between 1 and 15 characters and contain only letters and numbers. For all requirements, see the [Register an app installation for external properties](/rest/orgs/custom-properties#register-an-app-installation-for-external-custom-properties) endpoint of the REST API.

## 2. Register a {% data variables.product.prodname_github_app %}

Expand Down Expand Up @@ -83,14 +83,21 @@ The automation can run on a schedule or listen for events. The webhook you selec

In the automation, the {% data variables.product.prodname_github_app %} must obtain an installation access token and use the token to send data from the external system to {% data variables.product.github %}'s external properties API endpoints. See [AUTOTITLE](/apps/creating-github-apps/authenticating-with-a-github-app/authenticating-as-a-github-app-installation).

See the following endpoints of the REST API. You will find information on request size limits and error codes that your automation should account for.
A typical flow would be to:

* [Register an app installation for external custom properties](/rest/orgs/custom-properties#register-an-app-installation-for-external-custom-properties) (the app must register its display name before it can update properties, unless an organization administrator is expected to do this)
* [Get registered app installations for external custom properties](/rest/orgs/custom-properties#get-registered-app-installations-for-external-custom-properties)
* [Get all external custom properties for a {% data variables.product.prodname_github_app %} installation in an organization](/rest/orgs/custom-properties#get-all-external-custom-properties-for-a-github-app-installation-in-an-organization)
* [Create or update external custom property values for organization repositories](/rest/orgs/custom-properties#create-or-update-external-custom-property-values-for-organization-repositories)
* [Create or update external custom property values for a property across organization repositories](/rest/orgs/custom-properties#create-or-update-external-custom-property-values-for-a-property-across-organization-repositories)
* [Remove all external custom property values for a property across all organization repositories](/rest/orgs/custom-properties#remove-all-external-custom-property-values-for-a-property-across-all-organization-repositories)
1. **Register the app installation** with a display name before updating properties, unless an organization administrator will register it. See [Register an app installation for external custom properties](/rest/orgs/custom-properties#register-an-app-installation-for-external-custom-properties).
1. **Create or update property values for one or more repositories**. See:

* [Create or update external custom property values for organization repositories](/rest/orgs/custom-properties#create-or-update-external-custom-property-values-for-organization-repositories)
* [Create or update external custom property values for a property across organization repositories](/rest/orgs/custom-properties#create-or-update-external-custom-property-values-for-a-property-across-organization-repositories)

You might also need to:

* **Remove all values for one property across all organization repositories**. See [Remove all external custom property values for a property across all organization repositories](/rest/orgs/custom-properties#remove-all-external-custom-property-values-for-a-property-across-all-organization-repositories).
* **Get the external custom properties for the app installation** to verify the property definitions. See [Get all external custom properties for a {% data variables.product.prodname_github_app %} installation in an organization](/rest/orgs/custom-properties#get-all-external-custom-properties-for-a-github-app-installation-in-an-organization).
* **Get the registered app installations** to verify registration details. See [Get registered app installations for external custom properties](/rest/orgs/custom-properties#get-registered-app-installations-for-external-custom-properties).

Check the linked REST API references for request size limits and error codes that your automation needs to handle.

## 4. Install the app

Expand Down
39 changes: 38 additions & 1 deletion content/pull-requests/reference/stacked-prs-cli-commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ The `gh stack` extension for {% data variables.product.prodname_cli %} creates a
gh extension install github/gh-stack
```

The extension requires {% data variables.product.prodname_cli %} (`gh`) version 2.0 or later.
The extension requires {% data variables.product.prodname_cli %} (`gh`) version 2.0 or later, and Git 2.36 or later.

> [!NOTE]
> The `gh stack` extension uses your {% data variables.product.prodname_cli %} authentication. If you have not authenticated yet, run `gh auth login`.
Expand Down Expand Up @@ -63,6 +63,8 @@ Initializes a new stack locally. In interactive mode (no arguments), the command

When you provide explicit branch names, existing branches are adopted automatically and any missing branches are created. The trunk defaults to the repository's default branch unless you override it with `--base`.

Branches checked out in other worktrees can be adopted. If the final branch is already checked out elsewhere, `init` leaves your current checkout unchanged and reports the owning worktree instead.

The command enables `git rerere` automatically, so that conflict resolutions are remembered across rebases.

| Flag | Description |
Expand Down Expand Up @@ -95,6 +97,8 @@ gh stack add [flags] [branch]

For an existing stack, creates a new branch at the current HEAD, adds it to the top of the stack, and checks it out. You must run this command while on the topmost branch of a stack. If you do not provide a branch name, the command prompts for one.

If the branch name you provide is already checked out in another worktree, `add` adopts the existing branch without switching either checkout. The commit and stage shortcuts `-m`, `-A`, and `-u` are incompatible with that kind of adoption, and the command fails before staging anything or changing stack membership.

When you run the command interactively from a branch that is not part of a stack, `add` offers to initialize a new stack instead. The branch name you supply, or the auto-generated name, becomes the first layer. If you don't supply a name, the standard `init` prompts are used.

You can optionally stage changes and create a commit as part of the `add` flow. When you provide `-m` without an explicit branch name, the branch name is generated automatically in date and slug format, such as `03-24-add_login`.
Expand Down Expand Up @@ -166,6 +170,12 @@ Check out a stack by its stack number, a pull request number, a pull request URL
gh stack checkout [<stack-number> | <pr-number> | <pr-url> | <branch>]
```

| Flag | Description |
|------|-------------|
| `--print-path` | Print the target worktree's absolute path. Requires an explicit target and never prompts. |

For a target that is checked out in another worktree, `--print-path` prints that worktree's path without changing either checkout. For a target that is not checked out anywhere, the command checks out the branch in the current worktree before printing its path. Without the flag, trying to check out a target that's occupied elsewhere is an error that includes a path diagnostic, rather than a successful switch. See [Navigation](#navigation) for details on the output contract.

A bare number is interpreted first as a stack or pull request number. These are repository-scoped identifiers shown in the {% data variables.product.github %} UI. If nothing matches the number, it is tried as a branch name.

When you reference a remote stack, the command fetches the stack on {% data variables.product.github %}, pulls the branches, and sets up the stack locally. If the stack already exists locally and matches, the command switches to the branch. If the local and remote stacks have different compositions, you are prompted to resolve the conflict.
Expand Down Expand Up @@ -217,6 +227,9 @@ The command checks these conditions before opening the interface:
1. No rebase is in progress.
1. No pull request in the stack is queued for merge.
1. Commit history must be linear, with no merge commits and no diverged branches.
1. Every worktree needed by the staged actions, and by the branches that survive the cascade, must be clean and free of other Git operations.

Stack branches can be distributed across worktrees. Renames run in the branch's own worktree. Fold-down cherry-picks run in the receiving branch's worktree. Cascading rebases run each branch in its own worktree. A branch that isn't checked out anywhere uses the worktree you ran `modify` from, and inserted branches are created as refs without new worktrees. Dropped and folded branches, and their worktrees, are preserved. The trunk branch is only read, so unrelated or untouched source worktrees don't need to be clean.

**Operations**

Expand All @@ -241,6 +254,10 @@ If a rebase conflict occurs, you can either:
* Resolve the conflicts, stage the files, then run `gh stack modify --continue`.
* Run `gh stack modify --abort` to abort the operation and restore the stack to its previous state.

Resolve and stage conflicts in the worktree named in the conflict message, which may be a foreign fold receiver's worktree or a rebase owner's worktree rather than the one you ran `modify` from. Both `--continue` and `--abort` can be run from any linked worktree, because they use the recorded owner rather than your current checkout. Continuing resumes any remaining structural actions as well as remaining rebases. Aborting reverses renames in their own worktrees, restores only the refs that the operation touched, and deletes only the refs it created. If a restore or a journal or catalog save fails, the recovery state is retained so you can retry.

Other worktrees are never switched to a different branch. The worktree you ran `modify` from returns to its original branch, including its new name if that branch was renamed, or to the nearest surviving branch if the original is gone. If that surviving branch is checked out elsewhere, your worktree instead keeps its preserved original branch, and the command reports the surviving branch's path. Any pending state used by `gh stack submit` is only consumed for the stack that was just modified.

**After modifying**

If you have already created a stack of pull requests on {% data variables.product.github %}, run `gh stack submit` to push the updated branches and recreate the stack. The old stack is replaced automatically.
Expand Down Expand Up @@ -399,6 +416,8 @@ If a rebase conflict occurs, the operation pauses and prints the conflicted file
| `--remote <name>` | Remote to fetch from (defaults to the automatically detected remote) |
| `--committer-date-is-author-date` | Set the committer date to the author date during the rebase. Alias: `--preserve-dates`. |

Date-preserving rebases explicitly use Git's merge backend, so the setting persists across conflicts. `--continue` reuses the native rebase settings that were saved when the rebase started, and doesn't resend start-only date options.

| Argument | Description |
|----------|-------------|
| `[branch]` | Target branch (defaults to the current branch) |
Expand Down Expand Up @@ -543,6 +562,10 @@ Navigation commands move you between branches in the current stack without havin

All navigation commands clamp to the bounds of the stack. Moving up from the top, or down from the bottom, does nothing and displays a message.

`up`, `down`, `top`, `bottom`, `trunk`, and `checkout` with an explicit target all support `--print-path`. For a target checked out in another worktree, the command prints that worktree's path without switching to it. For a target that isn't checked out anywhere, the command checks it out in the worktree you ran it from, then prints that worktree's path. If the target is already checked out in the current worktree, the command prints the current worktree's root.

When you use `--print-path` successfully, standard output contains only the raw absolute path followed by a single newline. Diagnostics are written to standard error, and a failed or ambiguous target produces no standard output at all; `--print-path` never prompts. Without the flag, navigating to a branch that's checked out elsewhere fails and reports that branch's path. If you wrap `gh stack` in a shell function to `cd` into the printed path, check the command's exit status first, quote the path, and avoid `eval`.

### `gh stack switch`

Interactively switch to another branch in the stack.
Expand Down Expand Up @@ -686,6 +709,20 @@ gh stack feedback
gh stack feedback "Support for reordering branches"
```

## Worktree support

`gh stack` works across linked Git worktrees in the same clone.

All linked worktrees share one `gh-stack` state directory and recovery journal, stored under the repository's common directory. Native Git state, such as `HEAD`, the index, and in-progress rebase or cherry-pick markers, stays local to each worktree. Mutating commands are serialized across the whole clone, but read-only commands such as `gh stack view` remain available while a mutation runs in another worktree.

Nonconflicting legacy catalogs migrate to the current format automatically, and the original files are preserved. Catalogs with conflicting definitions require manual reconciliation. Complete any in-progress legacy recovery in its original worktree before migrating, and don't mix old and new catalog versions in the same clone.

`gh stack rebase` and `gh stack sync` automatically update the branches of any affected worktree that is clean, meaning it has no uncommitted changes, no other Git operation in progress, and is otherwise unchanged. They block updates to worktrees that are dirty, busy, missing, or have changed unexpectedly. Neither command stashes your changes automatically, or creates or removes worktrees for you.

For commands that share a recovery journal, `--continue` and `--abort` operate on the worktree recorded in the journal, not the worktree you run the command from. If recovery fails partway through, the operation's state is retained so you can retry.

For repositories created with `git init --separate-git-dir`, `gh stack` supports invocation from the main worktree, and from linked worktrees that have an absolute or relative `core.worktree` backlink to the main worktree, including settings stored in the main worktree's `config.worktree` file. The one unsupported configuration is invoking `gh stack` from a linked worktree that has no backlink to the main worktree. If an operation requires access to that worktree and can't find it, the operation fails with guidance on how to proceed; worktrees unaffected by the missing backlink continue to work normally. `gh stack` never uses a Git administration directory as a checkout destination.

## Environment variables

| Variable | Values | Description |
Expand Down
30 changes: 12 additions & 18 deletions data/tables/copilot/auto-model-selection.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,6 @@

# OpenAI

- name: GPT-5.4
cloud_agent: false
chat: true
cli: false
app: false

- name: GPT-5.5
cloud_agent: true
chat: true
cli: true
app: true

- name: GPT-5.6 Luna
cloud_agent: true
chat: true
Expand Down Expand Up @@ -68,6 +56,12 @@
cli: true
app: true

- name: GPT-6.1 Sol
cloud_agent: true
chat: true
cli: true
app: true

# Anthropic
- name: Claude Haiku 4.5
cloud_agent: true
Expand All @@ -93,20 +87,20 @@
cli: true
app: true

- name: Claude Sonnet 4.6
cloud_agent: false
- name: Claude Sonnet 5
cloud_agent: true
chat: true
cli: false
app: false
cli: true
app: true

- name: Claude Sonnet 5
- name: Claude Sonnet 5.5
cloud_agent: true
chat: true
cli: true
app: true

# Google
- name: Gemini 3.7 Flash
- name: Gemini 3.8 Flash
cloud_agent: true
chat: true
cli: true
Expand Down
2 changes: 1 addition & 1 deletion src/content-pipelines/state/gh-stack.sha
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2bd699a544a09cb5c45a013d03416e0894b0454e
cb357d8d68f7e4f44247eb784eba9a1fc3710798
2 changes: 1 addition & 1 deletion src/github-apps/lib/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,5 +60,5 @@
"2022-11-28"
]
},
"sha": "2b78fb0c53617f188e45979ecefd83b521c5428a"
"sha": "7bdf5f00553689c2dabb027685cf29081093767e"
}
5 changes: 3 additions & 2 deletions src/rest/components/RestCodeSamples.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, { useState, useEffect, useRef, FormEvent } from 'react'
import { FormControl, IconButton, Select, SegmentedControl } from '@primer/react'
import { IconButton, SegmentedControl } from '@primer/react'
import { FormControl, Select } from '@primer/react-brand'
import { CheckIcon, CopyIcon, InfoIcon } from '@primer/octicons-react'
import { announce } from '@primer/live-region-element'
import Cookies from '@/frame/components/lib/cookies'
Expand Down Expand Up @@ -137,7 +138,7 @@ export function RestCodeSamples({ operation, slug, heading }: Props) {
</h4>
{!isSingleExample && (
<div className="pb-5 pt-2">
<FormControl id="example-type-picker">
<FormControl>
<FormControl.Label visuallyHidden>Select the example type</FormControl.Label>
<Select onChange={handleExampleSelection}>
{exampleSelectOptions.map((option) => (
Expand Down
Loading
Loading