gitbetter.git

  1import shlex
  2import subprocess
  3from contextlib import contextmanager
  4
  5
  6class Git:
  7    def __init__(self, capture_stdout: bool = False):
  8        """If `capture_stdout` is `True`, all functions will return their generated `stdout` as a string.
  9        Otherwise, the functions return the call's exit code."""
 10        self.capture_stdout = capture_stdout
 11
 12    @contextmanager
 13    def capture_output(self):
 14        self.capture_stdout = True
 15        yield self
 16        self.capture_stdout = False
 17
 18    @property
 19    def capture_stdout(self) -> bool:
 20        """If `True`, member functions will return the generated `stdout` as a string,
 21        otherwise they return the command's exit code."""
 22        return self._capture_stdout
 23
 24    @capture_stdout.setter
 25    def capture_stdout(self, should_capture: bool):
 26        self._capture_stdout = should_capture
 27
 28    def _run(self, args: list[str]) -> str | int:
 29        if self._capture_stdout:
 30            return subprocess.run(args, stdout=subprocess.PIPE, text=True).stdout
 31        else:
 32            return subprocess.run(args).returncode
 33
 34    def execute(self, command: str) -> str | int:
 35        """Execute git command.
 36
 37        Equivalent to executing `git {command}` in the shell."""
 38        args = ["git"] + shlex.split(command)
 39        return self._run(args)
 40
 41    def new_repo(self) -> str | int:
 42        """Executes `git init -b main`."""
 43        return self.execute("init -b main")
 44
 45    def loggy(self) -> str | int:
 46        """Equivalent to `git log --oneline --name-only --abbrev-commit --graph`."""
 47        return self.execute("log --oneline --name-only --abbrev-commit --graph")
 48
 49    def status(self) -> str | int:
 50        """Execute `git status`."""
 51        return self.execute("status")
 52
 53    # ======================================Staging/Committing======================================
 54    def commit(self, args: str) -> str | int:
 55        """>>> git commit {args}"""
 56        return self.execute(f"commit {args}")
 57
 58    def add(self, files: list[str] | None = None) -> str | int:
 59        """Stage a list of files.
 60
 61        If no files are given (`files=None`), all files will be staged."""
 62        if not files:
 63            return self.execute("add .")
 64        else:
 65            files = " ".join(f'"{file}"' for file in files)  # type: ignore
 66            return self.execute(f"add {files}")
 67
 68    def commit_files(self, files: list[str], message: str) -> str | int:
 69        """Stage and commit a list of files with commit message `message`."""
 70        return self.add(files) + self.commit(f'-m "{message}"')  # type: ignore
 71
 72    def initcommit(self) -> str | int:
 73        """Equivalent to
 74        >>> git add .
 75        >>> git commit -m "Initial commit" """
 76        return self.add() + self.commit('-m "Initial commit"')  # type: ignore
 77
 78    def amend(self, files: list[str] | None = None) -> str | int:
 79        """Stage and commit changes to the previous commit.
 80
 81        If `files` is `None`, all files will be staged.
 82
 83        Equivalent to:
 84        >>> git add {files}
 85        >>> git commit --amend --no-edit
 86        """
 87        return self.add(files) + self.commit("--amend --no-edit")  # type: ignore
 88
 89    def tag(self, args: str = "") -> str | int:
 90        """Execute the `tag` command with `args`.
 91
 92        e.g.
 93
 94        `self.tag("--sort=-committerdate")`
 95
 96        will list all the tags for this repository in descending commit date."""
 97        return self.execute(f"tag {args}")
 98
 99    # ==========================================Push/Pull==========================================
