Skip to content

Conversation

@ngopalak-redhat
Copy link
Contributor

@ngopalak-redhat ngopalak-redhat commented Nov 3, 2025

What this PR does / why we need it:

Add /git:setup - Automated Git Repository Setup Command

Summary

New slash command that automates git repository setup for OpenShift/Red Hat development workflows with upstream, downstream, and personal fork remotes.

NOTE: The command does not conflict with /openshift:rebase which is used for the openshift/kubernetes repo. This new command is useful for folks who are working on other repositories of openshift. A note has been added to display this.

What It Does

  • Automates repository setup: Creates forks, clones repos, and configures remotes in one interactive flow
  • Supports 5 workflows: Upstream-only, downstream-only, full 3-remote setup, branch creation, and rebasing
  • Smart remote management: Automatically configures origin, upstream, and downstream (openshift) remotes
  • Branch operations: Create synced branches or rebase existing ones with conflict handling
  • Safe & validated: Checks GitHub auth, SSH keys, git config, and validates URLs before operations

Key Features

  • Interactive prompts with sensible defaults
  • Automatic fork creation via GitHub CLI (NOTE: Github CLI is not required if the fork is already created)
  • Handles existing repos/forks/remotes gracefully
  • Auto-stash/unstash for uncommitted changes during rebase
  • Compatible with /openshift:rebase command
  • Follows Go workspace conventions ($HOME/go/src/github.com//)

Workflows Supported

  1. Upstream only - Simple fork + upstream remote
  2. Upstream + downstream - Full OpenShift 3-remote setup (origin, upstream, openshift)
  3. Downstream only - OpenShift-native projects without upstream
  4. Create branch - New branch synced with remote
  5. Rebase branch - Rebase with latest code from any remote

Usage
`
/git:setup [--upstream-only | --downstream-only]

`

Benefits

  • Prevents common remote naming/URL mistakes.
  • Ensures consistent developer workflows
  • Interactive learning for new contributors
  • Makes it very easy for developers to create branches based on a remote branch.

There are several more options that can be added to this to simplify the developer experience in setting up repos.

Which issue(s) this PR fixes:

Fixes

Special notes for your reviewer:

Checklist:

  • Subject and description added to both, commit and PR.
  • Relevant issues have been referenced.
  • This change includes docs.

@openshift-ci openshift-ci bot added do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. labels Nov 3, 2025
@openshift-ci
Copy link

openshift-ci bot commented Nov 3, 2025

Hi @ngopalak-redhat. Thanks for your PR.

I'm waiting for a github.com member to verify that this patch is reasonable to test. If it is, they should reply with /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work. Regular contributors should join the org to skip this step.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@ngopalak-redhat ngopalak-redhat marked this pull request as ready for review November 3, 2025 08:00
@openshift-ci openshift-ci bot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Nov 3, 2025
@openshift-ci openshift-ci bot requested review from bentito and enxebre November 3, 2025 08:00
@ngopalak-redhat
Copy link
Contributor Author

/assign @stbenjam Similar to previous commands you have reviewed before :)

@stbenjam
Copy link
Member

stbenjam commented Nov 3, 2025

Please join the openshift-eng org. There's a pinned message on Slack.

/ok-to-test

@openshift-ci openshift-ci bot added ok-to-test Indicates a non-member PR verified by an org member that is safe to test. and removed needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. labels Nov 3, 2025
@ngopalak-redhat
Copy link
Contributor Author

/test lint

@openshift-ci
Copy link

openshift-ci bot commented Nov 3, 2025

@ngopalak-redhat: The specified target(s) for /test were not found.
The following commands are available to trigger optional jobs:

/test images

Use /test all to run all jobs.

In response to this:

/test lint

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@ngopalak-redhat
Copy link
Contributor Author

/test all

@ngopalak-redhat
Copy link
Contributor Author

Thanks @stbenjam . I have sent the request to join openshift-eng. Looks like "lint" can't be invoked via slash commands in git. I have fixed it the error it was reporting.

@brandisher
Copy link

/assign

Copy link
Member

@stbenjam stbenjam left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you have the "gh" command line tool already installed I think it could be a little smarter about knowing my username, and checking for fork, etc.

I'd be more apt to a use a command that was just /git:setup [link to upstream repo] and it did basically everything without needing to ask so many questions.

Won't hold up merging it, feel free to /hold cancel to merge it

/lgtm
/hold

Comment on lines +147 to +165
For **Option 1** (Upstream only) or **Option 2** (Upstream with downstream):
```
Do you want to create a personal fork from upstream? (y/n)
```

If yes:
- Use GitHub CLI to create fork: `gh repo fork <upstream-org>/<upstream-repo> --clone=false`
- This creates fork under authenticated user's account

If no or fork already exists:
```
What is your personal fork name?
Hint: Format is usually <github-username>/<repo-name>
Example: <username>/kubernetes
```

