Home / Alt manpages / gh-label-clone(1)

  • gh-label-clone(1)
  • User command
  • linux

Copy Labels Between Repos with gh label clone

Set up a fresh repository and you will want last project's labels, not GitHub's defaults, and gh label clone copies them across in one command. You will copy every label from one repository to another while keeping destination-only labels intact. The examples use GitHub CLI 2.87.3, the version installed on this machine, and take about ten minutes once you know the two repository names.

  • You need: an authenticated gh session that can read the source repository and change labels in the destination.
  • What it changes: repository metadata on GitHub. Your local Git checkout is untouched.
  • Privileges: no sudo.

1. Check the installed command and your session

Confirm which executable will run and check authentication before making a change:

$ command -v gh
/usr/bin/gh
$ gh --version
gh version 2.87.3 (2026-02-23)
$ gh auth status

The path can differ on your machine. The version line helps when you compare behaviour with another host. If gh auth status says you are not logged in, authenticate through your normal GitHub CLI process and stop until it succeeds. Never put an access token in a shell command or article.

Checkpoint

Both repository names are in OWNER/REPO form, for example acme/template-repo and acme/service-api. The source is the repository whose labels you want to copy.

2. Record the source and destination

Use shell variables to make the direction visible. Replace both values before running the later commands:

$ SOURCE='OWNER/SOURCE-REPOSITORY'
$ DESTINATION='OWNER/DESTINATION-REPOSITORY'
$ printf 'source: %s\ndestination: %s\n' "$SOURCE" "$DESTINATION"
source: OWNER/SOURCE-REPOSITORY
destination: OWNER/DESTINATION-REPOSITORY

Without --repo, the destination is the current repository. That default is easy to miss when you run the command from a checkout belonging to a different project. Supplying --repo removes the ambiguity and lets you run the operation from any directory.

3. Inspect both label sets

List the labels on both sides before copying. These commands ask for the fields that matter in a review and raise the limit above its default of 30:

$ gh label list --repo "$SOURCE" --limit 1000 --sort name --json name,color,description
$ gh label list --repo "$DESTINATION" --limit 1000 --sort name --json name,color,description

Both print JSON. Keep the two outputs if the destination already has carefully tuned colours or descriptions. A label with the same name can have different settings in the two repositories, and that matters if you later use --force.

Checkpoint

$SOURCE is the intended origin and $DESTINATION is the intended target. A typo in either produces a valid request against the wrong repository.

4. Copy labels without overwriting existing ones

Run the safe default first:

$ gh label clone "$SOURCE" --repo "$DESTINATION"
$ printf 'exit status: %s\n' "$?"
exit status: 0

What happens:

  • Source labels are copied to the destination.
  • Matching labels are skipped. Labels already present at the destination stay as they are.
  • Destination-only labels are safe. They are not deleted or modified.

A zero exit status means the CLI completed the request. Verify the resulting state instead of waiting for a progress message. Check the destination again:

$ gh label list --repo "$DESTINATION" --limit 1000 --sort name --json name,color,description

Compare it with the source output. New labels should now be present, and existing destination labels should keep their previous colour and description, because the default operation skips them.

5. Overwrite matching labels only after review

Warning

--force changes labels that share a name in the destination. It is the destructive branch of this workflow: source values replace destination values, and gh label clone has no undo.

Use it only when the source is the deliberate authority for matching labels:

$ gh label clone "$SOURCE" --repo "$DESTINATION" --force
$ printf 'exit status: %s\n' "$?"
exit status: 0

Review the destination once more:

$ gh label list --repo "$DESTINATION" --limit 1000 --sort name --json name,color,description

Recovery

Save the destination JSON before using --force. For a small number of labels you can then restore the recorded values with gh label edit, for example:

$ gh label edit 'bug' --repo "$DESTINATION" --color 'B60205' --description 'A confirmed defect'

Use the actual saved name, six-character hexadecimal colour and description from your review. This is manual restoration, not a transaction rollback.

6. Diagnose the common failures

  • Repository not found. Check the spelling and your access to both repositories. A private source can be readable in a browser session yet unavailable to the account gh uses. Run the two gh label list checks separately to see which side fails.
  • Wrong destination. Check the command for --repo and do not rely on the current directory. If you find a mistaken destination after a copy, stop. The default operation is additive, so destination-only labels remain; if --force was used, inspect the label list and repair overwritten labels from your saved values.
  • Labels missing after a successful run. Compare the source and destination lists with the same --limit. The default is 30, so a short listing does not prove the repository has only 30 labels. Raise the limit for large repositories and check the exit status.

Done means

  • Session checked: the installed gh version and authenticated account were confirmed.
  • Direction explicit: source and destination were written in OWNER/REPO form.
  • Before and after: the destination was inspected both before and after cloning.
  • Default run was gentle: destination-only labels were left alone and matching labels skipped.
  • Force was earned: --force was used only after review, with a saved record of any overwritten values.