100    def add_remote_url(self, url: str, name: str = "origin") -> str | int:
101        """Add remote url to repo."""
102        return self.execute(f"remote add {name} {url}")
103
104    def push(self, args: str = "") -> str | int:
105        """Equivalent to `git push {args}`."""
106        return self.execute(f"push {args}")
107
108    def pull(self, args: str = "") -> str | int:
109        """Equivalent to `git pull {args}`."""
110        return self.execute(f"pull {args}")
111
112    def push_new_branch(self, branch: str) -> str | int:
113        """Push a new branch to origin with tracking.
114
115        Equivalent to `git push -u origin {branch}`."""
116        return self.push(f"-u origin {branch}")
117
118    def pull_branch(self, branch: str) -> str | int:
119        """Pull `branch` from origin."""
120        return self.pull(f"origin {branch}")
121
122    # ============================================Checkout/Branches============================================
123    def branch(self, args: str) -> str | int:
124        """Equivalent to `git branch {args}`."""
125        return self.execute(f"branch {args}")
126
127    def list_branches(self) -> str | int:
128        """Print a list of branches."""
129        return self.branch("-vva")
130
131    def checkout(self, args: str) -> str | int:
132        """Equivalent to `git checkout {args}`."""
133        return self.execute(f"checkout {args}")
134
135    def switch_branch(self, branch_name: str) -> str | int:
136        """Switch to the branch specified by `branch_name`.
137
138        Equivalent to `git checkout {branch_name}`."""
139        return self.checkout(branch_name)
140
141    def create_new_branch(self, branch_name: str) -> str | int:
142        """Create and switch to a new branch named with `branch_name`.
143
144        Equivalent to `git checkout -b {branch_name} --track`."""
145        return self.checkout(f"-b {branch_name} --track")
146
147    def delete_branch(self, branch_name: str, local_only: bool = True) -> str | int:
148        """Delete `branch_name` from repo.
149
150        #### :params:
151
152        `local_only`: Only delete the local copy of `branch`, otherwise also delete the remote branch on origin and remote-tracking branch."""
153        output = self.branch(f"--delete {branch_name}")
154        if not local_only:
155            return output + self.push(f"origin --delete {branch_name}")  # type:ignore
156        return output
157
158    def undo(self) -> str | int:
159        """Undo uncommitted changes.
160
161        Equivalent to `git checkout .`."""
162        return self.checkout(".")
163
164    def merge(self, branch_name: str) -> str | int:
165        """Merge branch `branch_name` with currently active branch."""
166        return self.execute(f"merge {branch_name}")
167
168    # ===============================Requires GitHub CLI to be installed and configured===============================
169
170    def create_remote(self, name: str, public: bool = False) -> str | int:
171        """Uses GitHub CLI (must be installed and configured) to create a remote GitHub repo.
172
173        #### :params:
174
175        `name`: The name for the repo.
176
177        `public`: Set to `True` to create the repo as public, otherwise it'll be created as private."""
178        visibility = "--public" if public else "--private"
179        return self._run(["gh", "repo", "create", name, visibility])
180
181    def create_remote_from_cwd(self, public: bool = False) -> str | int:
182        """Use GitHub CLI (must be installed and configured) to create a remote GitHub repo from
183        the current working directory repo and add its url as this repo's remote origin.
184
185        #### :params:
186
187        `public`: Create the GitHub repo as a public repo, default is to create it as private."""
188        visibility = "public" if public else "private"
189        return self._run(
190            ["gh", "repo", "create", "--source", ".", f"--{visibility}", "--push"]
191        )
192
193    def _change_visibility(self, owner: str, name: str, visibility: str) -> str | int:
194        return self._run(
195            ["gh", "repo", "edit", f"{owner}/{name}", "--visibility", visibility]
196        )
197
198    def make_private(self, owner: str, name: str) -> str | int:
199        """Uses GitHub CLI (must be installed and configured) to set the repo's visibility to private.
200
201        #### :params:
202
203        `owner`: The repo owner.
204
205        `name`: The name of the repo to edit."""
206        return self._change_visibility(owner, name, "private")
207
208    def make_public(self, owner: str, name: str) -> str | int:
209        """Uses GitHub CLI (must be installed and configured) to set the repo's visibility to public.
210
211        #### :params:
212
213        `owner`: The repo owner.
214
215        `name`: The name of the repo to edit."""
216        return self._change_visibility(owner, name, "public")
217
218    def delete_remote(self, owner: str, name: str) -> str | int:
219        """Uses GitHub CLI (must be isntalled and configured) to delete the remote for this repo.
220
221        #### :params:
222
223        `owner`: The repo owner.
224
225        `name`: The name of the remote repo to delete."""
226        return self._run(["gh", "repo", "delete", f"{owner}/{name}", "--yes"])
class Git:
  7class Git:
  8    def __init__(self, capture_stdout: bool = False):
  9        """If `capture_stdout` is `True`, all functions will return their generated `stdout` as a string.
 10        Otherwise, the functions return the call's exit code."""
 11        self.capture_stdout = capture_stdout
 12
 13    @contextmanager
 14    def capture_output(self):
 15        self.capture_stdout = True
 16        yield self
 17        self.capture_stdout = False
 18
 19    @property
 20    def capture_stdout(self) -> bool:
 21        """If `True`, member functions will return the generated `stdout` as a string,
 22        otherwise they return the command's exit code."""
 23        return self._capture_stdout
 24
 25    @capture_stdout.setter
 26    def capture_stdout(self, should_capture: bool):
 27        self._capture_stdout = should_capture
 28
 29    def _run(self, args: list[str]) -> str | int:
 30        if self._capture_stdout:
 31            return subprocess.run(args, stdout=subprocess.PIPE, text=True).stdout
 32        else:
 33            return subprocess.run(args).returncode
 34
 35    def execute(self, command: str) -> str | int:
 36        """Execute git command.
 37
 38        Equivalent to executing `git {command}` in the shell."""
 39        args = ["git"] + shlex.split(command)
 40        return self._run(args)
 41
 42    def new_repo(self) -> str | int:
 43        """Executes `git init -b main`."""
 44        return self.execute("init -b main")
 45
 46    def loggy(self) -> str | int:
 47        """Equivalent to `git log --oneline --name-only --abbrev-commit --graph`."""
 48        return self.execute("log --oneline --name-only --abbrev-commit --graph")
 49
 50    def status(self) -> str | int:
 51        """Execute `git status`."""
 52        return self.execute("status")
 53
 54    # ======================================Staging/Committing======================================
 55    def commit(self, args: str) -> str | int:
 56        """>>> git commit {args}"""
 57        return self.execute(f"commit {args}")
 58
 59    def add(self, files: list[str] | None = None) -> str | int:
 60        """Stage a list of files.
 61
 62        If no files are given (`files=None`), all files will be staged."""
 63        if not files:
 64            return self.execute("add .")
 65        else:
 66            files = " ".join(f'"{file}"' for file in files)  # type: ignore
 67            return self.execute(f"add {files}")
 68
 69    def commit_files(self, files: list[str], message: str) -> str | int:
 70        """Stage and commit a list of files with commit message `message`."""
 71        return self.add(files) + self.commit(f'-m "{message}"')  # type: ignore
 72
 73    def initcommit(self) -> str | int:
 74        """Equivalent to
 75        >>> git add .
 76        >>> git commit -m "Initial commit" """
 77        return self.add() + self.commit('-m "Initial commit"')  # type: ignore
 78
 79    def amend(self, files: list[str] | None = None) -> str | int:
 80        """Stage and commit changes to the previous commit.
 81
 82        If `files` is `None`, all files will be staged.
 83
 84        Equivalent to:
 85        >>> git add {files}
 86        >>> git commit --amend --no-edit
 87        """
 88        return self.add(files) + self.commit("--amend --no-edit")  # type: ignore
 89
 90    def tag(self, args: str = "") -> str | int:
 91        """Execute the `tag` command with `args`.
 92
 93        e.g.
 94
 95        `self.tag("--sort=-committerdate")`
 96
 97        will list all the tags for this repository in descending commit date."""
 98        return self.execute(f"tag {args}")
 99