For **Option 3** (Downstream only):
```
Do you want to create a personal fork from downstream? (y/n)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could probably just have it check if I already have a fork

@openshift-ci openshift-ci bot added the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Nov 5, 2025
@openshift-ci openshift-ci bot added the lgtm Indicates that a PR is ready to be merged. label Nov 5, 2025
@openshift-ci
Copy link

openshift-ci bot commented Nov 5, 2025

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: ngopalak-redhat, stbenjam

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-ci openshift-ci bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Nov 5, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 5, 2025

Walkthrough

A new /git:setup Git plugin command is introduced to configure repositories with upstream and downstream remotes for forked development workflows. Changes include command metadata, documentation in plugin README, and comprehensive command-specific documentation with usage examples.

Changes

Cohort / File(s) Summary
Plugin command documentation
PLUGINS.md, plugins/git/README.md
Added /git:setup command reference with synopsis and description for configuring forked workflow remotes
Command metadata
docs/data.json
Added setup command entry to Git plugin with name, description, synopsis, and argument hints
Command-specific documentation
plugins/git/commands/setup.md
New comprehensive documentation file detailing interactive and non-interactive workflows, remote configuration, validation steps, usage examples, and safety considerations for fork-based development setup

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant GitSetup as /git:setup command
    participant GitHub as GitHub CLI
    participant GitConfig as Git Config
    participant LocalRepo as Local Repository

    User->>GitSetup: Execute /git:setup [--flags]
    GitSetup->>GitSetup: Determine setup type (interactive/flags)
    GitSetup->>GitSetup: Validate GitHub URL
    GitSetup->>GitHub: Check authentication & create fork
    GitHub-->>GitSetup: Fork created
    GitSetup->>LocalRepo: Clone/configure repository
    GitSetup->>GitConfig: Configure origin remote
    GitSetup->>GitConfig: Configure upstream remote
    GitSetup->>GitConfig: Configure downstream remote (if applicable)
    GitSetup->>GitSetup: Validate all remotes
    GitSetup-->>User: Setup complete with summary
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • plugins/git/commands/setup.md — Comprehensive workflow documentation requires careful review to verify accuracy of described remote configurations, interactive prompts, edge cases (existing repositories, existing remotes), and git command sequences
  • Validation logic descriptions — Ensure GitHub URL checks, SSH key requirements, and gh authentication validation steps are clearly documented and feasible
  • Usage examples — Verify all provided examples (OpenShift workflow, upstream-only, downstream-only, existing-directory scenarios) are accurate and cover expected use cases
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
PLUGINS.md (1)

65-72: Reorder command to maintain alphabetical sequence consistent with data.json. The "setup" command should appear after "summary" (line 72) to maintain alphabetical ordering. Ensure this matches the correction made to docs/data.json.

  - **`/git:debt-scan`** - Analyze technical debt indicators in the repository
+ - **`/git:setup` `[--upstream-only | --downstream-only]`** - Set up a git repository with upstream and downstream remotes for forked development workflows
+ - **`/git:summary`** - Show current branch, git status, and recent commits for quick context
  - **`/git:suggest-reviewers` `[base-branch]`** - Suggest appropriate reviewers for a PR based on git blame and OWNERS files
- - **`/git:setup` `[--upstream-only | --downstream-only]`** - Set up a git repository with upstream and downstream remotes for forked development workflows
- - **`/git:suggest-reviewers` `[base-branch]`** - Suggest appropriate reviewers for a PR based on git blame and OWNERS files
  - **`/git:summary`** - Show current branch, git status, and recent commits for quick context
♻️ Duplicate comments (1)
plugins/git/commands/setup.md (1)

145-177: Address fork existence checking as noted in past review. The documentation doesn't explicitly specify behavior when a fork already exists. Per stbenjam's earlier comment, the implementation should check for existing forks before attempting creation. Consider updating lines 149-150 and 165-166 to indicate that the tool should detect existing forks and skip creation gracefully.

🧹 Nitpick comments (3)
plugins/git/commands/setup.md (3)

119-124: Improve writing style to avoid repeated sentence beginnings. Lines 119–124 contain three successive sentences beginning with "If". Consider rewording one or two to improve readability:

- If `--upstream-only` flag is provided, skip to upstream-only flow.
- If `--downstream-only` flag is provided, skip to downstream-only flow.
- 
- If **Option 4** is selected, skip to "Create Branch in Existing Repository" flow.
- If **Option 5** is selected, skip to "Rebase Existing Branch with Remote" flow.
+ When `--upstream-only` flag is provided, skip to the upstream-only flow.
+ When `--downstream-only` flag is provided, skip to the downstream-only flow.
+ 
+ For **Option 4**, proceed to the "Create Branch in Existing Repository" flow.
+ For **Option 5**, proceed to the "Rebase Existing Branch with Remote" flow.

811-811: Use a hyphen to join compound modifier. Line 811 should read "Upstream-only Setup" instead of "Upstream Only Setup" per standard English grammar for compound modifiers before nouns.

- ### Example 2: Upstream Only Setup
+ ### Example 2: Upstream-Only Setup

218-237: Clarify clone path recommendations for consistency. The documentation suggests both <code-base-path>/github.com/<org>/<repo> format in step 8, which aligns with Go conventions mentioned in the Notes section. However, verify that default suggestions in the prompts (lines 227, 235) are consistent with this recommendation. Consider explicitly stating this is the recommended Go workspace structure to help users understand the rationale.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Cache: Disabled due to data retention organization setting

Knowledge base: Disabled due to Reviews -> Disable Knowledge Base setting

📥 Commits

Reviewing files that changed from the base of the PR and between b536984 and 086e35f.

📒 Files selected for processing (4)
  • PLUGINS.md (1 hunks)
  • docs/data.json (1 hunks)
  • plugins/git/README.md (1 hunks)
  • plugins/git/commands/setup.md (1 hunks)
🧰 Additional context used
🪛 LanguageTool
plugins/git/commands/setup.md

[style] ~122-~122: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...ided, skip to downstream-only flow. If Option 4 is selected, skip to "Crea...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)


[style] ~123-~123: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...Branch in Existing Repository" flow. If Option 5 is selected, skip to "Reba...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)


[grammar] ~811-~811: Use a hyphen to join words.
Context: ...p complete! ### Example 2: Upstream Only Setup /git:setup --upstream-on...

(QB_NEW_EN_HYPHEN)

🪛 markdownlint-cli2 (0.18.1)
plugins/git/commands/setup.md

10-10: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


33-33: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


45-45: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


90-90: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


99-99: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


108-108: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


128-128: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


137-137: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


148-148: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


157-157: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


164-164: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


173-173: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


180-180: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


185-185: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


190-190: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


202-202: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


210-210: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


223-223: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


231-231: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


272-272: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


301-301: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


309-309: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


316-316: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


341-341: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


357-357: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


378-378: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


421-421: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


429-429: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


494-494: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


509-509: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


522-522: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


550-550: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


555-555: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


587-587: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


591-591: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


707-707: Bare URL used

(MD034, no-bare-urls)


719-719: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


743-743: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


748-748: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


813-813: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


821-821: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


826-826: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


878-878: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


883-883: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


929-929: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


933-933: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


957-957: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


961-961: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


986-986: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


990-990: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


996-996: Hard tabs
Column: 7

(MD010, no-hard-tabs)


997-997: Hard tabs
Column: 7

(MD010, no-hard-tabs)


1032-1032: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


1036-1036: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


1085-1085: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


1089-1089: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


1183-1183: Bare URL used

(MD034, no-bare-urls)

🔇 Additional comments (2)
plugins/git/README.md (1)

7-19: LGTM. The documentation clearly describes the command's purpose and key features, aligning well with the PR objectives.

docs/data.json (1)

34-39: Reorder command to maintain alphabetical sequence. The new "setup" command should appear after "summary" and before "suggest-reviewers" to maintain alphabetical ordering of the commands array. Currently it's positioned after "debt-scan".

         {
           "name": "debt-scan",
           "description": "Analyze technical debt indicators in the repository",
           "synopsis": "/git:debt-scan",
           "argument_hint": ""
         },
+        {
+          "name": "setup",
+          "description": "Set up a git repository with upstream and downstream remotes for forked development workflows",
+          "synopsis": "/git:setup [--upstream-only | --downstream-only]",
+          "argument_hint": "[--upstream-only | --downstream-only]"
+        },
+        {
+          "name": "summary",
+          "description": "Show current branch, git status, and recent commits for quick context",
+          "synopsis": "/git:summary",
+          "argument_hint": ""
+        },
         {
           "name": "suggest-reviewers",
           ...
         }
-        {
-          "name": "setup",
-          "description": "Set up a git repository with upstream and downstream remotes for forked development workflows",
-          "synopsis": "/git:setup [--upstream-only | --downstream-only]",
-          "argument_hint": "[--upstream-only | --downstream-only]"
-        },

Likely an incorrect or invalid review comment.

Comment on lines +1 to +1185
---
description: Set up a git repository with upstream and downstream remotes for forked development workflows
argument-hint: [--upstream-only | --downstream-only]
---

## Name
git:setup

## Synopsis
```
/git:setup [--upstream-only | --downstream-only]
```

## Description
The `git:setup` command helps set up a git repository following the OpenShift/Red Hat development workflow where:
- **Upstream**: The original repository (e.g., kubernetes on GitHub)
- **Downstream**: The Red Hat/OpenShift fork (e.g., openshift/kubernetes)
- **Origin**: Your personal fork for development

This command handles:
- Creating personal forks from upstream repositories
- Cloning repositories to the local filesystem
- Setting up git remotes (origin, upstream, downstream)
- Creating and syncing branches across remotes
- Managing existing local repositories

## Implementation

### Welcome Message

When the tool starts, display the following message:

```
The git setup tool helps you fork git repositories and clone them. Also helps keep the cloned repo in sync with the upstream or downstream repo. You can also create branches in git that will have the correct changes from upstream repos.

