diff --git a/README.md b/README.md
index f34ae116..9cfa5e07 100644
--- a/README.md
+++ b/README.md
@@ -14,7 +14,7 @@
git-spice is a tool for stacking Git branches.
It lets you manage and navigate stacks of branches,
conveniently modify and rebase them,
-and create GitHub Pull Requests from them.
+and create GitHub Pull Requests or GitLab Merge Requests from them.
See for more details.
@@ -24,7 +24,7 @@ Usage looks roughly like this:
# Stack a branch on top of the current branch.
$ gs branch create feat1
-# Stack aonther branch on top of feat1.
+# Stack another branch on top of feat1.
$ gs branch create feat2
# Submit pull requests for feat1 and feat2.
@@ -51,8 +51,8 @@ $ gs sr # stack restack
## Features
- Create, edit, and navigate stacks of branches with ease.
-- Create and update GitHub Pull Requests for the entire stack
- or parts of it with a single command.
+- Submit the entire stack or parts of it with a single command.
+ Supports GitHub and GitLab.
- Keep using your existing workflow and adopt git-spice incrementally.
- Completely offline operation with no external dependencies
until you push or pull from a remote repository.
diff --git a/doc/hooks/badge.py b/doc/hooks/badge.py
new file mode 100644
index 00000000..36a7202f
--- /dev/null
+++ b/doc/hooks/badge.py
@@ -0,0 +1,44 @@
+"""
+Adds a badgge shortcode in the form:
+
+
+
+Where ICON is a mkdocs-material icon name
+and TEXT is the text to display.
+"""
+
+import re
+
+from mkdocs.config.defaults import MkDocsConfig
+from mkdocs.structure.files import Files
+from mkdocs.structure.pages import Page
+
+_tag_re = re.compile(r'')
+
+
+def on_page_markdown(
+ markdown: str,
+ page: Page,
+ config: MkDocsConfig,
+ files: Files,
+ **kwargs
+) -> str:
+ def replace(match: re.Match) -> str:
+ icon = match.group(1)
+ text = match.group(2)
+ return ''.join([
+ '',
+ *[
+ '',
+ f':{icon}:',
+ '',
+ ],
+ *[
+ '',
+ text,
+ '',
+ ],
+ ''
+ ])
+
+ return _tag_re.sub(replace, markdown)
diff --git a/doc/hooks/replace.py b/doc/hooks/replace.py
new file mode 100644
index 00000000..b4bd8f7e
--- /dev/null
+++ b/doc/hooks/replace.py
@@ -0,0 +1,27 @@
+"""
+Simple text replacement hooks.
+"""
+
+from mkdocs.config.defaults import MkDocsConfig
+from mkdocs.structure.files import Files
+from mkdocs.structure.pages import Page
+
+
+REPLACEMENTS = {
+ '': ':simple-github: GitHub',
+ '': ':simple-gitlab: GitLab',
+ '
Client ID for OAuth authentication with GitLab.
-Default to git-spice's built-in Client ID in https://gitlab.com.
-It should be set to a custom value if you are running your own GitLab Self-Managed instance.
+
+Defaults to git-spice's built-in Client ID (valid only for https://gitlab.com)
+or `$GITLAB_OAUTH_CLIENT_ID` if set.
+
+For Self-Hosted GitLab instances, you must set this value to a custom Client ID.
+
+See also [GitLab Self-Hosted](../setup/auth.md#gitlab-self-hosted).
### spice.log.all
diff --git a/doc/src/faq.md b/doc/src/faq.md
index 0f2109e4..2d70ccd0 100644
--- a/doc/src/faq.md
+++ b/doc/src/faq.md
@@ -31,17 +31,17 @@ keeping them up-to-date and in sync with each other.
- [The stacking workflow](https://www.stacking.dev/)
-## Where is the GitHub authentication token stored?
+## Where is the authentication token stored?
git-spice stores the GitHub authentication in a system-specific secure storage.
See [Authentication > Safety](setup/auth.md#safety) for details.
-## Why doesn't git-spice create one PR per commit?
+## Why doesn't git-spice create one CR per commit?
With tooling like this, there are two options:
each commit is an atomic unit of work, or each branch is.
While the former might be more in line with Git's original philosophy,
-the latter is more practical for most teams with GitHub-based workflows.
+the latter is more practical for most teams with GitHub or GitLab-based workflows.
With a PR per commit, when a PR gets review feedback,
you must amend that commit with fixes and force-push.
@@ -52,7 +52,7 @@ However, with a PR per branch, you can keep the original changes separate
from follow-up fixes, even if the branch is force-pushed.
This makes it easier for PR reviewers to work through the changes.
-And with GitHub squash-merges, you can still get a clean history
+And with squash-merges, you can still get a clean history
consisting of atomic, revertible commits on the trunk branch.
## How does git-spice interact with `rebase.updateRefs`?
diff --git a/doc/src/guide/branch.md b/doc/src/guide/branch.md
index 0a88b3e6..20ead59a 100644
--- a/doc/src/guide/branch.md
+++ b/doc/src/guide/branch.md
@@ -1,5 +1,5 @@
---
-title: Branch stacks
+title: Local stacks
icon: octicons/git-branch-16
description: >-
Manage, navigate, and manipulate stacks of branches with git-spice.
diff --git a/doc/src/guide/concepts.md b/doc/src/guide/concepts.md
index 25f827e7..6e6fa0da 100644
--- a/doc/src/guide/concepts.md
+++ b/doc/src/guide/concepts.md
@@ -82,6 +82,15 @@ text "Sibling" with s at F.n
This is "main" or "master" in most repositories.
Trunk is the only branch that does not have a base branch.
+**Change Request**
+: Change Request refers to a single merge-able unit of work
+ submitted to GitHub or GitLab.
+ Each Change Request corresponds to a branch.
+ On GitHub, these are called Pull Requests,
+ and on GitLab, they are called Merge Requests.
+ Since git-spice supports both platforms,
+ the term Change Request is used to refer to both.
+
**Stack**
: A stack is a collection of branches stacked on top of each other
in a way that each branch except the trunk has a base branch.
diff --git a/doc/src/guide/pr.md b/doc/src/guide/cr.md
similarity index 62%
rename from doc/src/guide/pr.md
rename to doc/src/guide/cr.md
index 2f319783..7255d58d 100644
--- a/doc/src/guide/pr.md
+++ b/doc/src/guide/cr.md
@@ -1,24 +1,36 @@
---
-title: PR stacks
+title: Submitting stacks
icon: octicons/git-pull-request-16
description: >-
- Create and update stacked pull requests from a stack of branches.
+ Create and update stacked change requests from a stack of branches.
---
-# Working with Pull Requests
+# Working with remote repositories
!!! note
- This page assumes you're using git-spice with GitHub.
- If you're using a different Git hosting service,
- you can still use git-spice, but some features may not be available.
+ This page assumes you are using one of the supported Git forges.
+ These are:
+
+ -
+ - ()
+
+ If you're using a different service,
+ you can still use git-spice,
+ but some features may not be available.
See:
- - [:material-tooltip-check: Recipes > Working with non-GitHub remotes](../recipes.md#working-with-non-github-remotes)
+ - [:material-tooltip-check: Recipes > Working with unsupported remotes](../recipes.md#working-with-unsupported-remotes)
- [:material-frequently-asked-questions: FAQ > Will git-spice add support for other Git hosting services](../faq.md#will-git-spice-add-support-for-other-git-hosting-services)
-## Submitting pull requests
+## Submitting change requests
+
+!!! info
+
+ git-spice uses the term *Change Request* to refer to submitted branches.
+ These corespond to Pull Requests on GitHub,
+ and to Merge Requests on GitLab.
When your local changes are ready,
use the following commands to submit your changes upstream:
@@ -33,10 +45,10 @@ use the following commands to submit your changes upstream:
submits all branches in the stack
Branch submission is an idempotent operation:
-pull requests will be created for branches that don't already have them,
+change requests will be created for branches that don't already have them,
and updated for branches that do.
-For new pull requests, these commands will prompt you for PR information.
+For new change requests, these commands will prompt you for CR information.
For example:
```freeze language="ansi"
@@ -52,11 +64,17 @@ For example:
### Navigation comments
-Pull Requests created by git-spice will include a navigation comment
+Change Requests created by git-spice will include a navigation comment
at the top with a visual representation of the stack,
and the position of the current branch in it.
-![Example of a stack navigation comment](../img/stack-comment.png)
+=== ""
+
+ ![Example of a stack navigation comment on GitHub](../img/stack-comment.png)
+
+=== ""
+
+ ![Example of a stack navigation comment on GitLab](../img/stack-comment-glab.png)
This behavior may be changed with the $$spice.submit.navigationComment$$
configuration key.
@@ -86,7 +104,7 @@ you may also specify title and body directly.
!!! info "Setting draft status non-interactively"
- Pull requests may be marked as draft or ready for review
+ Change requests may be marked as draft or ready for review
non-interactively with the `--draft` and `--no-draft` flags.
By default, the submit commands will leave
@@ -123,35 +141,52 @@ This will update the trunk branch (e.g. `main`)
with the latest changes from the upstream repository,
and delete any local branches whose PRs have been merged.
-## Importing pull requests
+## Importing open CRs
-You can import an existing PR into git-spice
+You can import an existing open CR into git-spice
by checking it out locally, tracking the branch with git-spice,
and re-submitting it.
-For example, if you have the GitHub CLI installed:
+For example:
-```freeze language="terminal"
-{gray}# Check out the PR locally{reset}
-{green}${reset} gh pr checkout 359
+=== ""
-{gray}# Track it with git-spice{reset}
-{green}${reset} gs branch track
+ ```freeze language="terminal"
+ {gray}# Check out the PR locally{reset}
+ {green}${reset} gh pr checkout 359
-{gray}# Re-submit it{reset}
-{green}${reset} gs branch submit
-{green}INF{reset} comment-recovery: Found existing CR #359
-{green}INF{reset} CR #359 is up-to-date: https://github.com/abhinav/git-spice/pull/359
-```
+ {gray}# Track it with git-spice{reset}
+ {green}${reset} gs branch track
+
+ {gray}# Re-submit it{reset}
+ {green}${reset} gs branch submit
+ {green}INF{reset} comment-recovery: Found existing CR #359
+ {green}INF{reset} CR #359 is up-to-date: https://github.com/abhinav/git-spice/pull/359
+ ```
+
+=== ""
+
+ ```freeze language="terminal"
+ {gray}# Check out the MR locally{reset}
+ {green}${reset} glab mr checkout 8
+
+ {gray}# Track it with git-spice{reset}
+ {green}${reset} gs branch track
+
+ {gray}# Re-submit it{reset}
+ {green}${reset} gs branch submit
+ {green}INF{reset} reticulating-splines: Found existing CR !8
+ {green}INF{reset} CR !8 is up-to-date: https://gitlab.com/abg/test-repo/-/merge_requests/8
+ ```
!!! important
For this to work, the following MUST all be true:
- - The PR is pushed to a branch in the upstream repository
+ - The CR is pushed to a branch in the upstream repository
- The local branch name exactly matches the upstream branch name
-This will work even for PRs that were not created by git-spice,
+This will work even for CRs that were not created by git-spice,
or authored by someone else, as long as the above conditions are met.
In or newer,
diff --git a/doc/src/guide/internals.md b/doc/src/guide/internals.md
index 1dc6bf55..0195f82f 100644
--- a/doc/src/guide/internals.md
+++ b/doc/src/guide/internals.md
@@ -26,7 +26,7 @@ Information is stored in JSON files with roughly the following structure:
```tree
repo # repository-level information
-templates # cached GitHub PR templates
+templates # cached change templates
rebase-continue # information about ongoing operations
branches # branch tracking information
feat1
diff --git a/doc/src/guide/limits.md b/doc/src/guide/limits.md
index 62785aa5..1bcaee3e 100644
--- a/doc/src/guide/limits.md
+++ b/doc/src/guide/limits.md
@@ -3,18 +3,18 @@ icon: octicons/stop-16
title: Limitations
description: >-
Usage constraints and limitations when using git-spice
- to interact with GitHub.
+ to interact with GitHub or GitLab.
---
-git-spice's handling of GitHub Pull Requests is limited
-by what's possible with GitHub and its handling of Git commits.
+Usage of git-spice with GitHub and GitLab runs into limitations
+of what is possible on those platforms, and how they handle Git commits.
Some limitations imposed on git-spice are listed below.
## Write access required
When a branch `F` is stacked on another branch `B`,
-and you want to create stacked Pull Requests from them,
-the PR for `F` will be created against `B`.
+and you want to submit Change Requests for both,
+the CR for `F` will be created against `B`.
To do this, git-spice needs to push both branches to the same repository.
Therefore, to use git-spice to stack PRs,
@@ -23,12 +23,14 @@ specifically the ability to push new branches.
## Squash-merges restack the upstack
-If a Pull Request is squash-merged into the trunk branch,
+On GitHub, when a Pull Request is squash-merged into the trunk branch,
all commits in that PR are replaced with a single commit with a different hash.
+Similarly on GitLab, when fast-forward merges are enabled, and commits are squashed,
+the commits in the MR are replaced with a single commit with a different hash.
-The branches upstack from that PR are not aware of this new commit,
+The branches upstack from that CR are not aware of this new commit,
still referring to the old, unsquashed history of the branch.
-GitHub does not yet know to reconcile this new commit with the upstack branches,
+GitHub and GitLab do not yet know to reconcile this new commit with the upstack branches,
even though the contents are the same.
```pikchr
@@ -81,14 +83,14 @@ arrow " restack" ljust from Y.s to Z.n
```
As a result of this, when a branch is squash-merged into the trunk branch,
-branches upstack from it need to be restacked, and all their PRs updated.
+branches upstack from it need to be restacked, and all their CRs updated.
## Base branch change may dismiss approvals
-Some GitHub repositories are configured to dismiss prior approvals of PRs
+Some remote repositories are configured to dismiss prior approvals of PRs
when the base branch of that PR is changed.
There is no workaround to this except to reconfigure the repository
as this setting is fundamentally incompatible with a PR stacking workflow.
diff --git a/doc/src/img/stack-comment-glab.png b/doc/src/img/stack-comment-glab.png
new file mode 100644
index 00000000..944a2ae8
--- /dev/null
+++ b/doc/src/img/stack-comment-glab.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:f1a0c7e7b9ce013c81416b00b8082505e63b8f5b838a3e942cab782c07e32ae6
+size 32099
diff --git a/doc/src/index.md b/doc/src/index.md
index a7be3152..de70098e 100644
--- a/doc/src/index.md
+++ b/doc/src/index.md
@@ -14,8 +14,9 @@ description: >-
git-spice is a tool for stacking Git branches.
It lets you manage and navigate stacks of branches,
-conveniently modify and rebase them,
-and create GitHub Pull Requests from them.
+conveniently modify and rebase them, and create
+ *Pull Requests* or
+ *Merge Requests* from them.
It works with Git instead of trying to replace Git.
Introduce it in small places in your existing workflow
@@ -68,7 +69,7 @@ $ gs repo sync
-- [:octicons-git-branch-16:{ .lg .middle } __Branch management__](guide/branch.md)
+- [:octicons-git-branch-16:{ .lg .middle } __Manage local branches__](guide/branch.md)
---
@@ -77,19 +78,18 @@ $ gs repo sync
you can keep your stack in sync with the trunk branch,
automatically rebase dependent branches, and more.
-- [:octicons-git-pull-request-16:{ .lg .middle } __Pull Request Management__](guide/pr.md)
+- [:octicons-git-pull-request-16:{ .lg .middle } __Submit change requests__](guide/cr.md)
---
- Create GitHub Pull Requests from your stack with a single command.
- git-spice can create
- [a PR for the current branch](cli/reference.md#gs-branch-submit),
- [PRs for the entire stack](cli/reference.md#gs-stack-submit), or
+ Submit branches in your stack with a single command.
+ git-spice can submit
+ [the current branch](cli/reference.md#gs-branch-submit),
+ [the entire stack](cli/reference.md#gs-stack-submit), or
[parts of](cli/reference.md#gs-upstack-submit)
[the stack](cli/reference.md#gs-downstack-submit).
- If a branch already has a PR, git-spice will update it.
- If a PR is merged,
- git-spice will automatically restack branches that depend on it.
+ If a branch has already been submitted, git-spice will update the submission.
+ If it has been merged, git-spice will automatically restack branches that depend on it.
- [:material-stairs:{ .lg .middle } __Incremental improvements__](start/stack.md)
@@ -105,7 +105,7 @@ $ gs repo sync
---
git-spice operates entirely locally.
- It talks directly to Git, and when you ask for it, to GitHub.
+ It talks directly to Git, and when you ask for it, to GitHub/GitLab.
All state is stored locally in your Git repository.
A network connection is not required, except when pushing or pulling.
diff --git a/doc/src/recipes.md b/doc/src/recipes.md
index 333bea86..36321fba 100644
--- a/doc/src/recipes.md
+++ b/doc/src/recipes.md
@@ -42,17 +42,17 @@ and then work on them, you can use the following to adjust the workflow:
gs branch create my-branch --commit
```
-### Working with non-GitHub remotes
+### Working with unsupported remotes
-If you're using a Git hosting service that is not GitHub
-(e.g. GitLab, Bitbucket, etc.),
+If you're using a Git hosting service that is not supported by git-spice
+(e.g. Bitbucket, SourceHut, etc.),
you can use git-spice to manage your branches locally without any issues.
However, when it comes to pushing branches to the remote,
there are some options that can help your workflow.
-- Stop git-spice from trying to create GitHub Pull Requests
+- Stop git-spice from trying to submit changes to the service
by setting $$spice.submit.publish$$ to false.
```bash
diff --git a/doc/src/setup/auth.md b/doc/src/setup/auth.md
index abb613a4..504f59da 100644
--- a/doc/src/setup/auth.md
+++ b/doc/src/setup/auth.md
@@ -1,41 +1,63 @@
---
icon: material/lock
description: >-
- Authenticate with GitHub to push and pull changes.
+ Authenticate with GitHub/GitLab to push and pull changes.
---
# Authentication
git-spice is offline-first.
It does not require authentication for local stacking operations.
-However, once you want to push or pull changes to/from a GitHub repository,
-you will need to authenticate with GitHub.
+However, once you want to push or pull changes to/from a remote repository,
+you will need to authenticate with the respective service.
-This page covers the authentication options for git-spice.
+This page covers methods to authenticate git-spice with GitHub and GitLab.
+Note that GitLab support requires at least version .
## Logging in
-To authenticate with GitHub, run:
+Take the following steps to authenticate with a service:
-```sh
-gs auth login
-```
+1. Run the following command:
+
+ ```sh
+ gs auth login
+ ```
-This will present you with a list of authentication methods.
+2. Pick the service you want to authenticate with.
-See [Authentication methods](#authentication-methods) for details
-on what to expect from each method,
-or skip on to [Pick an authentication method](#picking-an-authentication-method).
+ ```freeze language="ansi"
+ --8<-- "captures/forge-prompt.txt"
+ ```
+
+3. You will be presented with a list of authentication methods.
+ Pick the one that suits you best.
+
+!!! tip
+
+ Skip prompt (2) by running $$gs auth login$$
+ inside a Git repository cloned from GitHub or GitLab.
## Authentication methods
-git-spice provides several ways to authenticate with GitHub.
+Each supported service supports different authentication methods.
+
+- [OAuth](#oauth):
+- [GitHub App](#github-app):
+- [Personal Access Token](#personal-access-token):
+- [Service CLI](#service-cli):
+- [Environment variable](#environment-variable):
+
+Read on for more details on each method,
+or skip on to [Pick an authentication method](#picking-an-authentication-method).
### OAuth
+**Supported by**
+
With OAuth authentication, you will take the following steps:
-1. Authenticate yourself on github.com in your browser.
+1. Authenticate yourself on the service website in your browser.
2. Authorize git-spice to act on your behalf on the **current device only**.
```freeze language="terminal"
@@ -47,24 +69,39 @@ The code expires in a few minutes.
It will take a few seconds to verify after you enter it.
```
-Two options are available for OAuth:
+=== ""
-- **OAuth**: grants access to all repositories, public and private.
-- **OAuth: Public repositories only**:
- grants access to public repositories only.
+ On GitHub, OAuth is available in two flavors:
-For more granular control, use [GitHub App](#github-app) authentication.
+ - **OAuth**: grants access to all repositories, public and private.
+ - **OAuth: Public repositories only**:
+ grants access to public repositories only.
-!!! note
+ For more granular control than that,
+ use [GitHub App](#github-app) authentication.
+
+ !!! note
+
+ For private repositories owned by organizations,
+ you will need a member with administrative access to the repository
+ to allow installation of the git-spice OAuth App.
+
+ If that is not an option,
+ use a [Personal Access Token](#personal-access-token).
+
+=== ""
+
+ For Self-Hosted GitLab instances,
+ an administrator will need to set up a git-spice OAuth App.
+ Be sure to **uncheck** the "Confidential" option when creating the App.
- For private repositories owned by organizations,
- you will need a member with administrative access to the repository
- to allow installation of the git-spice OAuth App.
If that is not an option,
use a [Personal Access Token](#personal-access-token).
### GitHub App
+**Supported by**
+
With GitHub App authentication, you will take the following steps:
1. Authenticate yourself on github.com in your browser.
@@ -94,8 +131,10 @@ You **must** install the GitHub App to access repositories with git-spice.
### Personal Access Token
+**Supported by**
+
To use a Personal Access Token with git-spice,
-you will generate a Personal Access Token on GitHub
+you will generate a Personal Access Token on the website
and enter it in the prompt.
```freeze language="terminal"
@@ -104,90 +143,141 @@ Select an authentication method: {red}Personal Access Token{reset}
{green}Enter Personal Access Token{reset}:
```
-The token may be a classic token or a fine-grained token.
+=== ""
-=== "Classic token"
+ The token may be a classic token or a fine-grained token.
- With classic tokens, you can grant access to all repositories,
- or all public repositories only.
- These tokens have the ability to never expire.
+ === "Classic token"
- To use a classic token:
+ With classic tokens, you can grant access to all repositories,
+ or all public repositories only.
+ These tokens have the ability to never expire.
- 1. Go to .
- This may ask you to re-authenticate.
- 2. In the token creation form:
+ To use a classic token:
- - enter a descriptive note for the token
- - pick an expiration window, or select "No expiration"
- - select `repo` scope for full access to all repositories,
- or `public_repo` for access to public repositories only
+ 1. Go to .
+ This may ask you to re-authenticate.
+ 2. In the token creation form:
- 3. Click "Generate token" and copy the token.
+ - enter a descriptive note for the token
+ - pick an expiration window, or select "No expiration"
+ - select `repo` scope for full access to all repositories,
+ or `public_repo` for access to public repositories only
-=== "Fine-grained token"
+ 3. Click "Generate token" and copy the token.
- With fine-grained tokens, you have more granular control over
- repositories that you grant access to.
- These token must always have an expiration date.
+ === "Fine-grained token"
- To use a fine-grained token:
+ With fine-grained tokens, you have more granular control over
+ repositories that you grant access to.
+ These token must always have an expiration date.
- 1. Go to .
- This may ask you to re-authenticate.
- 2. In the token creation form:
+ To use a fine-grained token:
- - pick a descriptive note for the token
- - pick an expiration window
- - in the *Repository access* section, select the repositories
- you want to use git-spice with
- - in the *Repository permissions* section,
- grant **Read and write** access to **Pull requests** and **Contents**
+ 1. Go to .
+ This may ask you to re-authenticate.
+ 2. In the token creation form:
- 3. Click "Generate token" and copy the token.
+ - pick a descriptive note for the token
+ - pick an expiration window
+ - in the *Repository access* section, select the repositories
+ you want to use git-spice with
+ - in the *Repository permissions* section,
+ grant **Read and write** access to **Pull requests** and **Contents**
+
+ 3. Click "Generate token" and copy the token.
+
+=== ""
+
+ To use a Personal Access Token with GitLab:
+
+ 1. Go to .
+ 2. Select *Add new token*
+ 3. In the token creation form:
+
+ - pick a descriptive name for the token
+ - pick an expiration date if needed
+ - select the `api` scope
After you have a token, enter it into the prompt.
-### GitHub CLI
+### Service CLI
+
+**Supported by**
+
+If you have the GitHub or GitLab CLIs installed and authenticated,
+you can get authentication tokens for git-spice from them.
-If you have the [GitHub CLI](https://cli.github.com/) installed and authenticated,
-you can select this as the authentication method.
+=== ""
-This requires no additional steps.
-We'll request a token from GitHub CLI as needed.
+ 1. Install the [GitHub CLI](https://github.com/cli/cli#installation)
+ 2. Authenticate it:
-### GITHUB_TOKEN
+ ```freeze language="terminal"
+ {green}${reset} gh auth login
+ ```
-If you have a `GITHUB_TOKEN` environment variable set,
-that takes precedence over all other authentication methods.
+=== ""
-The $$gs auth login$$ operation will fail if you use this method.
+ 1. Install the [GitLab CLI](https://gitlab.com/gitlab-org/cli#installation).
+ 2. Authenticate it:
+
+ ```freeze language="terminal"
+ {green}${reset} glab auth login
+ ```
+
+Once you pick this authentication option, no additional steps are required.
+git-spice will request a token from the CLI as needed.
+
+### Environment variable
+
+**Supported by**
+
+You can provide the authentication token as an environment variable.
+This is not recommended as a primary authentication method,
+but it can be useful in CI/CD environments.
+
+=== ""
+
+ Set the `GITHUB_TOKEN` environment variable to your token.
+
+=== ""
+
+ Set the `GITLAB_TOKEN` environment variable to your token.
+
+If you have the environment variable set,
+this takes precedence over all other authentication methods.
+
+The $$gs auth login$$ operation will always fail if you use this method.
## Picking an authentication method
-[OAuth](#oauth) and [GitHub App](#github-app) authentication are best if you
-have the permissions needed to install OAuth/GitHub Apps
-on all repositories that you want to use git-spice with.
-The two are equivalent in terms of user experience.
-Use GitHub App authentication if you don't want to give git-spice access
-to all your repositories.
+[OAuth](#oauth) is best if you have the permissions needed
+to install it on all repositories that you want to use git-spice with.
+Additionally, on GitHub, [GitHub App](#github-app) is similar,
+but it may be preferable if you don't want to give git-spice
+access to all your repositories.
-[GitHub CLI](#github-cli) is the most convenient method if you already have
-the GitHub CLI installed and authenticated.
-It loses some security benefits of the other methods,
-as it re-uses the token from the GitHub CLI.
-You lose the ability to revoke the git-spice token
-without revoking the GitHub CLI token.
+[Service CLI](#service-cli) is the most convenient method if you already have
+the CLI for the service installed and authenticated,
+and your organization already allows its use.
+It loses security benefits of the other methods,
+as it re-uses the token assigned to the CLI.
+For example, it you lose the ability to revoke the git-spice token
+without revoking the CLI token.
[Personal Access Token](#personal-access-token) is flexible and secure.
It may be used even with repositories where you don't have permission to
-install OAuth/GitHub Apps.
+install OAuth or GitHub Apps.
However, it requires manual token management, making it less convenient.
-[GITHUB_TOKEN](#github_token) is the least convenient and the least secure method.
+[Environment variable](#environment-variable) is the least convenient
+and the least secure method. End users should typically never pick this.
It is intended only for CI/CD environments where you have no other choice.
-## GitHub Enterprise
+## Self-hosted instances
+
+### GitHub Enterprise
To use git-spice with a GitHub Enterprise instance,
inform it of the instance URL, authenticate, and use git-spice as usual.
@@ -231,9 +321,46 @@ inform it of the instance URL, authenticate, and use git-spice as usual.
Both values must be set for git-spice to work with GitHub Enterprise.
+### GitLab Self-Hosted
+
+To use git-spice with a self-hosted GitLab instance,
+set $$spice.forge.gitlab.url$$ to the address of your GitLab instance.
+
+```freeze language="terminal"
+{green}${reset} git config {red}spice.forge.gitlab.url{reset} {mag}https://gitlab.example.com{reset}
+```
+
+This may also be set with the `GITLAB_URL` environment variable.
+
+```freeze language="bash"
+export GITLAB_URL=https://gitlab.example.com
+```
+
+#### OAuth with GitLab Self-Hosted
+
+To use OAuth authentication with a self-hosted GitLab instance,
+you must first set up an OAuth App on the GitLab instance.
+Be sure to **uncheck** the "Confidential" option when creating the App.
+This will generate an OAuth Client ID for the App.
+
+Feed that into git-spice with the $$spice.forge.gitlab.oauth.clientID$$
+configuration option.
+
+```freeze language="terminal"
+{green}${reset} git config {red}spice.forge.gitlab.oauth.clientID{reset} {mag}your-client-id{reset}
+```
+
+This may also be set with the `GITLAB_OAUTH_CLIENT_ID` environment variable.
+
+```freeze language="bash"
+export GITLAB_OAUTH_CLIENT_ID=your-client-id
+```
+
+Authenticate with $$gs auth login$$ as usual after that.
+
## Safety
-By default, git-spice stores your GitHub authentication token
+By default, git-spice stores your authentication token
in a system-specific secure storage.
On macOS, this is the system Keychain.
On Linux, it uses the [Secret Service](https://specifications.freedesktop.org/secret-service/latest/),
diff --git a/doc/src/start/stack.md b/doc/src/start/stack.md
index b1f7adcd..b9aef4ef 100644
--- a/doc/src/start/stack.md
+++ b/doc/src/start/stack.md
@@ -153,4 +153,4 @@ Time to modify a branch in the middle of the stack.
- [ ] Use $$gs commit create$$ to combine the commit and restack steps
- [ ] Explore different flags of $$gs branch create$$
-- [ ] [Create your first stacked pull requests](submit.md)
+- [ ] [Create your first stacked CRs](submit.md)
diff --git a/doc/src/start/submit.md b/doc/src/start/submit.md
index b9b0e5a1..42dc1f3c 100644
--- a/doc/src/start/submit.md
+++ b/doc/src/start/submit.md
@@ -1,8 +1,8 @@
---
-title: Your first stacked PRs
+title: Your first stacked CRs
icon: material/slide
description: >-
- Turn a stack of branches into Pull Requests.
+ Turn a stack of branches into Change Requests.
Update them all in one go.
prev_page: stack.md
next_page: ../guide/index.md
@@ -11,7 +11,8 @@ next_page: ../guide/index.md
# Your first stacked Pull Requests
This page will walk you through creating and updating
-GitHub Pull Requests with git-spice.
+*GitHub Pull Requests* or *GitLab Merge Requests* with git-spice.
+git-spice refers to these as *Change Requests* (CRs).
## Prerequisites
@@ -28,7 +29,7 @@ GitHub Pull Requests with git-spice.
text "feat2"
```
-- [x] Set up a GitHub repository.
+- [x] Set up a GitHub or GitLab repository.
??? info "Optional: Create an experimental repository"
@@ -36,20 +37,31 @@ GitHub Pull Requests with git-spice.
you may want to create a new repository on GitHub
to experiment with instead of using a real project.
- To do this, if you have the GitHub CLI installed,
+ To do this, if you have the GitHub or GitLab CLI installed,
run the following inside your experimental repository:
- ```bash
- gh repo create gs-playground \
- --public \
- --source=$(pwd) \
- --push
- ```
+ === ""
+
+ ```bash
+ gh repo create gs-playground \
+ --public \
+ --source=$(pwd) \
+ --push
+ ```
+
+ If you don't have the GitHub CLI installed,
+ go to and follow the instructions there.
+
+ === ""
+
+ ```bash
+ glab repo create gs-playground --public
+ ```
- If you don't have the GitHub CLI installed,
- go to and follow the instructions there.
+ If you don't have the GitLab CLI installed,
+ go to and follow the instructions there.
-## Create a Pull Request
+## Create a Change Request
1. Check out `feat1`.
@@ -71,7 +83,7 @@ GitHub Pull Requests with git-spice.
gs bco feat1
```
-2. Submit a PR.
+2. Submit the change.
=== "gs"
@@ -85,7 +97,7 @@ GitHub Pull Requests with git-spice.
gs bs
```
-3. Follow the prompts on-screen to create the PR.
+3. Follow the prompts on-screen to create the CR.
For example:
```freeze language="ansi"
@@ -100,20 +112,20 @@ GitHub Pull Requests with git-spice.
gs up
```
-2. Submit a PR.
+2. Submit a CR.
```bash
gs branch submit
```
-3. Follow the prompts on-screen to create the PR.
+3. Follow the prompts on-screen to create the CR.
-The new PR will now be stacked on top of the previous one:
-GitHub will show `feat1` as the base branch for the PR.
+The new CR will now be stacked on top of the previous one:
+the remote will show `feat1` as the base branch for the CR.
## Modify mid-stack
-Modify the `feat1` branch and update the PR.
+Modify the `feat1` branch and update the CR.
1. Check out `feat1`.
@@ -145,19 +157,19 @@ Modify the `feat1` branch and update the PR.
This will commit to the current branch,
and rebase the upstack branches on top of the new commit.
-3. Update all PRs in the stack.
+3. Update all CRs in the stack.
```bash
gs stack submit
```
-This will push to both PRs in the stack.
+This will push to both CRs in the stack.
If one of the branches was not submitted yet,
-it will prompt you to create a PR for it.
+it will prompt you to create a CR for it.
-## Merge a PR
+## Merge a CR
-1. Open up the Pull Request for `feat1` on GitHub
+1. Open up the CR for `feat1` in your browser
and merge it into `main`.
2. Run the following command to sync the stack with the trunk:
@@ -169,7 +181,7 @@ it will prompt you to create a PR for it.
This will delete `feat1` locally,
and rebase `feat2` on top of `main`.
-3. Submit the PR for `feat2` to update the pull request
+3. Submit the CR for `feat2` to update the pull request
if necessary.
```bash
@@ -180,8 +192,8 @@ it will prompt you to create a PR for it.
**This section covered:**
-- [x] $$gs branch submit$$ creates or updates a PR for the current branch.
-- [x] $$gs stack submit$$ creates or updates PRs for the entire stack.
+- [x] $$gs branch submit$$ creates or updates a CR for the current branch.
+- [x] $$gs stack submit$$ creates or updates CRs for the entire stack.
- [x] $$gs repo sync$$ syncs the stack with the trunk branch,
deletes merged branches, and rebases the remaining branches.
diff --git a/internal/forge/gitlab/forge.go b/internal/forge/gitlab/forge.go
index 22ab463d..66465602 100644
--- a/internal/forge/gitlab/forge.go
+++ b/internal/forge/gitlab/forge.go
@@ -34,7 +34,7 @@ type Options struct {
// ClientID is the OAuth client ID for GitLab OAuth device flow.
// This should be used if the GitLab instance is Self Managed.
- ClientID string `name:"gitlab-oauth-client-id" hidden:"" config:"forge.gitlab.oauth.clientID" help:"GitLab OAuth client ID"`
+ ClientID string `name:"gitlab-oauth-client-id" hidden:"" env:"GITLAB_OAUTH_CLIENT_ID" config:"forge.gitlab.oauth.clientID" help:"GitLab OAuth client ID"`
}
// Forge builds a GitLab Forge.