100    # ==========================================Push/Pull==========================================
101    def add_remote_url(self, url: str, name: str = "origin") -> str | int:
102        """Add remote url to repo."""
103        return self.execute(f"remote add {name} {url}")
104
105    def push(self, args: str = "") -> str | int:
106        """Equivalent to `git push {args}`."""
107        return self.execute(f"push {args}")
108
109    def pull(self, args: str = "") -> str | int:
110        """Equivalent to `git pull {args}`."""
111        return self.execute(f"pull {args}")
112
113    def push_new_branch(self, branch: str) -> str | int:
114        """Push a new branch to origin with tracking.
115
116        Equivalent to `git push -u origin {branch}`."""
117        return self.push(f"-u origin {branch}")
118
119    def pull_branch(self, branch: str) -> str | int:
120        """Pull `branch` from origin."""
121        return self.pull(f"origin {branch}")
122
123    # ============================================Checkout/Branches============================================
124    def branch(self, args: str) -> str | int:
125        """Equivalent to `git branch {args}`."""
126        return self.execute(f"branch {args}")
127
128    def list_branches(self) -> str | int:
129        """Print a list of branches."""
130        return self.branch("-vva")
131
132    def checkout(self, args: str) -> str | int:
133        """Equivalent to `git checkout {args}`."""
134        return self.execute(f"checkout {args}")
135
136    def switch_branch(self, branch_name: str) -> str | int:
137        """Switch to the branch specified by `branch_name`.
138
139        Equivalent to `git checkout {branch_name}`."""
140        return self.checkout(branch_name)
141
142    def create_new_branch(self, branch_name: str) -> str | int:
143        """Create and switch to a new branch named with `branch_name`.
144
145        Equivalent to `git checkout -b {branch_name} --track`."""
146        return self.checkout(f"-b {branch_name} --track")
147
148    def delete_branch(self, branch_name: str, local_only: bool = True) -> str | int:
149        """Delete `branch_name` from repo.
150
151        #### :params:
152
153        `local_only`: Only delete the local copy of `branch`, otherwise also delete the remote branch on origin and remote-tracking branch."""
154        output = self.branch(f"--delete {branch_name}")
155        if not local_only:
156            return output + self.push(f"origin --delete {branch_name}")  # type:ignore
157        return output
158
159    def undo(self) -> str | int:
160        """Undo uncommitted changes.
161
162        Equivalent to `git checkout .`."""
163        return self.checkout(".")
164
165    def merge(self, branch_name: str) -> str | int:
166        """Merge branch `branch_name` with currently active branch."""
167        return self.execute(f"merge {branch_name}")
168
169    # ===============================Requires GitHub CLI to be installed and configured===============================
170
171    def create_remote(self, name: str, public: bool = False) -> str | int:
172        """Uses GitHub CLI (must be installed and configured) to create a remote GitHub repo.
173
174        #### :params:
175
176        `name`: The name for the repo.
177
178        `public`: Set to `True` to create the repo as public, otherwise it'll be created as private."""
179        visibility = "--public" if public else "--private"
180        return self._run(["gh", "repo", "create", name, visibility])
181
182    def create_remote_from_cwd(self, public: bool = False) -> str | int:
183        """Use GitHub CLI (must be installed and configured) to create a remote GitHub repo from
184        the current working directory repo and add its url as this repo's remote origin.
185
186        #### :params:
187
188        `public`: Create the GitHub repo as a public repo, default is to create it as private."""
189        visibility = "public" if public else "private"
190        return self._run(
191            ["gh", "repo", "create", "--source", ".", f"--{visibility}", "--push"]
192        )
193
194    def _change_visibility(self, owner: str, name: str, visibility: str) -> str | int:
195        return self._run(
196            ["gh", "repo", "edit", f"{owner}/{name}", "--visibility", visibility]
197        )
198
199    def make_private(self, owner: str, name: str) -> str | int:
200        """Uses GitHub CLI (must be installed and configured) to set the repo's visibility to private.
201
202        #### :params:
203
204        `owner`: The repo owner.
205
206        `name`: The name of the repo to edit."""
207        return self._change_visibility(owner, name, "private")
208
209    def make_public(self, owner: str, name: str) -> str | int:
210        """Uses GitHub CLI (must be installed and configured) to set the repo's visibility to public.
211
212        #### :params:
213
214        `owner`: The repo owner.
215
216        `name`: The name of the repo to edit."""
217        return self._change_visibility(owner, name, "public")
218
219    def delete_remote(self, owner: str, name: str) -> str | int:
220        """Uses GitHub CLI (must be isntalled and configured) to delete the remote for this repo.
221
222        #### :params:
223
224        `owner`: The repo owner.
225
226        `name`: The name of the remote repo to delete."""
227        return self._run(["gh", "repo", "delete", f"{owner}/{name}", "--yes"])
Git(capture_stdout: bool = False)
 8    def __init__(self, capture_stdout: bool = False):
 9        """If `capture_stdout` is `True`, all functions will return their generated `stdout` as a string.
10        Otherwise, the functions return the call's exit code."""
11        self.capture_stdout = capture_stdout