IMPORTANT: To rebase openshift/kubernetes use the "/openshift:rebase" command. This command is for generalized git repository setup and management.
```

### Initial Setup Flow

1. **Ask for Local Code Repository Base Path**

First, ask the user where they keep all their code repositories:

```
Where do you keep your code repositories?
Example: $HOME/go/src
Default: $HOME/go/src
```

Once the user provides the path:
- Validate that the directory exists
- If the directory doesn't exist, ask if they want to create it
- Change to that directory: `cd <code-base-path>`
- Store this path as `<code-base-path>` for later use in constructing the full clone path

Example implementation:
```bash
# Get the code base path from user (default: $HOME/go/src)
code_base_path="${user_input:-$HOME/go/src}"

# Expand ~ to full home path if needed
code_base_path="${code_base_path/#\~/$HOME}"

# Check if directory exists
if [ ! -d "$code_base_path" ]; then
echo "Directory $code_base_path does not exist."
read -p "Would you like to create it? (y/n): " create_dir
if [ "$create_dir" = "y" ]; then
mkdir -p "$code_base_path"
echo "✓ Created directory $code_base_path"
else
echo "Please provide an existing directory path."
exit 1
fi
fi

# Change to the code base directory
cd "$code_base_path"
echo "✓ Changed to directory $code_base_path"
```

2. **Ask About Repository Type**

**Note**: The AskUserQuestion tool has a maximum of 4 options. To accommodate all 5 workflow options, use one of these approaches:

**Approach A - Two-step question (Recommended)**:

First question:
```
Do you want to set up:
1. Upstream repository only (no downstream fork)
2. Upstream with downstream fork (Red Hat/OpenShift workflow)
3. Downstream repository only (e.g., OpenShift projects without upstream)
4. Work with existing repository (create/rebase branches)
```

If option 4 is selected, ask a follow-up question:
```
What would you like to do with your existing repository?
1. Create a new branch synced with upstream/downstream branch
2. Rebase an existing branch with latest code from remote
```

**Approach B - Direct text output (Alternative)**:

Instead of using AskUserQuestion, output the options as text and ask the user to respond:
```
Do you want to set up:
1. Upstream repository only (no downstream fork)
2. Upstream with downstream fork (Red Hat/OpenShift workflow)
3. Downstream repository only (e.g., OpenShift projects without upstream)
4. Create a branch in personal forked repository synced with upstream/downstream branch (for existing repos)
5. Rebase an existing branch with latest code from remote (for existing repos)

Please respond with the option number (1-5):
```

If `--upstream-only` flag is provided, skip to upstream-only flow.
If `--downstream-only` flag is provided, skip to downstream-only flow.

If **Option 4** is selected, skip to "Create Branch in Existing Repository" flow.
If **Option 5** is selected, skip to "Rebase Existing Branch with Remote" flow.

3. **Get Repository URL**

For **Option 1** (Upstream only) or **Option 2** (Upstream with downstream):
```
What is the upstream repository URL?
Example: https://github.com/kubernetes/kubernetes
```

Validate the URL is a valid GitHub repository.
Parse to extract: `<upstream-org>/<upstream-repo>`

For **Option 3** (Downstream only):
```
What is the downstream repository URL?
Example: https://github.com/openshift/machine-config-operator
```

Validate the URL is a valid GitHub repository.
Parse to extract: `<downstream-org>/<downstream-repo>`

4. **Personal Fork Setup**

For **Option 1** (Upstream only) or **Option 2** (Upstream with downstream):
```
Do you want to create a personal fork from upstream? (y/n)
```

If yes:
- Use GitHub CLI to create fork: `gh repo fork <upstream-org>/<upstream-repo> --clone=false`
- This creates fork under authenticated user's account

If no or fork already exists:
```
What is your personal fork name?
Hint: Format is usually <github-username>/<repo-name>
Example: <username>/kubernetes
```

For **Option 3** (Downstream only):
```
Do you want to create a personal fork from downstream? (y/n)
```

If yes:
- Use GitHub CLI to create fork: `gh repo fork <downstream-org>/<downstream-repo> --clone=false`
- This creates fork under authenticated user's account

If no or fork already exists:
```
What is your personal fork name?
Hint: Format is usually <github-username>/<repo-name>
Example: <username>/machine-config-operator
```

5. **Personal Fork Branch (Optional)**
```
Do you have a specific branch in your personal fork you want to work with? (y/n)
```

If yes:
```
What is the branch name?
```

6. **Downstream Repository (for Option 2 only - Upstream with downstream)**
```
What is the downstream repository?
Hint: For OpenShift projects, this is usually openshift/<repo-name>
Example: openshift/kubernetes
Default: openshift/<repo-name>
```

Skip this step for **Option 1** (Upstream only) and **Option 3** (Downstream only).

7. **Downstream Remote Name (for Option 2 and Option 3)**

For **Option 2** (Upstream with downstream):
```
What should the downstream remote be named?
Recommended: "openshift" (for OpenShift projects)
Default: openshift
```

For **Option 3** (Downstream only):
The downstream repository becomes the primary remote alongside origin.
```
What should the downstream remote be named?
Recommended: "openshift" (for OpenShift projects)
Default: openshift
```

Skip this step for **Option 1** (Upstream only).

8. **Local Clone Path**

Use the `<code-base-path>` from step 1 to construct the full clone path.

For **Option 1** (Upstream only) or **Option 2** (Upstream with downstream):
```
Where do you want to clone the repository?
Recommended format: <code-base-path>/github.com/<org>/<repo>
Example: $HOME/go/src/github.com/kubernetes/kubernetes
Default: <code-base-path>/github.com/<upstream-org>/<upstream-repo>
```

For **Option 3** (Downstream only):
```
Where do you want to clone the repository?
Recommended format: <code-base-path>/github.com/<org>/<repo>
Example: $HOME/go/src/github.com/openshift/machine-config-operator
Default: <code-base-path>/github.com/<downstream-org>/<downstream-repo>
```

9. **Check if Local Directory Exists**

If the directory does NOT exist:

For **Option 1** (Upstream only):
- Clone from personal fork: `git clone [email protected]:<personal-fork>.git <local-path>`
- If personal fork branch was specified: `git clone -b <branch> [email protected]:<personal-fork>.git <local-path>`
- Change to the directory: `cd <local-path>`
- Add upstream remote: `git remote add upstream [email protected]:<upstream-org>/<upstream-repo>.git`
- Fetch all remotes: `git fetch --all`

For **Option 2** (Upstream with downstream):
- Clone from personal fork: `git clone [email protected]:<personal-fork>.git <local-path>`
- If personal fork branch was specified: `git clone -b <branch> [email protected]:<personal-fork>.git <local-path>`
- Change to the directory: `cd <local-path>`
- Add upstream remote: `git remote add upstream [email protected]:<upstream-org>/<upstream-repo>.git`
- Add downstream remote: `git remote add <downstream-name> [email protected]:<downstream-repo>.git`
- Fetch all remotes: `git fetch --all`

For **Option 3** (Downstream only):
- Clone from personal fork: `git clone [email protected]:<personal-fork>.git <local-path>`
- If personal fork branch was specified: `git clone -b <branch> [email protected]:<personal-fork>.git <local-path>`
- Change to the directory: `cd <local-path>`
- Add downstream remote: `git remote add <downstream-name> [email protected]:<downstream-org>/<downstream-repo>.git`
- Fetch all remotes: `git fetch --all`

If the directory DOES exist:
- Proceed to "Managing Existing Repository" flow

### Create Branch in Existing Repository (Option 4)

When **Option 4** is selected from step 2, follow this flow to create a branch in the personal fork that syncs with an upstream/downstream branch:

1. **Ask for Existing Local Repository Path**
```
What is the local path to your existing repository?
Example: $HOME/go/src/github.com/kubernetes/kubernetes
```

Validate that the directory exists and is a git repository:
```bash
if [ ! -d "$local_path" ]; then
echo "Error: Directory does not exist"
exit 1
fi

if [ ! -d "$local_path/.git" ]; then
echo "Error: Not a git repository"
exit 1
fi

cd "$local_path"
```

2. **List Available Remotes**

Get all remotes and display them to the user:
```bash
cd "$local_path"
git remote -v
```

If there are multiple remotes (more than just 'origin'), ask the user to select one:
```
Which remote do you want to sync with?
Available remotes: origin, upstream, openshift
```

If there's only one remote, use it automatically.

3. **Ask for Branch Name in Selected Remote**
```
Which branch from <selected-remote> do you want to sync with?
Example: main, master, release-4.18
Default: main
```

4. **Ask for New Branch Name**
```
What should the new branch be named in your personal fork?
Example: feature/my-feature, sync-upstream-main
```

5. **Create and Push Branch**

Implementation:
```bash
cd "$local_path"

# Fetch the selected remote
git fetch "$selected_remote"

# Create new branch from remote branch
git checkout -b "$new_branch_name" "$selected_remote/$remote_branch"

# Push to origin (personal fork)
git push -u origin "$new_branch_name"

echo "✓ Created branch '$new_branch_name' from $selected_remote/$remote_branch"
echo "✓ Pushed to origin/$new_branch_name"
```

6. **Display Final Summary**
```
✓ Branch Creation Complete

Local path: <local-path>
New branch: <new_branch_name>
Synced with: <selected-remote>/<remote_branch>

To verify the setup, run:
git remote -v
```

### Rebase Existing Branch with Remote (Option 5)

When **Option 5** is selected from step 2, follow this flow to rebase an existing branch with the latest code from a remote:

1. **Ask for Existing Local Repository Path**
```
What is the local path to your existing repository?
Example: $HOME/go/src/github.com/kubernetes/kubernetes
```

Validate that the directory exists and is a git repository:
```bash
if [ ! -d "$local_path" ]; then
echo "Error: Directory does not exist"
exit 1
fi

if [ ! -d "$local_path/.git" ]; then
echo "Error: Not a git repository"
exit 1
fi

cd "$local_path"
```

2. **Ask for Branch to Rebase**
```
Which branch do you want to rebase?
Example: feature/my-feature, bugfix/fix-123
```

Validate that the branch exists:
```bash
if ! git rev-parse --verify "$branch_name" >/dev/null 2>&1; then
echo "Error: Branch '$branch_name' does not exist"
exit 1
fi
```

3. **Determine Current Remote Tracking Branch**

Check if the branch has a remote tracking branch:
```bash
cd "$local_path"

# Get the upstream tracking branch for the specified branch
tracking_branch=$(git rev-parse --abbrev-ref "$branch_name@{upstream}" 2>/dev/null)