If capture_stdout is True, all functions will return their generated stdout as a string. Otherwise, the functions return the call's exit code.

capture_stdout: bool

If True, member functions will return the generated stdout as a string, otherwise they return the command's exit code.

@contextmanager
def capture_output(self):
13    @contextmanager
14    def capture_output(self):
15        self.capture_stdout = True
16        yield self
17        self.capture_stdout = False
def execute(self, command: str) -> str | int:
35    def execute(self, command: str) -> str | int:
36        """Execute git command.
37
38        Equivalent to executing `git {command}` in the shell."""
39        args = ["git"] + shlex.split(command)
40        return self._run(args)

Execute git command.

Equivalent to executing git {command} in the shell.

def new_repo(self) -> str | int:
42    def new_repo(self) -> str | int:
43        """Executes `git init -b main`."""
44        return self.execute("init -b main")

Executes git init -b main.

def loggy(self) -> str | int:
46    def loggy(self) -> str | int:
47        """Equivalent to `git log --oneline --name-only --abbrev-commit --graph`."""
48        return self.execute("log --oneline --name-only --abbrev-commit --graph")

Equivalent to git log --oneline --name-only --abbrev-commit --graph.

def status(self) -> str | int:
50    def status(self) -> str | int:
51        """Execute `git status`."""
52        return self.execute("status")