if [ -n "$tracking_branch" ]; then
echo "Current tracking branch: $tracking_branch"
# Parse remote and branch name
remote_name=$(echo "$tracking_branch" | cut -d'/' -f1)
remote_branch=$(echo "$tracking_branch" | cut -d'/' -f2-)
else
echo "This branch is not tracking any remote branch"
remote_name=""
remote_branch=""
fi
```

4. **List Available Remotes and Ask for Remote**

Get all remotes and display them to the user:
```bash
cd "$local_path"
git remote -v
```

Ask the user which remote to sync with:
```
Which remote do you want to rebase with?
Available remotes: origin, upstream, openshift
Current tracking remote: <remote_name> (if exists)
Default: <remote_name> (if exists, otherwise no default)
```

5. **Ask for Branch Name in Selected Remote**
```
Which branch from <selected-remote> do you want to rebase with?
Current tracking branch: <remote_branch> (if exists)
Example: main, master, release-4.18
Default: <remote_branch> (if exists, otherwise main)
```

6. **Perform Rebase**

Implementation:
```bash
cd "$local_path"

# Check for uncommitted changes
if ! git diff-index --quiet HEAD --; then
echo "Warning: You have uncommitted changes."
read -p "Do you want to stash them? (y/n): " stash_changes
if [ "$stash_changes" = "y" ]; then
git stash save "Auto-stash before rebase"
stashed=true
else
echo "Please commit or stash your changes before rebasing."
exit 1
fi
fi

# Fetch the selected remote
git fetch "$selected_remote"

# Checkout the branch
git checkout "$branch_name"

# Perform rebase
echo "Rebasing $branch_name with $selected_remote/$remote_branch..."
if git rebase "$selected_remote/$remote_branch"; then
echo "✓ Rebase completed successfully"

# Pop stash if we stashed changes
if [ "$stashed" = "true" ]; then
echo "Restoring stashed changes..."
git stash pop
fi

# Ask about force push
read -p "Do you want to force push to origin/$branch_name? (y/n): " force_push
if [ "$force_push" = "y" ]; then
git push -f origin "$branch_name"
echo "✓ Force pushed to origin/$branch_name"
else
echo "You can force push later with: git push -f origin $branch_name"
fi
else
echo "✗ Rebase failed. Please resolve conflicts manually."
echo "After resolving conflicts, run: git rebase --continue"
echo "To abort the rebase, run: git rebase --abort"

# If stashed, remind user
if [ "$stashed" = "true" ]; then
echo "Note: Your changes were stashed. Run 'git stash pop' after completing the rebase."
fi
exit 1
fi
```

7. **Display Final Summary**
```
✓ Rebase Complete

Local path: <local-path>
Branch: <branch_name>
Rebased with: <selected-remote>/<remote_branch>

To verify the rebase, run:
git log --oneline -10
```

### Managing Existing Repository

When the local directory already exists, present options:

```
The directory <local-path> already exists.
What would you like to do?

1. Create a branch synced with upstream
2. Create a branch synced with downstream
3. Sync an existing personal fork branch with upstream
4. Just setup/verify remotes
5. Cancel
```

#### Option 1: Create Branch Synced with Upstream

```
Which upstream branch do you want to sync with?
Default: main
```

Implementation:
```bash
cd <local-path>

# Verify/add upstream remote if not exists
git remote | grep -q "^upstream$" || git remote add upstream [email protected]:<upstream-org>/<upstream-repo>.git

# Fetch upstream
git fetch upstream

# Get upstream branch (default: main)
upstream_branch="${user_input:-main}"

# Create new local branch
read -p "Name for the new local branch: " local_branch
git checkout -b "$local_branch" "upstream/$upstream_branch"

# Push to personal fork
git push -u origin "$local_branch"
```

#### Option 2: Create Branch Synced with Downstream

```
What is the downstream remote name?
Default: openshift
```

```
Which downstream branch do you want to sync with?
Default: master
```

Implementation:
```bash
cd <local-path>

# Verify/add downstream remote if not exists
downstream_name="${user_input:-openshift}"
git remote | grep -q "^$downstream_name$" || {
read -p "Downstream repository (e.g., openshift/kubernetes): " downstream_repo
git remote add "$downstream_name" "[email protected]:$downstream_repo.git"
}

# Fetch downstream
git fetch "$downstream_name"

# Get downstream branch
downstream_branch="${user_input:-master}"

# Create new local branch
read -p "Name for the new local branch: " local_branch
git checkout -b "$local_branch" "$downstream_name/$downstream_branch"

# Push to personal fork
git push -u origin "$local_branch"
```

#### Option 3: Sync Personal Fork Branch with Upstream

```
Which branch in your personal fork do you want to sync?
```

```
Which upstream branch should it sync with?
Default: main
```

Implementation:
```bash
cd <local-path>

# Verify remotes
git remote | grep -q "^upstream$" || git remote add upstream [email protected]:<upstream-org>/<upstream-repo>.git

# Fetch all
git fetch --all

# Checkout the personal fork branch
git checkout "$personal_branch"

# Rebase or merge with upstream
read -p "Sync method (rebase/merge)? Default: rebase: " sync_method
sync_method="${sync_method:-rebase}"

upstream_branch="${user_input:-main}"

if [ "$sync_method" = "rebase" ]; then
git rebase "upstream/$upstream_branch"
else
git merge "upstream/$upstream_branch"
fi

# Push to personal fork (may need force push if rebased)
if [ "$sync_method" = "rebase" ]; then
echo "Rebase complete. You may need to force push: git push -f origin $personal_branch"
read -p "Force push now? (y/n): " force_push
[ "$force_push" = "y" ] && git push -f origin "$personal_branch"
else
git push origin "$personal_branch"
fi
```

#### Option 4: Setup/Verify Remotes

Implementation:
```bash
cd <local-path>

# Show current remotes
echo "Current remotes:"
git remote -v

# Check and add missing remotes
echo ""
echo "Verifying remotes..."

# Check origin
if ! git remote | grep -q "^origin$"; then
read -p "Origin remote not found. Enter origin URL (your personal fork): " origin_url
git remote add origin "$origin_url"
echo "✓ Added origin remote"
else
echo "✓ Origin remote exists"
fi

# Check upstream
if ! git remote | grep -q "^upstream$"; then
read -p "Upstream remote not found. Enter upstream URL: " upstream_url
git remote add upstream "$upstream_url"
echo "✓ Added upstream remote"
else
echo "✓ Upstream remote exists"
fi

# Check downstream (optional)
read -p "Do you need a downstream remote (e.g., OpenShift fork)? (y/n): " need_downstream
if [ "$need_downstream" = "y" ]; then
read -p "Downstream remote name (default: openshift): " downstream_name
downstream_name="${downstream_name:-openshift}"

if ! git remote | grep -q "^$downstream_name$"; then
read -p "Downstream repository (e.g., openshift/kubernetes): " downstream_repo
git remote add "$downstream_name" "[email protected]:$downstream_repo.git"
echo "✓ Added $downstream_name remote"
else
echo "✓ $downstream_name remote exists"
fi
fi

# Fetch all remotes
echo ""
echo "Fetching all remotes..."
git fetch --all
echo "✓ All remotes fetched"

# Show final configuration
echo ""
echo "Final remote configuration:"
git remote -v
```

### Validation Steps

Throughout the process:

1. **Validate GitHub Repository URLs**
- Use `gh repo view <org>/<repo>` to verify repository exists
- Handle both HTTPS and SSH URL formats

2. **Verify GitHub Authentication**
- Check if `gh auth status` shows authenticated
- If not authenticated, prompt: `gh auth login`

3. **Check Git Configuration**
- Verify git user.name and user.email are set
- If not: prompt user to configure with `git config --global user.name` and `git config --global user.email`

4. **Verify SSH Keys**
- When using SSH URLs ([email protected]:...), verify SSH key is configured
- Test with: `ssh -T [email protected]`

5. **Handle Errors Gracefully**
- If fork creation fails (already exists), continue with existing fork
- If clone fails (directory exists), offer to use existing directory
- If remote add fails (already exists), skip or update URL

## Return Value

The command returns a summary of the setup and instructs the user to verify:

```
✓ Repository Setup Complete

Local path: $HOME/go/src/github.com/kubernetes/kubernetes
Current branch: feature-branch

Remotes configured:
origin [email protected]:<username>/kubernetes.git (your fork)
upstream [email protected]:kubernetes/kubernetes.git (upstream)
openshift [email protected]:openshift/kubernetes.git (downstream)

To verify the setup, run:
git remote -v

Next steps:
cd $HOME/go/src/github.com/kubernetes/kubernetes
git fetch --all
git branch -a # View all branches
```

## Examples

### Example 1: Complete Setup for OpenShift Workflow with kubernetes/kubernetes

```
/git:setup
```

Interactive flow:
```
Where do you keep your code repositories? (default: $HOME/go/src)
> $HOME/go/src

✓ Changed to directory $HOME/go/src

Do you want to set up:
1. Upstream repository only
2. Upstream with downstream fork (Red Hat/OpenShift workflow)
3. Downstream repository only (e.g., OpenShift projects without upstream)
4. Create a branch in personal forked repository synced with upstream/downstream branch (for existing repos)
5. Rebase an existing branch with latest code from remote (for existing repos)
> 2

What is the upstream repository URL?
> https://github.com/kubernetes/kubernetes

Do you want to create a personal fork from upstream? (y/n)
> y

Creating fork...
✓ Fork created: <username>/kubernetes

Do you have a specific branch in your personal fork? (y/n)
> n

What is the downstream repository? (default: openshift/kubernetes)
> openshift/kubernetes

What should the downstream remote be named? (default: openshift)
> openshift

Where do you want to clone the repository?
Recommended: $HOME/go/src/github.com/kubernetes/kubernetes
> $HOME/go/src/github.com/kubernetes/kubernetes

Cloning repository...
✓ Cloned to $HOME/go/src/github.com/kubernetes/kubernetes
✓ Added upstream remote
✓ Added openshift remote
✓ Fetched all remotes

✓ Repository Setup Complete

Local path: $HOME/go/src/github.com/kubernetes/kubernetes
Current branch: master

Remotes configured:
origin [email protected]:<username>/kubernetes.git (your fork)
upstream [email protected]:kubernetes/kubernetes.git (upstream)
openshift [email protected]:openshift/kubernetes.git (downstream)

To verify the setup, run:
git remote -v

Next steps:
cd $HOME/go/src/github.com/kubernetes/kubernetes
git fetch --all
git branch -a # View all branches

Setup complete!
```

### Example 2: Upstream Only Setup

```
/git:setup --upstream-only
```

or interactively select option 1.

### Example 2a: Upstream Only Setup with containerd/cgroups

```
/git:setup
```

Interactive flow:
```
Where do you keep your code repositories? (default: $HOME/go/src)
> $HOME/go/src

✓ Changed to directory $HOME/go/src

Do you want to set up:
1. Upstream repository only
2. Upstream with downstream fork (Red Hat/OpenShift workflow)
3. Downstream repository only (e.g., OpenShift projects without upstream)
4. Create a branch in personal forked repository synced with upstream/downstream branch (for existing repos)
5. Rebase an existing branch with latest code from remote (for existing repos)
> 1

What is the upstream repository URL?
> https://github.com/containerd/cgroups

Do you want to create a personal fork from upstream? (y/n)
> y

Creating fork...
✓ Fork created: <username>/cgroups

Do you have a specific branch in your personal fork? (y/n)
> n

Where do you want to clone the repository?
Recommended: $HOME/go/src/github.com/containerd/cgroups
> $HOME/go/src/github.com/containerd/cgroups

Cloning repository...
✓ Cloned to $HOME/go/src/github.com/containerd/cgroups
✓ Added upstream remote
✓ Fetched all remotes

✓ Repository Setup Complete

Local path: $HOME/go/src/github.com/containerd/cgroups
Current branch: main

Remotes configured:
origin [email protected]:<username>/cgroups.git (your fork)
upstream [email protected]:containerd/cgroups.git (upstream)

To verify the setup, run:
git remote -v

Setup complete!
```

### Example 3: Downstream Only Setup (OpenShift Projects)

```
/git:setup --downstream-only
```

Interactive flow:
```
Where do you keep your code repositories? (default: $HOME/go/src)
> $HOME/go/src

✓ Changed to directory $HOME/go/src

Do you want to set up:
1. Upstream repository only
2. Upstream with downstream fork (Red Hat/OpenShift workflow)
3. Downstream repository only (e.g., OpenShift projects without upstream)
4. Create a branch in personal forked repository synced with upstream/downstream branch (for existing repos)
5. Rebase an existing branch with latest code from remote (for existing repos)
> 3

What is the downstream repository URL?
> https://github.com/openshift/machine-config-operator

Do you want to create a personal fork from downstream? (y/n)
> y

Creating fork...
✓ Fork created: <username>/machine-config-operator

Do you have a specific branch in your personal fork? (y/n)
> n

What should the downstream remote be named? (default: openshift)
> openshift