Execute git status.

def commit(self, args: str) -> str | int:
55    def commit(self, args: str) -> str | int:
56        """>>> git commit {args}"""
57        return self.execute(f"commit {args}")
>>> git commit {args}
def add(self, files: list[str] | None = None) -> str | int:
59    def add(self, files: list[str] | None = None) -> str | int:
60        """Stage a list of files.
61
62        If no files are given (`files=None`), all files will be staged."""
63        if not files:
64            return self.execute("add .")
65        else:
66            files = " ".join(f'"{file}"' for file in files)  # type: ignore
67            return self.execute(f"add {files}")

Stage a list of files.

If no files are given (files=None), all files will be staged.

def commit_files(self, files: list[str], message: str) -> str | int:
69    def commit_files(self, files: list[str], message: str) -> str | int:
70        """Stage and commit a list of files with commit message `message`."""
71        return self.add(files) + self.commit(f'-m "{message}"')  # type: ignore

Stage and commit a list of files with commit message message.

def initcommit(self) -> str | int:
73    def initcommit(self) -> str | int:
74        """Equivalent to
75        >>> git add .
76        >>> git commit -m "Initial commit" """
77        return self.add() + self.commit('-m "Initial commit"')  # type: ignore

Equivalent to

>>> git add .
>>> git commit -m "Initial commit"
def amend(self, files: list[str] | None = None) -> str | int:
79    def amend(self, files: list[str] | None = None) -> str | int:
80        """Stage and commit changes to the previous commit.
81
82        If `files` is `None`, all files will be staged.
83
84        Equivalent to:
85        >>> git add {files}
86        >>> git commit --amend --no-edit
87        """
88        return self.add(files) + self.commit("--amend --no-edit")  # type: ignore

Stage and commit changes to the previous commit.

If files is None, all files will be staged.

Equivalent to:

>>> git add {files}
>>> git commit --amend --no-edit
def tag(self, args: str = '') -> str | int:
90    def tag(self, args: str = "") -> str | int:
91        """Execute the `tag` command with `args`.
92
93        e.g.
94
95        `self.tag("--sort=-committerdate")`
96
97        will list all the tags for this repository in descending commit date."""
98        return self.execute(f"tag {args}")

Execute the tag command with args.

e.g.

self.tag("--sort=-committerdate")

will list all the tags for this repository in descending commit date.

def add_remote_url(self, url: str, name: str = 'origin') -> str | int:
101    def add_remote_url(self, url: str, name: str = "origin") -> str | int:
102        """Add remote url to repo."""
103        return self.execute(f"remote add {name} {url}")

Add remote url to repo.

def push(self, args: str = '') -> str | int:
105    def push(self, args: str = "") -> str | int:
106        """Equivalent to `git push {args}`."""
107        return self.execute(f"push {args}")

Equivalent to git push {args}.

def pull(self, args: str = '') -> str | int:
109    def pull(self, args: str = "") -> str | int:
110        """Equivalent to `git pull {args}`."""
111        return self.execute(f"pull {args}")

Equivalent to git pull {args}.

def push_new_branch(self, branch: str) -> str | int:
113    def push_new_branch(self, branch: str) -> str | int:
114        """Push a new branch to origin with tracking.
115
116        Equivalent to `git push -u origin {branch}`."""
117        return self.push(f"-u origin {branch}")

Push a new branch to origin with tracking.

Equivalent to git push -u origin {branch}.

def pull_branch(self, branch: str) -> str | int:
119    def pull_branch(self, branch: str) -> str | int:
120        """Pull `branch` from origin."""
121        return self.pull(f"origin {branch}")

Pull branch from origin.

def branch(self, args: str) -> str | int:
124    def branch(self, args: str) -> str | int:
125        """Equivalent to `git branch {args}`."""
126        return self.execute(f"branch {args}")

Equivalent to git branch {args}.

def list_branches(self) -> str | int:
128    def list_branches(self) -> str | int:
129        """Print a list of branches."""
130        return self.branch("-vva")

Print a list of branches.

def checkout(self, args: str) -> str | int:
132    def checkout(self, args: str) -> str | int:
133        """Equivalent to `git checkout {args}`."""
134        return self.execute(f"checkout {args}")

Equivalent to git checkout {args}.

def switch_branch(self, branch_name: str) -> str | int:
136    def switch_branch(self, branch_name: str) -> str | int:
137        """Switch to the branch specified by `branch_name`.
138
139        Equivalent to `git checkout {branch_name}`."""
140        return self.checkout(branch_name)

Switch to the branch specified by branch_name.

Equivalent to git checkout {branch_name}.

def create_new_branch(self, branch_name: str) -> str | int:
142    def create_new_branch(self, branch_name: str) -> str | int:
143        """Create and switch to a new branch named with `branch_name`.
144
145        Equivalent to `git checkout -b {branch_name} --track`."""
146        return self.checkout(f"-b {branch_name} --track")

Create and switch to a new branch named with branch_name.

Equivalent to git checkout -b {branch_name} --track.

def delete_branch(self, branch_name: str, local_only: bool = True) -> str | int:
148    def delete_branch(self, branch_name: str, local_only: bool = True) -> str | int:
149        """Delete `branch_name` from repo.
150
151        #### :params:
152
153        `local_only`: Only delete the local copy of `branch`, otherwise also delete the remote branch on origin and remote-tracking branch."""
154        output = self.branch(f"--delete {branch_name}")
155        if not local_only:
156            return output + self.push(f"origin --delete {branch_name}")  # type:ignore
157        return output

Delete branch_name from repo.

:params:

local_only: Only delete the local copy of branch, otherwise also delete the remote branch on origin and remote-tracking branch.

def undo(self) -> str | int:
159    def undo(self) -> str | int:
160        """Undo uncommitted changes.
161
162        Equivalent to `git checkout .`."""
163        return self.checkout(".")

Undo uncommitted changes.

Equivalent to git checkout ..

def merge(self, branch_name: str) -> str | int:
165    def merge(self, branch_name: str) -> str | int:
166        """Merge branch `branch_name` with currently active branch."""
167        return self.execute(f"merge {branch_name}")

Merge branch branch_name with currently active branch.

def create_remote(self, name: str, public: bool = False) -> str | int:
171    def create_remote(self, name: str, public: bool = False) -> str | int:
172        """Uses GitHub CLI (must be installed and configured) to create a remote GitHub repo.
173
174        #### :params:
175
176        `name`: The name for the repo.
177
178        `public`: Set to `True` to create the repo as public, otherwise it'll be created as private."""
179        visibility = "--public" if public else "--private"
180        return self._run(["gh", "repo", "create", name, visibility])

Uses GitHub CLI (must be installed and configured) to create a remote GitHub repo.

:params:

name: The name for the repo.

public: Set to True to create the repo as public, otherwise it'll be created as private.

def create_remote_from_cwd(self, public: bool = False) -> str | int:
182    def create_remote_from_cwd(self, public: bool = False) -> str | int:
183        """Use GitHub CLI (must be installed and configured) to create a remote GitHub repo from
184        the current working directory repo and add its url as this repo's remote origin.
185
186        #### :params:
187
188        `public`: Create the GitHub repo as a public repo, default is to create it as private."""
189        visibility = "public" if public else "private"
190        return self._run(
191            ["gh", "repo", "create", "--source", ".", f"--{visibility}", "--push"]
192        )

Use GitHub CLI (must be installed and configured) to create a remote GitHub repo from the current working directory repo and add its url as this repo's remote origin.

:params:

public: Create the GitHub repo as a public repo, default is to create it as private.

def make_private(self, owner: str, name: str) -> str | int:
199    def make_private(self, owner: str, name: str) -> str | int:
200        """Uses GitHub CLI (must be installed and configured) to set the repo's visibility to private.
201
202        #### :params:
203
204        `owner`: The repo owner.
205
206        `name`: The name of the repo to edit."""
207        return self._change_visibility(owner, name, "private")

Uses GitHub CLI (must be installed and configured) to set the repo's visibility to private.

:params:

owner: The repo owner.

name: The name of the repo to edit.

def make_public(self, owner: str, name: str) -> str | int:
209    def make_public(self, owner: str, name: str) -> str | int:
210        """Uses GitHub CLI (must be installed and configured) to set the repo's visibility to public.
211
212        #### :params:
213
214        `owner`: The repo owner.
215
216        `name`: The name of the repo to edit."""
217        return self._change_visibility(owner, name, "public")

Uses GitHub CLI (must be installed and configured) to set the repo's visibility to public.

:params:

owner: The repo owner.

name: The name of the repo to edit.

def delete_remote(self, owner: str, name: str) -> str | int:
219    def delete_remote(self, owner: str, name: str) -> str | int:
220        """Uses GitHub CLI (must be isntalled and configured) to delete the remote for this repo.
221
222        #### :params:
223
224        `owner`: The repo owner.
225
226        `name`: The name of the remote repo to delete."""
227        return self._run(["gh", "repo", "delete", f"{owner}/{name}", "--yes"])

Uses GitHub CLI (must be isntalled and configured) to delete the remote for this repo.

:params:

owner: The repo owner.

name: The name of the remote repo to delete.