Where do you want to clone the repository?
Recommended: $HOME/go/src/github.com/openshift/machine-config-operator
> $HOME/go/src/github.com/openshift/machine-config-operator

Cloning repository...
✓ Cloned to $HOME/go/src/github.com/openshift/machine-config-operator
✓ Added openshift remote
✓ Fetched all remotes

To verify the setup, run:
git remote -v

Setup complete!
```

### Example 4: Existing Directory - Create Branch from Upstream

```
/git:setup
```

```
The directory $HOME/go/src/github.com/kubernetes/kubernetes already exists.
What would you like to do?
1. Create a branch synced with upstream
2. Create a branch synced with downstream
3. Sync an existing personal fork branch with upstream
4. Just setup/verify remotes
> 1

Which upstream branch do you want to sync with? (default: main)
> main

Name for the new local branch:
> feature/my-new-feature

✓ Created branch 'feature/my-new-feature' tracking upstream/main
✓ Pushed to origin/feature/my-new-feature

To verify the setup, run:
git remote -v
```

### Example 5: Sync Existing Branch with Upstream

```
/git:setup
```

```
The directory $HOME/go/src/github.com/openshift/origin already exists.
What would you like to do?
> 3

Which branch in your personal fork do you want to sync?
> my-feature-branch

Which upstream branch should it sync with? (default: main)
> main

Sync method (rebase/merge)? (default: rebase)
> rebase

✓ Rebased my-feature-branch onto upstream/main
Force push now? (y/n)
> y
✓ Force pushed to origin/my-feature-branch

To verify the setup, run:
git remote -v
```

### Example 6: Setup Remotes for Existing Repository

```
/git:setup
```

```
The directory $HOME/go/src/github.com/openshift/kubernetes already exists.
What would you like to do?
> 4

Current remotes:
origin [email protected]:<username>/kubernetes.git (fetch)
origin [email protected]:<username>/kubernetes.git (push)

Verifying remotes...
✓ Origin remote exists
Upstream remote not found. Enter upstream URL:
> https://github.com/kubernetes/kubernetes
✓ Added upstream remote

Do you need a downstream remote? (y/n)
> y

Downstream remote name (default: openshift):
> openshift

Downstream repository:
> openshift/kubernetes
✓ Added openshift remote

Fetching all remotes...
✓ All remotes fetched

Final remote configuration:
origin [email protected]:<username>/kubernetes.git (fetch)
origin [email protected]:<username>/kubernetes.git (push)
upstream [email protected]:kubernetes/kubernetes.git (fetch)
upstream [email protected]:kubernetes/kubernetes.git (push)
openshift [email protected]:openshift/kubernetes.git (fetch)
openshift [email protected]:openshift/kubernetes.git (push)

To verify the setup, run:
git remote -v
```

### Example 7: Create Branch in Existing Repository Synced with Remote

```
/git:setup
```

```
Where do you keep your code repositories? (default: $HOME/go/src)
> $HOME/go/src

✓ Changed to directory $HOME/go/src

Do you want to set up:
1. Upstream repository only
2. Upstream with downstream fork (Red Hat/OpenShift workflow)
3. Downstream repository only (e.g., OpenShift projects without upstream)
4. Create a branch in personal fork synced with upstream/downstream branch (for existing repos)
> 4

What is the local path to your existing repository?
> $HOME/go/src/github.com/kubernetes/kubernetes

Current remotes:
origin [email protected]:<username>/kubernetes.git (fetch)
origin [email protected]:<username>/kubernetes.git (push)
upstream [email protected]:kubernetes/kubernetes.git (fetch)
upstream [email protected]:kubernetes/kubernetes.git (push)
openshift [email protected]:openshift/kubernetes.git (fetch)
openshift [email protected]:openshift/kubernetes.git (push)

Which remote do you want to sync with?
Available remotes: origin, upstream, openshift
> upstream

Which branch from upstream do you want to sync with? (default: main)
> main

What should the new branch be named in your personal fork?
> sync-upstream-main

✓ Created branch 'sync-upstream-main' from upstream/main
✓ Pushed to origin/sync-upstream-main

✓ Branch Creation Complete

Local path: $HOME/go/src/github.com/kubernetes/kubernetes
New branch: sync-upstream-main
Synced with: upstream/main

To verify the setup, run:
git remote -v
```

### Example 8: Rebase Existing Branch with Remote

```
/git:setup
```

```
Where do you keep your code repositories? (default: $HOME/go/src)
> $HOME/go/src

✓ Changed to directory $HOME/go/src

Do you want to set up:
1. Upstream repository only
2. Upstream with downstream fork (Red Hat/OpenShift workflow)
3. Downstream repository only (e.g., OpenShift projects without upstream)
4. Create a branch in personal forked repository synced with upstream/downstream branch (for existing repos)
5. Rebase an existing branch with latest code from remote (for existing repos)
> 5

What is the local path to your existing repository?
> $HOME/go/src/github.com/kubernetes/kubernetes

Which branch do you want to rebase?
> feature/my-feature

Current remotes:
origin [email protected]:<username>/kubernetes.git (fetch)
origin [email protected]:<username>/kubernetes.git (push)
upstream [email protected]:kubernetes/kubernetes.git (fetch)
upstream [email protected]:kubernetes/kubernetes.git (push)
openshift [email protected]:openshift/kubernetes.git (fetch)
openshift [email protected]:openshift/kubernetes.git (push)

Current tracking branch: upstream/master

Which remote do you want to rebase with?
Available remotes: origin, upstream, openshift
Current tracking remote: upstream
> upstream

Which branch from upstream do you want to rebase with?
Current tracking branch: master
> master

Warning: You have uncommitted changes.
Do you want to stash them? (y/n)
> y

✓ Stashed uncommitted changes
Fetching upstream...
Checking out feature/my-feature...
Rebasing feature/my-feature with upstream/master...
✓ Rebase completed successfully
Restoring stashed changes...
✓ Stashed changes restored

Do you want to force push to origin/feature/my-feature? (y/n)
> y

✓ Force pushed to origin/feature/my-feature

✓ Rebase Complete

Local path: $HOME/go/src/github.com/kubernetes/kubernetes
Branch: feature/my-feature
Rebased with: upstream/master

To verify the rebase, run:
git log --oneline -10
```

## Arguments

- `--upstream-only`: Skip downstream setup, only configure upstream and personal fork
- `--downstream-only`: Skip upstream setup, only configure downstream (OpenShift/Red Hat fork) and personal fork. Useful for projects like openshift/machine-config-operator that don't have an upstream repository.
- `--ssh`: Use SSH URLs for git remotes (default)
- `--https`: Use HTTPS URLs for git remotes instead of SSH
- `--no-fork`: Don't create a fork, only clone upstream/downstream
- `--path <path>`: Specify the local clone path (skips prompt)

## Safety Considerations

1. **Backup Existing Work**: If directory exists and has uncommitted changes, warn user
2. **Verify Write Permissions**: Check if user has write access to personal fork before cloning
3. **SSH Key Check**: Verify SSH keys are configured before using SSH URLs
4. **Git Configuration**: Ensure user.name and user.email are configured
5. **Remote Conflicts**: If remote names conflict, ask user to choose different names
6. **Branch Conflicts**: If branch name exists, offer to use different name or force update

## Prerequisites

- Git installed and configured
- GitHub CLI (`gh`) installed and authenticated
- SSH keys configured for GitHub (if using SSH URLs)
- Write access to create forks (for fork creation)

## Notes

- This command is compatible with the `/openshift:rebase` workflow which requires three remotes: origin, openshift, and upstream
- Default behavior uses SSH URLs ([email protected]:...) for better authentication with SSH keys
- The recommended directory structure follows Go conventions: `$HOME/go/src/github.com/<org>/<repo>`
- For OpenShift projects, the downstream remote name "openshift" is recommended for compatibility with rebase scripts
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Fix markdown linting issues to improve maintainability. The file has numerous markdown formatting issues flagged by markdownlint:

  • Lines 10, 33, 45, 90, 99, 108, 128, 137, 148, 157, 164, 173, 180, 185, 190, 202, 210, 223, 231, 272, 301, 309, 316, 341, 357, 378, 421, 429, 494, 509, 522, 550, 555, 587, 591, 707, 719, 743, 748, 813, 821, 826, 878, 883, 929, 933, 957, 961, 986, 990, 1032, 1036, 1085, 1089: Missing language specifier in fenced code blocks. Most should be bash or text.
  • Lines 996–997: Hard tabs in git output examples; use spaces instead.
  • Lines 707, 1183: Bare URLs should be wrapped in backticks or proper Markdown link format.

Apply this diff to add language specifiers to bash code blocks (example for a representative sample):

- ```
+ ```bash

For the git remote output examples (lines 996–997), replace hard tabs with spaces:

- origin	[email protected]:<username>/kubernetes.git (fetch)
+ origin    [email protected]:<username>/kubernetes.git (fetch)

Wrap bare URLs in backticks (example at line 707):

- Test with: ssh -T [email protected]
+ Test with: `ssh -T [email protected]`
🧰 Tools
🪛 LanguageTool

[style] ~122-~122: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...ided, skip to downstream-only flow. If Option 4 is selected, skip to "Crea...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)


[style] ~123-~123: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...Branch in Existing Repository" flow. If Option 5 is selected, skip to "Reba...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)


[grammar] ~811-~811: Use a hyphen to join words.
Context: ...p complete! ### Example 2: Upstream Only Setup /git:setup --upstream-on...

(QB_NEW_EN_HYPHEN)

🪛 markdownlint-cli2 (0.18.1)

10-10: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


33-33: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


45-45: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


90-90: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


99-99: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


108-108: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


128-128: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


137-137: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


148-148: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


157-157: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


164-164: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


173-173: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


180-180: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


185-185: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


190-190: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


202-202: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


210-210: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


223-223: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


231-231: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


272-272: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


301-301: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


309-309: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


316-316: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


341-341: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


357-357: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


378-378: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


421-421: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


429-429: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


494-494: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


509-509: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


522-522: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


550-550: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


555-555: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


587-587: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


591-591: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


707-707: Bare URL used

(MD034, no-bare-urls)


719-719: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


743-743: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


748-748: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


813-813: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


821-821: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


826-826: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


878-878: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


883-883: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


929-929: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


933-933: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


957-957: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


961-961: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


986-986: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


990-990: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


996-996: Hard tabs
Column: 7

(MD010, no-hard-tabs)


997-997: Hard tabs
Column: 7

(MD010, no-hard-tabs)


1032-1032: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


1036-1036: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


1085-1085: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


1089-1089: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


1183-1183: Bare URL used

(MD034, no-bare-urls)

🤖 Prompt for AI Agents
plugins/git/commands/setup.md (lines 1-1185): Several fenced code blocks are
missing language specifiers (see lines
10,33,45,90,99,108,128,137,148,157,164,173,180,185,190,202,210,223,231,272,301,309,316,341,357,378,421,429,494,509,522,550,555,587,591,707,719,743,748,813,821,826,878,883,929,933,957,961,986,990,1032,1036,1085,1089)
— add the appropriate language after the opening triple backticks (mostly bash
or text); replace hard tabs in the git remote output example at lines 996–997
with spaces; wrap bare URLs at lines 707 and 1183 in backticks or convert to
proper Markdown links; after changes run markdownlint to verify no remaining
lint errors and commit the fixes.

```

If yes:
- Use GitHub CLI to create fork: `gh repo fork <upstream-org>/<upstream-repo> --clone=false`

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if the user doesn't already have gh installed?

I'm assuming that Claude will automatically try to download and install it with the user's permission but given that this command is git:setup I'd recommend more of a purist approach and have it only execute git commands without the gh wrapper.

This has the added benefit of allowing this skill to work with Gitlab (and other git hosts).

Available remotes: origin, upstream, openshift
```

If there's only one remote, use it automatically.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
If there's only one remote, use it automatically.

I'd vote to drop this instruction only out of an abundance of caution. In terms of doing what's least surprising, I think letting the users pick a remote even if there's only one is the most expected workflow. Especially in the case of existing repositories, default to selecting whatever remote is configured could be an undesirable user experience.

1. Create a branch synced with upstream
2. Create a branch synced with downstream
3. Sync an existing personal fork branch with upstream
4. Just setup/verify remotes

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
4. Just setup/verify remotes
4. Only setup and/or verify remotes

## Prerequisites

- Git installed and configured
- GitHub CLI (`gh`) installed and authenticated

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm being pedantic but this requirement makes this more like /github:setup than git:setup.

@openshift-ci openshift-ci bot removed the lgtm Indicates that a PR is ready to be merged. label Nov 6, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. ok-to-test Indicates a non-member PR verified by an org member that is safe to test.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants