Repository: VirtusLab/git-machete
Pull request #1036 (2023-08-27 17:11:45)

Release v3.8.1


Patch:
diff --git a/.circleci/config.yml b/.circleci/config.yml
index 40b92b1..63794f2 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -179,7 +179,8 @@ jobs:
       - checkout
       - run: pip install tox
       # We don't collect coverage on Windows as it massively extends execution time for some reason.
-      - run: tox -e testenv -- -vv
+      # See https://github.com/tox-dev/tox/issues/3092 for why `py` and not `testenv`.
+      - run: tox -e py -- -vv
       - store_test_results:
           path: test-results/
 
diff --git a/PACKAGES.md b/PACKAGES.md
index 29fd71f..d442ffb 100644
--- a/PACKAGES.md
+++ b/PACKAGES.md
@@ -11,7 +11,7 @@ the **edge-most** channel that corresponds to the **released** versions of git-m
 | Conda Forge                                         | ![Conda package](https://img.shields.io/conda/vn/conda-forge/git-machete.svg?label=)                            | [**Conda package**](https://anaconda.org/conda-forge/git-machete)                                                                                                                                                         | [Recipe](https://github.com/conda-forge/git-machete-feedstock/blob/main/recipe/meta.yaml) (points to PyPI)                                 | [PRs](https://github.com/conda-forge/git-machete-feedstock/pulls?q=is%3Apr)  | Feedstock maintainers, incl. [@asford (Alex Ford)](https://github.com/asford) and ourselves | Feedstock GitHub bot                                                                                                                                                                  | -                                     | ![Conda downloads](https://img.shields.io/conda/dn/conda-forge/git-machete.svg)                                                                                                                                                                                                                                       |
 | Gentoo                                              | ![Gentoo package](https://repology.org/badge/version-for-repo/gentoo/git-machete.svg?header=)                   | [**Gentoo package**](https://packages.gentoo.org/packages/dev-vcs/git-machete)                                                                                                                                            | [ebuild](https://gitweb.gentoo.org/repo/gentoo.git/tree/dev-vcs/git-machete) (points to GitHub)                                            |                                                                              | Gentoo package maintainers                                                                  | Gentoo package maintainers                                                                                                                                                            | bash, fish, zsh                       |                                                                                                                                                                                                                                                                                                                       |
 | GitHub Releases (rpm)                               | ![GitHub latest release](https://img.shields.io/github/v/release/VirtusLab/git-machete?label=)                  | [**GitHub releases**](https://github.com/VirtusLab/git-machete/releases)                                                                                                                                                  |                                                                                                                                            |                                                                              | Ourselves                                                                                   | Our CI on `master` builds                                                                                                                                                             | -                                     | ![GitHub releases total downloads](https://img.shields.io/github/downloads/VirtusLab/git-machete/total)[^2]                                                                                                                                                                                                           |
-| Homebrew                                            | ![homebrew formula](https://img.shields.io/homebrew/v/git-machete.svg?label=)                                   | [**Formula**](https://formulae.brew.sh/formula/git-machete)                                                                                                                                                               | [Formula source](https://github.com/Homebrew/homebrew-core/blob/master/Formula/git-machete.rb) (points to PyPI)                            | [PRs](https://github.com/Homebrew/homebrew-core/pulls?q=is%3Apr+git-machete) | Homebrew maintainers                                                                        | Our CI on `master` builds (opens formula-bump PR), then homebrew-core GitHub Actions                                                                                                  | bash, fish, zsh + man page            | ![homebrew formula monthly downloads](https://img.shields.io/homebrew/installs/dm/git-machete.svg) <br/> ![homebrew formula quarterly downloads](https://img.shields.io/homebrew/installs/dq/git-machete.svg) <br/> ![homebrew formula yearly downloads](https://img.shields.io/homebrew/installs/dy/git-machete.svg) |
+| Homebrew                                            | ![homebrew formula](https://img.shields.io/homebrew/v/git-machete.svg?label=)                                   | [**Formula**](https://formulae.brew.sh/formula/git-machete)                                                                                                                                                               | [Formula source](https://github.com/Homebrew/homebrew-core/blob/master/Formula/g/git-machete.rb) (points to PyPI)                          | [PRs](https://github.com/Homebrew/homebrew-core/pulls?q=is%3Apr+git-machete) | Homebrew maintainers                                                                        | Our CI on `master` builds (opens formula-bump PR), then homebrew-core GitHub Actions                                                                                                  | bash, fish, zsh + man page            | ![homebrew formula monthly downloads](https://img.shields.io/homebrew/installs/dm/git-machete.svg) <br/> ![homebrew formula quarterly downloads](https://img.shields.io/homebrew/installs/dq/git-machete.svg) <br/> ![homebrew formula yearly downloads](https://img.shields.io/homebrew/installs/dy/git-machete.svg) |
 | [LiGurOS (Gentoo fork)](https://liguros.gitlab.io/) | ![LiGurOS develop package](https://repology.org/badge/version-for-repo/liguros_develop/git-machete.svg?header=) |                                                                                                                                                                                                                           | [ebuild](https://gitlab.com/liguros/liguros-repo/-/tree/develop/dev-vcs/git-machete) (points to GitHub)                                    |                                                                              | LiGurOS package maintainers                                                                 | LiGurOS package maintainers                                                                                                                                                           | bash, fish, zsh                       |                                                                                                                                                                                                                                                                                                                       |
 | nixpkgs                                             | ![nixpkgs unstable package](https://repology.org/badge/version-for-repo/nix_unstable/git-machete.svg?header=)   | [**nixpkgs unstable package**](https://search.nixos.org/packages?channel=unstable&show=git-machete&query=git-machete)                                                                                                     | [Expression](https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/version-management/git-machete/default.nix) (points to GitHub) | [PRs](https://github.com/NixOS/nixpkgs/pulls?q=is%3Apr+git-machete)          | nixpkgs maintainers, incl. [@blitz (Julian Stecklina)](https://github.com/blitz)            | [@r-ryantm bot](https://github.com/r-ryantm) ([logs](https://r.ryantm.com/log/updatescript/git-machete/))[^3]                                                                         | bash, fish, zsh                       |                                                                                                                                                                                                                                                                                                                       |
 | PyPI                                                | ![PyPI package](https://img.shields.io/pypi/v/git-machete.svg?label=)                                           | [**PyPI package**](https://pypi.org/project/git-machete) <br/> [Test PyPI package](https://test.pypi.org/project/git-machete)                                                                                             |                                                                                                                                            |                                                                              | Ourselves                                                                                   | Our CI on `master` builds[^4]                                                                                                                                                         | -                                     | ![PyPI daily downloads](https://img.shields.io/pypi/dd/git-machete.svg) <br/> ![PyPI weekly downloads](https://img.shields.io/pypi/dw/git-machete.svg) <br/> ![PyPI monthly downloads](https://img.shields.io/pypi/dm/git-machete.svg) <br/> ![PyPI wheel?](https://img.shields.io/pypi/wheel/git-machete.svg)        |
diff --git a/README.md b/README.md
index 71066e0..1ea6b28 100644
--- a/README.md
+++ b/README.md
@@ -14,7 +14,8 @@
 [![codecov](https://codecov.io/gh/VirtusLab/git-machete/branch/develop/graph/badge.svg)](https://codecov.io/gh/VirtusLab/git-machete)
 
 [//]: # (The image is referenced by its full URL to ensure it renders correctly on https://pypi.org/project/git-machete/)
-<img src="https://raw.githubusercontent.com/VirtusLab/git-machete/master/graphics/logo_with_name.svg" style="width: 100%; display: block; margin-bottom: 10pt;" />
+<img src="https://raw.githubusercontent.com/VirtusLab/git-machete/develop/graphics/logo/svg/with-name.svg#gh-light-mode-only"     style="width: 100%; display: block; margin-bottom: 10pt;" />
+<img src="https://raw.githubusercontent.com/VirtusLab/git-machete/develop/graphics/logo/svg/with-name-dark.svg#gh-dark-mode-only" style="width: 100%; display: block; margin-bottom: 10pt;" />
 
 💪 git-machete is a robust tool that **simplifies your git workflows**.<br/>
 
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index 06943c5..f30012a 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -1,5 +1,9 @@
 # Release notes
 
+## New in git-machete 3.18.1
+
+- fixed: `machete.github.remote` git config key can be specified independently from `machete.github.organization` and `machete.github.repository`
+
 ## New in git-machete 3.18.0
 
 - added: `git machete completion bash|fish|zsh` command
diff --git a/ci/checks/enforce-mocking-only-whitelisted-methods.sh b/ci/checks/enforce-mocking-only-whitelisted-methods.sh
index 7abeee3..9e179a4 100755
--- a/ci/checks/enforce-mocking-only-whitelisted-methods.sh
+++ b/ci/checks/enforce-mocking-only-whitelisted-methods.sh
@@ -13,7 +13,7 @@ git_machete.client.MacheteClient.is_stdout_a_tty
 git_machete.git_operations.GitContext.fetch_remote
 git_machete.github.GitHubClient.MAX_PULLS_PER_PAGE_COUNT
 git_machete.github.GitHubToken.for_domain
-git_machete.github.RemoteAndOrganizationAndRepository.from_url
+git_machete.github.OrganizationAndRepository.from_url
 git_machete.utils._popen_cmd
 git_machete.utils._run_cmd
 git_machete.utils.find_executable
diff --git a/ci/homebrew/ci-deploy.sh b/ci/homebrew/ci-deploy.sh
index 3feea29..78f1ae9 100644
--- a/ci/homebrew/ci-deploy.sh
+++ b/ci/homebrew/ci-deploy.sh
@@ -54,7 +54,7 @@ else
   attempts=5
   i=1
   while true; do
-    if brew install --build-from-source --formula /home/linuxbrew/.linuxbrew/Homebrew/Library/Taps/homebrew/homebrew-core/Formula/git-machete.rb; then
+    if brew install --build-from-source --formula /home/linuxbrew/.linuxbrew/Homebrew/Library/Taps/homebrew/homebrew-core/Formula/g/git-machete.rb; then
       break
     elif (( i < attempts )); then
       echo "Retrying the installation..."
diff --git a/docs/man/git-machete.1 b/docs/man/git-machete.1
index 5ef0c67..65bdbef 100644
--- a/docs/man/git-machete.1
+++ b/docs/man/git-machete.1
@@ -27,9 +27,9 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
 .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
 .in \\n[rst2man-indent\\n[rst2man-indent-level]]u
 ..
-.TH "GIT-MACHETE" "1" "Aug 11, 2023" "" "git-machete"
+.TH "GIT-MACHETE" "1" "Aug 27, 2023" "" "git-machete"
 .SH NAME
-git-machete \- git-machete 3.18.0
+git-machete \- git-machete 3.18.1
 .sp
 git machete is a robust tool that \fBsimplifies your git workflows\fP\&.
 .sp
@@ -342,20 +342,18 @@ You can alter the default behavior by setting the following git config keys:
 .B GitHub Enterprise domain
 E.g. \fBgit config machete.github.domain git.example.org\fP
 .TP
-.B Remote name
+.B Remote name (as in \fBgit remote\fP)
 E.g. \fBgit config machete.github.remote origin\fP
 .TP
-.B Organization name
-E.g. \fBgit config machete.github.organization VirtusLab\fP
-.TP
-.B Repository name
-E.g. \fBgit config machete.github.repository git\-machete\fP
+.B Organization and repository name
+E.g. \fBgit config machete.github.organization VirtusLab; git config machete.github.repository git\-machete\fP
 .UNINDENT
 .UNINDENT
 .UNINDENT
 .sp
 Note that you do \fBnot\fP need to set all four keys at once.
 For example, in a typical usage of GitHub Enterprise, it should be enough to just set \fBmachete.github.domain\fP\&.
+Only \fBmachete.github.organization\fP and \fBmachete.github.repository\fP must be specified together.
 .UNINDENT
 .UNINDENT
 .sp
@@ -404,25 +402,23 @@ You can alter the default behavior by setting the following git config keys:
 .B GitHub Enterprise domain
 E.g. \fBgit config machete.github.domain git.example.org\fP
 .TP
-.B Remote name
+.B Remote name (as in \fBgit remote\fP)
 E.g. \fBgit config machete.github.remote origin\fP
 .TP
-.B Organization name
-E.g. \fBgit config machete.github.organization VirtusLab\fP
-.TP
-.B Repository name
-E.g. \fBgit config machete.github.repository git\-machete\fP
+.B Organization and repository name
+E.g. \fBgit config machete.github.organization VirtusLab; git config machete.github.repository git\-machete\fP
 .UNINDENT
 .UNINDENT
 .UNINDENT
 .sp
 Note that you do \fBnot\fP need to set all four keys at once.
 For example, in a typical usage of GitHub Enterprise, it should be enough to just set \fBmachete.github.domain\fP\&.
+Only \fBmachete.github.organization\fP and \fBmachete.github.repository\fP must be specified together.
 .UNINDENT
 .UNINDENT
 .TP
 .B \fBmachete.overrideForkPoint.<branch>.to\fP:
-Executing \fBgit machete fork\-point \-\-override\-to[\-parent|\-inferred|=<revision>] [<branch>]\fP sets up a fork point override for <branch>.
+Executing \fBgit machete fork\-point \-\-override\-to[\-parent|\-inferred|=<revision>] [<branch>]\fP sets up a fork point override for \fB<branch>\fP\&.
 .sp
 The override data is stored under \fBmachete.overrideForkPoint.<branch>.to\fP git config key.
 .sp
@@ -592,20 +588,18 @@ You can alter the default behavior by setting the following git config keys:
 .B GitHub Enterprise domain
 E.g. \fBgit config machete.github.domain git.example.org\fP
 .TP
-.B Remote name
+.B Remote name (as in \fBgit remote\fP)
 E.g. \fBgit config machete.github.remote origin\fP
 .TP
-.B Organization name
-E.g. \fBgit config machete.github.organization VirtusLab\fP
-.TP
-.B Repository name
-E.g. \fBgit config machete.github.repository git\-machete\fP
+.B Organization and repository name
+E.g. \fBgit config machete.github.organization VirtusLab; git config machete.github.repository git\-machete\fP
 .UNINDENT
 .UNINDENT
 .UNINDENT
 .sp
 Note that you do \fBnot\fP need to set all four keys at once.
 For example, in a typical usage of GitHub Enterprise, it should be enough to just set \fBmachete.github.domain\fP\&.
+Only \fBmachete.github.organization\fP and \fBmachete.github.repository\fP must be specified together.
 .UNINDENT
 .UNINDENT
 .sp
@@ -1060,20 +1054,18 @@ You can alter the default behavior by setting the following git config keys:
 .B GitHub Enterprise domain
 E.g. \fBgit config machete.github.domain git.example.org\fP
 .TP
-.B Remote name
+.B Remote name (as in \fBgit remote\fP)
 E.g. \fBgit config machete.github.remote origin\fP
 .TP
-.B Organization name
-E.g. \fBgit config machete.github.organization VirtusLab\fP
-.TP
-.B Repository name
-E.g. \fBgit config machete.github.repository git\-machete\fP
+.B Organization and repository name
+E.g. \fBgit config machete.github.organization VirtusLab; git config machete.github.repository git\-machete\fP
 .UNINDENT
 .UNINDENT
 .UNINDENT
 .sp
 Note that you do \fBnot\fP need to set all four keys at once.
 For example, in a typical usage of GitHub Enterprise, it should be enough to just set \fBmachete.github.domain\fP\&.
+Only \fBmachete.github.organization\fP and \fBmachete.github.repository\fP must be specified together.
 .UNINDENT
 .UNINDENT
 .sp
diff --git a/docs/source/cli/config.rst b/docs/source/cli/config.rst
index f6c17f7..dcf6f72 100644
--- a/docs/source/cli/config.rst
+++ b/docs/source/cli/config.rst
@@ -15,7 +15,7 @@ Note: ``config`` is not a command as such, just a help topic (there is no ``git
         :start-line: 2
 
 ``machete.overrideForkPoint.<branch>.to``:
-    Executing ``git machete fork-point --override-to[-parent|-inferred|=<revision>] [<branch>]`` sets up a fork point override for <branch>.
+    Executing ``git machete fork-point --override-to[-parent|-inferred|=<revision>] [<branch>]`` sets up a fork point override for ``<branch>``.
 
     The override data is stored under ``machete.overrideForkPoint.<branch>.to`` git config key.
 
diff --git a/docs/source/github_config_keys.rst b/docs/source/github_config_keys.rst
index c75b28d..527c0c8 100644
--- a/docs/source/github_config_keys.rst
+++ b/docs/source/github_config_keys.rst
@@ -6,18 +6,16 @@
         GitHub Enterprise domain
             E.g. ``git config machete.github.domain git.example.org``
 
-        Remote name
+        Remote name (as in ``git remote``)
             E.g. ``git config machete.github.remote origin``
 
-        Organization name
-            E.g. ``git config machete.github.organization VirtusLab``
-
-        Repository name
-            E.g. ``git config machete.github.repository git-machete``
+        Organization and repository name
+            E.g. ``git config machete.github.organization VirtusLab; git config machete.github.repository git-machete``
 
     Note that you do **not** need to set all four keys at once.
     For example, in a typical usage of GitHub Enterprise, it should be enough to just set ``machete.github.domain``.
+    Only ``machete.github.organization`` and ``machete.github.repository`` must be specified together.
 
 ..
-    Text order in this file is relevant, if you want to change something, find each ``.. include:: github_config_keys.rst`` instance
-    and if the instance has ``start-line`` or ``end-line`` options provided, make sure that after changes the output text stays the same.
+    Text order in this file is relevant, if you want to change something, find each occurrence of ``.. include:: github_config_keys.rst``
+    and if this occurrence has ``start-line`` or ``end-line`` options provided, make sure that after changes the output text stays the same.
diff --git a/git_machete/__init__.py b/git_machete/__init__.py
index c754d32..12879d5 100644
--- a/git_machete/__init__.py
+++ b/git_machete/__init__.py
@@ -1,1 +1,1 @@
-__version__ = '3.18.0'
+__version__ = '3.18.1'
diff --git a/git_machete/cli.py b/git_machete/cli.py
index 4e7422b..bfc1d73 100644
--- a/git_machete/cli.py
+++ b/git_machete/cli.py
@@ -865,14 +865,10 @@ def main() -> None:
         sys.exit(ExitCode.END_OF_FILE_SIGNAL)
     except KeyboardInterrupt:
         sys.exit(ExitCode.KEYBOARD_INTERRUPT)
-    except (argparse.ArgumentError, argparse.ArgumentTypeError) as e:
-        print(get_short_general_usage())
-        print(e, file=sys.stderr)
-        sys.exit(ExitCode.ARGUMENT_ERROR)
     except (MacheteException, UnderlyingGitException) as e:
         print(e, file=sys.stderr)
         sys.exit(ExitCode.MACHETE_EXCEPTION)
-    except InteractionStopped:
+    except InteractionStopped:  # pragma: no cover
         pass
 
 
diff --git a/git_machete/client.py b/git_machete/client.py
index 794d2f5..9f02a32 100644
--- a/git_machete/client.py
+++ b/git_machete/client.py
@@ -20,7 +20,8 @@ from .git_operations import (HEAD, AnyBranchName, AnyRevision, BranchPair,
                              GitLogEntry, LocalBranchShortName,
                              RemoteBranchShortName)
 from .github import (GitHubClient, GitHubPullRequest, GitHubToken,
-                     RemoteAndOrganizationAndRepository, is_github_remote_url)
+                     OrganizationAndRepository,
+                     OrganizationAndRepositoryAndRemote, is_github_remote_url)
 from .utils import (GITHUB_NEW_ISSUE_MESSAGE, AnsiEscapeCodes, PopenResult,
                     SyncToParentStatus, bold, colored, debug, dim, excluding,
                     flat_map, fmt, get_pretty_choices, get_second,
@@ -1586,8 +1587,8 @@ class MacheteClient:
 
     def sync_annotations_to_github_prs(self) -> None:
         domain = self.__derive_github_domain()
-        remote_org_repo = self.__derive_remote_and_github_org_and_repo(domain=domain)
-        github_client = GitHubClient(domain=domain, organization=remote_org_repo.organization, repository=remote_org_repo.repository)
+        org_repo_remote = self.__derive_org_repo_and_remote(domain=domain)
+        github_client = GitHubClient(domain=domain, organization=org_repo_remote.organization, repository=org_repo_remote.repository)
         print('Checking for open GitHub PRs... ', end='', flush=True)
         current_user: Optional[str] = github_client.derive_current_user_login()
         debug('Current GitHub user is ' + (bold(current_user or '<none>')))
@@ -2028,8 +2029,8 @@ class MacheteClient:
                             fail_on_missing_current_user_for_my_opened_prs: bool = False
                             ) -> None:
         domain = self.__derive_github_domain()
-        remote_org_repo = self.__derive_remote_and_github_org_and_repo(domain=domain)
-        github_client = GitHubClient(domain=domain, organization=remote_org_repo.organization, repository=remote_org_repo.repository)
+        org_repo_remote = self.__derive_org_repo_and_remote(domain=domain)
+        github_client = GitHubClient(domain=domain, organization=org_repo_remote.organization, repository=org_repo_remote.repository)
         print('Checking for open GitHub PRs... ', end='', flush=True)
 
         current_user: Optional[str] = github_client.derive_current_user_login()
@@ -2048,14 +2049,14 @@ class MacheteClient:
             pr_nos, all_opened_prs_from_github=all_open_prs, github_client=github_client,
             all=all_opened_prs, mine=my_opened_prs, by=opened_by, user=current_user)
 
-        debug(f'organization is {remote_org_repo.organization}, repository is {remote_org_repo.repository}')
-        self.__git.fetch_remote(remote_org_repo.remote)
+        debug(f'organization is {org_repo_remote.organization}, repository is {org_repo_remote.repository}')
+        self.__git.fetch_remote(org_repo_remote.remote)
 
         pr: Optional[GitHubPullRequest] = None
         checked_out_prs: List[GitHubPullRequest] = []
         for pr in sorted(applicable_prs, key=lambda x: x.number):
             if pr.full_repository_name:
-                if '/'.join([remote_org_repo.remote, pr.head]) not in self.__git.get_remote_branches():
+                if '/'.join([org_repo_remote.remote, pr.head]) not in self.__git.get_remote_branches():
                     remote_already_added: Optional[str] = self.__get_remote_name_for_repository_url(domain, pr.repository_url)
                     if remote_already_added:
                         remote_to_fetch = remote_already_added
@@ -2063,7 +2064,7 @@ class MacheteClient:
                         remote_to_fetch = pr.full_repository_name.split('/')[0]
                         if remote_to_fetch not in self.__git.get_remotes():
                             self.__git.add_remote(remote_to_fetch, pr.repository_url)
-                    if remote_org_repo.remote != remote_to_fetch:
+                    if org_repo_remote.remote != remote_to_fetch:
                         self.__git.fetch_remote(remote_to_fetch)
                     if '/'.join([remote_to_fetch, pr.head]) not in self.__git.get_remote_branches():
                         raise MacheteException(
@@ -2072,7 +2073,7 @@ class MacheteClient:
             else:
                 warn(f'Pull request #{bold(str(pr.number))} comes from fork and its repository is already deleted. '
                      f'No remote tracking data will be set up for {bold(pr.head)} branch.')
-                github_client.checkout_pr_refs(self.__git, remote_org_repo.remote, pr.number, LocalBranchShortName.of(pr.head))
+                github_client.checkout_pr_refs(self.__git, org_repo_remote.remote, pr.number, LocalBranchShortName.of(pr.head))
             if pr.state == 'closed':
                 warn(f'Pull request #{bold(str(pr.number))} is already closed.')
             debug(f'found {pr}')
@@ -2167,24 +2168,22 @@ class MacheteClient:
 
     def __get_remote_name_for_repository_url(self, github_domain: str, remote_url: str) -> Optional[str]:
         """
-        Check if remote is added locally by its url,
-        because it may happen that a remote is already added under a name different from the name of organization on GitHub
+        Check if the given remote (as identified by `remote_url`) is already added to local git remotes,
+        because it may happen that the local git remote's name is different from the name of organization on GitHub.
         """
         for remote, url in self.__get_url_for_remote().items():
-            url = url if url.endswith('.git') else url + '.git'
-            remote_url = remote_url if remote_url.endswith('.git') else remote_url + '.git'
             if is_github_remote_url(github_domain, url) and \
-                    RemoteAndOrganizationAndRepository.from_url(github_domain, url, remote) == \
-                    RemoteAndOrganizationAndRepository.from_url(github_domain, remote_url, remote):
+                    OrganizationAndRepository.from_url(github_domain, url) == \
+                    OrganizationAndRepository.from_url(github_domain, remote_url):
                 return remote
         return None
 
     def retarget_github_pr(self, head: LocalBranchShortName, ignore_if_missing: bool) -> None:
         domain = self.__derive_github_domain()
-        remote_org_repo = self.__derive_remote_and_github_org_and_repo(domain=domain, branch_used_for_tracking_data=head)
-        github_client = GitHubClient(domain=domain, organization=remote_org_repo.organization, repository=remote_org_repo.repository)
+        org_repo_remote = self.__derive_org_repo_and_remote(domain=domain, branch_used_for_tracking_data=head)
+        github_client = GitHubClient(domain=domain, organization=org_repo_remote.organization, repository=org_repo_remote.repository)
 
-        debug(f'organization is {remote_org_repo.organization}, repository is {remote_org_repo.repository}')
+        debug(f'organization is {org_repo_remote.organization}, repository is {org_repo_remote.repository}')
 
         try:
             prs: List[GitHubPullRequest] = github_client.derive_pull_requests_by_head(head)
@@ -2223,31 +2222,67 @@ class MacheteClient:
     def __derive_github_domain(self) -> str:
         return self.__git.get_config_attr_or_none(key=git_config_keys.GITHUB_DOMAIN) or GitHubClient.DEFAULT_GITHUB_DOMAIN
 
-    def __derive_remote_and_github_org_and_repo(self,
-                                                domain: str,
-                                                branch_used_for_tracking_data: Optional[LocalBranchShortName] = None
-                                                ) -> RemoteAndOrganizationAndRepository:
-        remote_and_organization_and_repository_from_config = RemoteAndOrganizationAndRepository.from_config(self.__git)
-        if remote_and_organization_and_repository_from_config:
-            return remote_and_organization_and_repository_from_config
+    def __derive_org_repo_and_remote(
+            self,
+            domain: str,
+            branch_used_for_tracking_data: Optional[LocalBranchShortName] = None
+    ) -> OrganizationAndRepositoryAndRemote:
+        remote_from_config = self.__git.get_config_attr_or_none(key=git_config_keys.GITHUB_REMOTE)
+        org_from_config = self.__git.get_config_attr_or_none(key=git_config_keys.GITHUB_ORGANIZATION)
+        repo_from_config = self.__git.get_config_attr_or_none(key=git_config_keys.GITHUB_REPOSITORY)
 
         url_for_remote: Dict[str, str] = self.__get_url_for_remote()
         if not url_for_remote:
-            raise MacheteException(fmt('No remotes defined for this repository (see `git remote`)'))
-
-        remote_and_organization_and_repository_from_urls: Dict[str, RemoteAndOrganizationAndRepository] = {
-            remote: ror for remote, ror in (
-                (remote, RemoteAndOrganizationAndRepository.from_url(domain, url, remote)) for remote, url in url_for_remote.items()
-            ) if ror
+            raise MacheteException('No remotes defined for this repository (see `git remote`)')
+
+        if org_from_config and not repo_from_config:
+            raise MacheteException('`machete.github.organization` git config key is present, '
+                                   'but `machete.github.repository` is missing. Both keys must be present to take effect')
+
+        if not org_from_config and repo_from_config:
+            raise MacheteException('`machete.github.repository` git config key is present, '
+                                   'but `machete.github.organization` is missing. Both keys must be present to take effect')
+
+        if remote_from_config:
+            if remote_from_config not in url_for_remote:
+                raise MacheteException(f'`machete.github.remote` git config key points to `{remote_from_config}` remote, '
+                                       'but such remote does not exist')
+
+        if remote_from_config and org_from_config and repo_from_config:
+            return OrganizationAndRepositoryAndRemote(org_from_config, repo_from_config, remote_from_config)
+
+        if remote_from_config:
+            url = url_for_remote[remote_from_config]
+            org_and_repo = OrganizationAndRepository.from_url(domain, url)
+            if not org_and_repo:
+                raise MacheteException(f'`machete.github.remote` git config key points to `{remote_from_config}` remote, '
+                                       f'but its URL `{url}` does not correspond to a valid GitHub repository')
+            return OrganizationAndRepositoryAndRemote(org_and_repo.organization, org_and_repo.repository, remote_from_config)
+
+        if org_from_config and repo_from_config:
+            for remote, url in self.__get_url_for_remote().items():
+                if is_github_remote_url(domain, url) and \
+                        OrganizationAndRepository.from_url(domain, url) == \
+                        OrganizationAndRepository(org_from_config, repo_from_config):
+                    return OrganizationAndRepositoryAndRemote(org_from_config, repo_from_config, remote)
+            raise MacheteException(
+                'Both `machete.github.organization` and `machete.github.repository` git config keys are defined, '
+                f'but no remote seems to correspond to `{org_from_config}/{repo_from_config}` (organization/repository) on GitHub.\n'
+                'Consider pointing to the remote via `machete.github.remote` config key')
+
+        remote_and_organization_and_repository_from_urls: Dict[str, OrganizationAndRepositoryAndRemote] = {
+            remote: OrganizationAndRepositoryAndRemote(oar.organization, oar.repository, remote) for remote, oar in (
+                (remote, OrganizationAndRepository.from_url(domain, url)) for remote, url in url_for_remote.items()
+            ) if oar
         }
 
         if not remote_and_organization_and_repository_from_urls:
             raise MacheteException(
-                fmt('Remotes are defined for this repository, but none of them '
-                    'seems to correspond to GitHub (see `git remote -v` for details).\n'
-                    'It is possible that you are using a custom GitHub URL.\n'
-                    'If that is the case, you can provide repository information explicitly via some or all of git config keys: '
-                    '`machete.github.{domain,remote,organization,repository}.`\n'))  # noqa: FS003
+                'Remotes are defined for this repository, but none of them '
+                'seems to correspond to GitHub (see `git remote -v` for details).\n'
+                'It is possible that you are using a custom GitHub URL.\n'
+                'If that is the case, you can provide repository information explicitly via some or all of git config keys: '
+                '`machete.github.{domain,remote,organization,repository}.`\n')  # noqa: FS003
 
         if len(remote_and_organization_and_repository_from_urls) == 1:
             return remote_and_organization_and_repository_from_urls[list(remote_and_organization_and_repository_from_urls.keys())[0]]
@@ -2286,15 +2321,15 @@ class MacheteClient:
             raise MacheteException(  # pragma: no cover; should never happen
                 f'Could not determine base branch for PR. Branch {bold(head)} is a root branch.' + GITHUB_NEW_ISSUE_MESSAGE)
         domain = self.__derive_github_domain()
-        remote_org_repo = self.__derive_remote_and_github_org_and_repo(domain=domain, branch_used_for_tracking_data=head)
-        github_client = GitHubClient(domain=domain, organization=remote_org_repo.organization, repository=remote_org_repo.repository)
-        print(f"Fetching {bold(remote_org_repo.remote)}...")
-        self.__git.fetch_remote(remote_org_repo.remote)
-        if '/'.join([remote_org_repo.remote, base]) not in self.__git.get_remote_branches():
+        org_repo_remote = self.__derive_org_repo_and_remote(domain=domain, branch_used_for_tracking_data=head)
+        github_client = GitHubClient(domain=domain, organization=org_repo_remote.organization, repository=org_repo_remote.repository)
+        print(f"Fetching {bold(org_repo_remote.remote)}...")
+        self.__git.fetch_remote(org_repo_remote.remote)
+        if '/'.join([org_repo_remote.remote, base]) not in self.__git.get_remote_branches():
             warn(f'Base branch for this PR ({bold(base)}) is not found on remote, pushing...')
             self.__handle_untracked_branch(
                 branch=base,
-                new_remote=remote_org_repo.remote,
+                new_remote=org_repo_remote.remote,
                 is_called_from_traverse=False,
                 is_called_from_create_pr=True,
                 opt_push_tracked=False,
@@ -2302,7 +2337,7 @@ class MacheteClient:
                 opt_yes=False)
 
         current_user: Optional[str] = github_client.derive_current_user_login()
-        debug(f'organization is {remote_org_repo.organization}, repository is {remote_org_repo.repository}')
+        debug(f'organization is {org_repo_remote.organization}, repository is {org_repo_remote.repository}')
         debug('current GitHub user is ' + (current_user or '<none>'))
 
         description_path = self.__git.get_main_git_subpath('info', 'description')
diff --git a/git_machete/generated_docs.py b/git_machete/generated_docs.py
index efb16e7..7a9a081 100644
--- a/git_machete/generated_docs.py
+++ b/git_machete/generated_docs.py
@@ -155,16 +155,14 @@ long_docs: Dict[str, str] = {
            GitHub Enterprise domain
               E.g. `git config machete.github.domain git.example.org`
 
-           Remote name
+           Remote name (as in `git remote`)
               E.g. `git config machete.github.remote origin`
 
-           Organization name
-              E.g. `git config machete.github.organization VirtusLab`
-
-           Repository name
-              E.g. `git config machete.github.repository git-machete`
+           Organization and repository name
+              E.g. `git config machete.github.organization VirtusLab; git config machete.github.repository git-machete`
         Note that you do <b>not</b> need to set all four keys at once.
         For example, in a typical usage of GitHub Enterprise, it should be enough to just set `machete.github.domain`.
+        Only `machete.github.organization` and `machete.github.repository` must be specified together.
 
         In any other case, sets the annotation for the given/current branch to the given <annotation text>.
         If multiple <annotation text>'s are passed to the command, they are concatenated with a single space.
@@ -223,16 +221,14 @@ long_docs: Dict[str, str] = {
            GitHub Enterprise domain
               E.g. `git config machete.github.domain git.example.org`
 
-           Remote name
+           Remote name (as in `git remote`)
               E.g. `git config machete.github.remote origin`
 
-           Organization name
-              E.g. `git config machete.github.organization VirtusLab`
-
-           Repository name
-              E.g. `git config machete.github.repository git-machete`
+           Organization and repository name
+              E.g. `git config machete.github.organization VirtusLab; git config machete.github.repository git-machete`
         Note that you do <b>not</b> need to set all four keys at once.
         For example, in a typical usage of GitHub Enterprise, it should be enough to just set `machete.github.domain`.
+        Only `machete.github.organization` and `machete.github.repository` must be specified together.
 
         <b>Options:</b>
            <b>-c</b>, <b>--checkout-my-github-prs</b>
@@ -288,21 +284,19 @@ long_docs: Dict[str, str] = {
                  GitHub Enterprise domain
               E.g. `git config machete.github.domain git.example.org`
 
-                 Remote name
+                 Remote name (as in `git remote`)
               E.g. `git config machete.github.remote origin`
 
-                 Organization name
-              E.g. `git config machete.github.organization VirtusLab`
-
-                 Repository name
-              E.g. `git config machete.github.repository git-machete`
+                 Organization and repository name
+              E.g. `git config machete.github.organization VirtusLab; git config machete.github.repository git-machete`
 
               Note that you do <b>not</b> need to set all four keys at once.
               For example, in a typical usage of GitHub Enterprise, it should be enough to just set `machete.github.domain`.
+              Only `machete.github.organization` and `machete.github.repository` must be specified together.
 
            `machete.overrideForkPoint.<branch>.to`:
  
-              Executing `git machete fork-point --override-to[-parent|-inferred|=<revision>] [<branch>]` sets up a fork point override for <branch>.
+              Executing `git machete fork-point --override-to[-parent|-inferred|=<revision>] [<branch>]` sets up a fork point override for `<branch>`.
 
               The override data is stored under `machete.overrideForkPoint.<branch>.to` git config key.
 
@@ -576,16 +570,14 @@ long_docs: Dict[str, str] = {
            GitHub Enterprise domain
               E.g. `git config machete.github.domain git.example.org`
 
-           Remote name
+           Remote name (as in `git remote`)
               E.g. `git config machete.github.remote origin`
 
-           Organization name
-              E.g. `git config machete.github.organization VirtusLab`
-
-           Repository name
-              E.g. `git config machete.github.repository git-machete`
+           Organization and repository name
+              E.g. `git config machete.github.organization VirtusLab; git config machete.github.repository git-machete`
         Note that you do <b>not</b> need to set all four keys at once.
         For example, in a typical usage of GitHub Enterprise, it should be enough to just set `machete.github.domain`.
+        Only `machete.github.organization` and `machete.github.repository` must be specified together.
 
         <b>Subcommands:</b>
            `anno-prs`:
diff --git a/git_machete/github.py b/git_machete/github.py
index a04e3de..2375413 100644
--- a/git_machete/github.py
+++ b/git_machete/github.py
@@ -9,8 +9,6 @@ import urllib.request
 from pathlib import Path
 from typing import Any, Dict, List, NamedTuple, Optional, Tuple
 
-from git_machete import git_config_keys
-
 from .exceptions import MacheteException, UnprocessableEntityHTTPError
 from .git_operations import GitContext, LocalBranchShortName
 from .utils import bold, debug, fmt, popen_cmd, warn
@@ -43,34 +41,28 @@ class GitHubPullRequest(NamedTuple):
         return f"PR #{self.number} by {self.user}: {self.head} -> {self.base}"
 
 
-class RemoteAndOrganizationAndRepository(NamedTuple):
-    remote: str
+class OrganizationAndRepository(NamedTuple):
     organization: str
     repository: str
 
     @classmethod
-    def from_config(cls, git: GitContext) -> Optional["RemoteAndOrganizationAndRepository"]:
-        remote = git.get_config_attr_or_none(key=git_config_keys.GITHUB_REMOTE)
-        organization = git.get_config_attr_or_none(key=git_config_keys.GITHUB_ORGANIZATION)
-        repository = git.get_config_attr_or_none(key=git_config_keys.GITHUB_REPOSITORY)
-        if remote and organization and repository:
-            return cls(remote, organization, repository)
-        else:
-            return None
-
-    @classmethod
-    def from_url(cls, domain: str, url: str, remote: str) -> Optional["RemoteAndOrganizationAndRepository"]:
+    def from_url(cls, domain: str, url: str) -> Optional["OrganizationAndRepository"]:
+        url = url if url.endswith('.git') else url + '.git'
         for pattern in github_remote_url_patterns(domain):
             match = re.match(pattern, url)
             if match:
                 org = match.group(1)
                 repo = match.group(2)
-                return cls(remote=remote,
-                           organization=org,
-                           repository=repo if repo[-4:] != '.git' else repo[:-4])
+                return cls(organization=org, repository=repo if repo[-4:] != '.git' else repo[:-4])
         return None
 
 
+class OrganizationAndRepositoryAndRemote(NamedTuple):
+    organization: str
+    repository: str
+    remote: str
+
+
 GITHUB_TOKEN_ENV_VAR = 'GITHUB_TOKEN'
 
 
@@ -444,4 +436,5 @@ def github_remote_url_patterns(domain: str) -> List[str]:
 
 
 def is_github_remote_url(domain: str, url: str) -> bool:
+    url = url if url.endswith('.git') else url + '.git'
     return any((re.match(pattern, url) for pattern in github_remote_url_patterns(domain)))
diff --git a/graphics/logo_with_name.svg b/graphics/logo/svg/with-name-dark.svg
similarity index 92%
rename from graphics/logo_with_name.svg
rename to graphics/logo/svg/with-name-dark.svg
index 7317520..9bf2034 100644
--- a/graphics/logo_with_name.svg
+++ b/graphics/logo/svg/with-name-dark.svg
@@ -65,66 +65,66 @@ Created by potrace 1.15, written by Peter Selinger 2001-2017
       <path
          d="M 423,1768 C 207,1552 26,1362 20,1347 5,1306 8,1244 26,1207 48,1163 1156,53 1202,29 c 41,-21 101,-25 145,-9 15,6 85,68 156,138 l 127,127 -137,138 -138,137 -42,-6 c -53,-8 -105,9 -150,49 -86,75 -85,199 1,275 20,17 41,32 46,32 6,0 10,134 10,355 0,195 -3,355 -8,355 -4,0 -69,-62 -145,-138 l -138,-138 9,-40 c 14,-64 -4,-120 -53,-169 -117,-117 -315,-37 -315,128 0,112 85,192 196,185 l 54,-3 141,141 140,141 3,74 2,74 -140,143 c -78,78 -143,142 -146,142 -3,0 -181,-177 -397,-392 z"
          id="path6"
-         style="fill:#3e2c00"
+         style="fill:#d1d1d1"
          inkscape:connector-curvature="0" />
     </g>
     <g
        id="g4786">
       <g
          id="g4801"
-         style="fill:#3e2c00;fill-opacity:1">
+         style="fill:#d1d1d1;fill-opacity:1">
         <path
            d="m 433.26495,150.94518 -8.2,0.8 q -3.2,0.2 -3.2,2.8 v 43 q -20.2,9.6 -51.8,9.6 -20,0 -34.6,-5.6 -14.4,-5.6 -22.8,-16 -8.2,-10.4 -12.2,-23.6 -3.8,-13.2 -3.8,-30 0,-33.400002 19.2,-54.000002 19.2,-20.6 55.8,-20.6 11.6,0 24,3 12.6,3 21.2,8.6 v 37.800002 l -22.2,-1.6 -3,-18.000002 q -0.8,-3.4 -3.2,-4 -9.2,-2.6 -18.4,-2.6 -19.2,0 -30.2,13.8 -11,13.600002 -11,37.200002 0,25.2 10.6,39 10.8,13.6 32,13.6 8.6,0 16.6,-1.4 3.2,-0.6 3.2,-3.6 v -26.2 h -22.2 l 2.8,-18 h 61.4 z"
-           style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:200px;line-height:1.25;font-family:Adelle;-inkscape-font-specification:'Adelle Bold';letter-spacing:0px;word-spacing:0px;fill:#3e2c00;fill-opacity:1;stroke:none;stroke-width:0.75"
+           style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:200px;line-height:1.25;font-family:Adelle;-inkscape-font-specification:'Adelle Bold';letter-spacing:0px;word-spacing:0px;fill:#d1d1d1;fill-opacity:1;stroke:none;stroke-width:0.75"
            id="path4767"
            inkscape:connector-curvature="0" />
         <path
            d="m 478.26459,53.545178 q 4.8,4.4 4.8,13 0,8.6 -4.8,13.4 -4.8,4.6 -13.4,4.6 -8.6,0 -13.4,-4.6 -4.6,-4.8 -4.6,-13.4 0,-8.6 4.6,-13 4.8,-4.6 13.4,-4.6 8.8,0 13.4,4.6 z m 17.8,151.200002 h -57 v -15.8 l 10.2,-1.4 q 2,-0.2 2.6,-1 0.6,-0.8 0.6,-3 v -58.8 q 0,-3.4 -2.6,-4.2 l -10.8,-3.8 2.2,-16.2 h 41.4 v 83 q 0,2.4 0.4,3.2 0.6,0.6 2.8,0.8 l 10.2,1.4 z"
-           style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:200px;line-height:1.25;font-family:Adelle;-inkscape-font-specification:'Adelle Bold';letter-spacing:0px;word-spacing:0px;fill:#3e2c00;fill-opacity:1;stroke:none;stroke-width:0.75"
+           style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:200px;line-height:1.25;font-family:Adelle;-inkscape-font-specification:'Adelle Bold';letter-spacing:0px;word-spacing:0px;fill:#d1d1d1;fill-opacity:1;stroke:none;stroke-width:0.75"
            id="path4769"
            inkscape:connector-curvature="0" />
         <path
            d="m 575.46459,181.54518 5.4,17.6 q -16.4,8 -32.6,8 -17.6,0 -25.2,-7.6 -7.6,-7.6 -7.6,-24.6 v -52.4 q 0,-2 -1.6,-2 h -14 v -17.8 q 13.2,-1.4 19.2,-8.800002 6,-7.4 7.6,-23.8 h 19 v 28.4 q 0,2.000002 1.6,2.000002 h 28.2 v 20 h -29.8 v 47.8 q 0,9.2 2.8,12.8 2.8,3.6 10.8,3.6 7.6,0 16.2,-3.2 z"
-           style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:200px;line-height:1.25;font-family:Adelle;-inkscape-font-specification:'Adelle Bold';letter-spacing:0px;word-spacing:0px;fill:#3e2c00;fill-opacity:1;stroke:none;stroke-width:0.75"
+           style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:200px;line-height:1.25;font-family:Adelle;-inkscape-font-specification:'Adelle Bold';letter-spacing:0px;word-spacing:0px;fill:#d1d1d1;fill-opacity:1;stroke:none;stroke-width:0.75"
            id="path4771"
            inkscape:connector-curvature="0" />
       </g>
       <g
          id="g4810"
-         style="fill:#3e2c00;fill-opacity:1">
+         style="fill:#d1d1d1;fill-opacity:1">
         <path
            d="m 811.26429,204.74518 h -65.8 v -15.6 l 16.4,-1.4 q 2,-0.2 2.6,-1 0.6,-0.8 0.6,-3 v -76 h -0.8 l -28.6,68.2 h -32.6 l -28.2,-68.4 h -1 v 76 q 0,2.4 0.4,3.2 0.6,0.6 2.8,0.8 l 17.2,1.6 v 15.6 h -60.8 v -15.6 l 12.6,-1.4 q 2,-0.2 2.6,-1 0.6,-0.8 0.6,-3 V 81.145178 q 0,-2.2 -0.6,-3 -0.6,-0.8 -2.6,-1 l -12.6,-1.4 v -15.8 h 53.6 l 34.8,90.600002 h 0.8 l 36.6,-90.600002 h 52 v 15.6 l -13.4,1.6 q -2.2,0.2 -2.8,1 -0.4,0.6 -0.4,2.8 V 183.74518 q 0,3.4 3.2,3.8 l 13.4,1.6 z"
-           style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:200px;line-height:1.25;font-family:Adelle;-inkscape-font-specification:'Adelle Bold';letter-spacing:0px;word-spacing:0px;fill:#3e2c00;fill-opacity:1;stroke:none;stroke-width:0.75"
+           style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:200px;line-height:1.25;font-family:Adelle;-inkscape-font-specification:'Adelle Bold';letter-spacing:0px;word-spacing:0px;fill:#d1d1d1;fill-opacity:1;stroke:none;stroke-width:0.75"
            id="path4773"
            inkscape:connector-curvature="0" />
         <path
            d="m 927.46431,204.74518 h -36.8 l -2,-10.8 -1,-0.2 q -13.8,13.4 -33.6,13.4 -29.2,0 -29.2,-29.6 0,-14.8 9.2,-22.2 9.2,-7.4 28.2,-8.6 l 23,-1.6 v -11 q 0,-8.2 -2.4,-12 -2.4,-3.8 -11,-3.8 -8,0 -11.4,2.6 -3.2,2.4 -3.2,10.8 l -28.2,-2.4 q 0,-30.800002 43,-30.800002 23.4,0 33,7.800002 9.6,7.8 9.6,28.4 v 48.6 q 0,2.4 0.4,3.2 0.6,0.6 2.8,0.8 l 9.6,1.6 z m -42.2,-26.4 v -16.6 l -13.6,1 q -8.8,0.6 -12.4,3.2 -3.6,2.6 -3.6,8.6 0,11 11.4,11 8.4,0 18.2,-7.2 z"
-           style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:200px;line-height:1.25;font-family:Adelle;-inkscape-font-specification:'Adelle Bold';letter-spacing:0px;word-spacing:0px;fill:#3e2c00;fill-opacity:1;stroke:none;stroke-width:0.75"
+           style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:200px;line-height:1.25;font-family:Adelle;-inkscape-font-specification:'Adelle Bold';letter-spacing:0px;word-spacing:0px;fill:#d1d1d1;fill-opacity:1;stroke:none;stroke-width:0.75"
            id="path4775"
            inkscape:connector-curvature="0" />
         <path
            d="m 1016.464,178.74518 7.8,18.6 q -16.2,9.8 -37.99998,9.8 -26,0 -39.2,-14.4 -13.2,-14.6 -13.2,-38.6 0,-27.2 14.8,-41.4 15,-14.200002 40,-14.200002 11,0 20.59998,2.600002 9.8,2.4 15,5.8 v 31.4 l -21.4,-1 -2.4,-13.2 q -0.4,-2.6 -2.39998,-3.2 -4.2,-1.4 -10.2,-1.4 -9.8,0 -16,7.6 -6.2,7.6 -6.2,24 0,33.4 25.8,33.4 11.59998,0 24.99998,-5.8 z"
-           style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:200px;line-height:1.25;font-family:Adelle;-inkscape-font-specification:'Adelle Bold';letter-spacing:0px;word-spacing:0px;fill:#3e2c00;fill-opacity:1;stroke:none;stroke-width:0.75"
+           style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:200px;line-height:1.25;font-family:Adelle;-inkscape-font-specification:'Adelle Bold';letter-spacing:0px;word-spacing:0px;fill:#d1d1d1;fill-opacity:1;stroke:none;stroke-width:0.75"
            id="path4777"
            inkscape:connector-curvature="0" />
         <path
            d="m 1151.8635,204.74518 h -43.4 v -65.2 q 0,-17 -10.6,-17 -10.6,0 -20.8,7.4 v 53.6 q 0,2.4 0.4,3.2 0.6,0.6 2.8,0.8 l 9.6,1.4 v 15.8 h -55.2 v -15.8 l 9,-1.4 q 2,-0.2 2.6,-1 0.6,-0.8 0.6,-3 V 77.945178 q 0,-3.4 -2.6,-4.2 l -11,-3.8 2.2,-16.2 h 41.2 v 56.600002 l 1,0.2 q 14.6,-12.000002 32,-12.000002 15.4,0 22.2,8.200002 6.8,8 6.8,24.2 v 52.6 q 0,2.4 0.4,3.2 0.6,0.6 2.8,0.8 l 10,1.4 z"
-           style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:200px;line-height:1.25;font-family:Adelle;-inkscape-font-specification:'Adelle Bold';letter-spacing:0px;word-spacing:0px;fill:#3e2c00;fill-opacity:1;stroke:none;stroke-width:0.75"
+           style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:200px;line-height:1.25;font-family:Adelle;-inkscape-font-specification:'Adelle Bold';letter-spacing:0px;word-spacing:0px;fill:#d1d1d1;fill-opacity:1;stroke:none;stroke-width:0.75"
            id="path4779"
            inkscape:connector-curvature="0" />
         <path
            d="m 1245.0632,177.14518 7.4,19.8 q -21,10.2 -41,10.2 -27.4,0 -39.6,-14.8 -12.2,-15 -12.2,-40.4 0,-26 13.8,-39.6 14,-13.800002 35.8,-13.800002 20.8,0 32.4,11.800002 11.6,11.6 11.6,36.6 0,5.4 -0.4,13.4 h -61.2 q 1.6,23.6 23.6,23.6 11.4,0 29.8,-6.8 z m -53.2,-35.8 h 31.8 q -0.2,-21.2 -15,-21.2 -15.2,0 -16.8,21.2 z"
-           style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:200px;line-height:1.25;font-family:Adelle;-inkscape-font-specification:'Adelle Bold';letter-spacing:0px;word-spacing:0px;fill:#3e2c00;fill-opacity:1;stroke:none;stroke-width:0.75"
+           style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:200px;line-height:1.25;font-family:Adelle;-inkscape-font-specification:'Adelle Bold';letter-spacing:0px;word-spacing:0px;fill:#d1d1d1;fill-opacity:1;stroke:none;stroke-width:0.75"
            id="path4781"
            inkscape:connector-curvature="0" />
         <path
            d="m 1335.8631,181.54518 5.4,17.6 q -16.4,8 -32.6,8 -17.6,0 -25.2,-7.6 -7.6,-7.6 -7.6,-24.6 v -52.4 q 0,-2 -1.6,-2 h -14 v -17.8 q 13.2,-1.4 19.2,-8.800002 6,-7.4 7.6,-23.8 h 19 v 28.4 q 0,2.000002 1.6,2.000002 h 28.2 v 20 h -29.8 v 47.8 q 0,9.2 2.8,12.8 2.8,3.6 10.8,3.6 7.6,0 16.2,-3.2 z"
-           style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:200px;line-height:1.25;font-family:Adelle;-inkscape-font-specification:'Adelle Bold';letter-spacing:0px;word-spacing:0px;fill:#3e2c00;fill-opacity:1;stroke:none;stroke-width:0.75"
+           style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:200px;line-height:1.25;font-family:Adelle;-inkscape-font-specification:'Adelle Bold';letter-spacing:0px;word-spacing:0px;fill:#d1d1d1;fill-opacity:1;stroke:none;stroke-width:0.75"
            id="path4783"
            inkscape:connector-curvature="0" />
         <path
            d="m 1430.2626,177.14518 7.4,19.8 q -21,10.2 -41,10.2 -27.4,0 -39.6,-14.8 -12.2,-15 -12.2,-40.4 0,-26 13.8,-39.6 14,-13.800002 35.8,-13.800002 20.8,0 32.4,11.800002 11.6,11.6 11.6,36.6 0,5.4 -0.4,13.4 h -61.2 q 1.6,23.6 23.6,23.6 11.4,0 29.8,-6.8 z m -53.2,-35.8 h 31.8 q -0.2,-21.2 -15,-21.2 -15.2,0 -16.8,21.2 z"
-           style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:200px;line-height:1.25;font-family:Adelle;-inkscape-font-specification:'Adelle Bold';letter-spacing:0px;word-spacing:0px;fill:#3e2c00;fill-opacity:1;stroke:none;stroke-width:0.75"
+           style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:200px;line-height:1.25;font-family:Adelle;-inkscape-font-specification:'Adelle Bold';letter-spacing:0px;word-spacing:0px;fill:#d1d1d1;fill-opacity:1;stroke:none;stroke-width:0.75"
            id="path4785"
            inkscape:connector-curvature="0" />
       </g>
diff --git a/requirements/coverage.txt b/requirements/coverage.txt
index 5e7d98e..57e8d25 100644
--- a/requirements/coverage.txt
+++ b/requirements/coverage.txt
@@ -1,5 +1,6 @@
 coverage==6.2; python_version <= '3.6'
-coverage==7.2.7; python_version >= '3.7'
+coverage==7.2.7; python_version >= '3.7' and python_version < '3.8'
+coverage==7.3.0; python_version >= '3.8'
 
 pytest==7.0.1; python_version <= '3.6'
 pytest==7.4.0; python_version >= '3.7'
diff --git a/requirements/mypy.txt b/requirements/mypy.txt
index 7ad91e5..d33f980 100644
--- a/requirements/mypy.txt
+++ b/requirements/mypy.txt
@@ -1,6 +1,6 @@
 mypy==0.971; python_version <= '3.6'
 mypy==1.4.1; python_version >= '3.7' and python_version < '3.8'
-mypy==1.5.0; python_version >= '3.8'
+mypy==1.5.1; python_version >= '3.8'
 
 pytest==7.0.1; python_version <= '3.6'
 pytest==7.4.0; python_version >= '3.7'
diff --git a/requirements/pypi-deploy.txt b/requirements/pypi-deploy.txt
index f77cc3f..34b0fd7 100644
--- a/requirements/pypi-deploy.txt
+++ b/requirements/pypi-deploy.txt
@@ -1,2 +1,2 @@
 twine==4.0.2
-wheel==0.41.1
+wheel==0.41.2
diff --git a/requirements/vulture-check.txt b/requirements/vulture-check.txt
index 7a6f752..b53ea43 100644
--- a/requirements/vulture-check.txt
+++ b/requirements/vulture-check.txt
@@ -1,1 +1,1 @@
-vulture==2.8
+vulture==2.9.1
diff --git a/tox.ini b/tox.ini
index 9f64b9d..51f558f 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,8 +1,8 @@
 [tox]
 # Environments selected for frequent execution during development
 # Let's still include pep8-check despite a preceding autopep8 run to filter out certain errors
-# (like W293 blank line in multiline strings contains whitespace)
-# that don't seem to ever get fixed by autopep8.
+# (like W293 blank line in multiline strings contains whitespace, or FS003 f-string missing prefix)
+# that don't get fixed by autopep8.
 envlist = pep8,isort,pep8-check,mypy,vulture-check,sphinx-man,py-docs
 minversion = 2.3.2
 skipsdist = True


Test patch:
diff --git a/tests/base_test.py b/tests/base_test.py
index 1be3636..b60c780 100644
--- a/tests/base_test.py
+++ b/tests/base_test.py
@@ -133,7 +133,11 @@ class GitRepositorySandbox:
         return self
 
     def add_remote(self, remote: str, url: str) -> "GitRepositorySandbox":
-        self.execute(f'git remote add {remote} {url}')
+        self.execute(f'git remote add {remote} "{url}"')
+        return self
+
+    def set_remote_url(self, remote: str, url: str) -> "GitRepositorySandbox":
+        self.execute(f'git remote set-url {remote} "{url}"')
         return self
 
     def remove_remote(self, remote: str = 'origin') -> "GitRepositorySandbox":
@@ -164,6 +168,10 @@ class GitRepositorySandbox:
         self.execute(f'git config {key} "{value}"')
         return self
 
+    def unset_git_config_key(self, key: str) -> "GitRepositorySandbox":
+        self.execute(f'git config --unset {key}')
+        return self
+
     def read_file(self, file_name: str) -> str:
         with open(file_name) as f:
             return f.read()
diff --git a/tests/mockers_github.py b/tests/mockers_github.py
index 10ed7ff..8331c64 100644
--- a/tests/mockers_github.py
+++ b/tests/mockers_github.py
@@ -7,9 +7,9 @@ from urllib.error import HTTPError
 from urllib.parse import ParseResult, parse_qs, urlencode, urlparse
 from urllib.request import Request
 
-from git_machete.github import GitHubToken, RemoteAndOrganizationAndRepository
+from git_machete.github import GitHubToken, OrganizationAndRepository
 
-mock_repository_info: Dict[str, str] = {'full_name': 'testing/checkout_prs',
+mock_repository_info: Dict[str, str] = {'full_name': 'tester/repo_sandbox',
                                         'html_url': 'https://github.com/tester/repo_sandbox.git'}
 
 
@@ -21,8 +21,8 @@ def mock_github_token_for_domain_fake(_domain: str) -> GitHubToken:
     return GitHubToken(value='ghp_dummy_token', provider='dummy_provider')
 
 
-def mock_from_url(domain: str, url: str, remote: str) -> "RemoteAndOrganizationAndRepository":  # noqa: U100
-    return RemoteAndOrganizationAndRepository(remote, "example-org", "example-repo")
+def mock_from_url(domain: str, url: str) -> "OrganizationAndRepository":  # noqa: U100
+    return OrganizationAndRepository("example-org", "example-repo")
 
 
 def mock_shutil_which(path: Optional[str]) -> Callable[[Any], Optional[str]]:
diff --git a/tests/test_github.py b/tests/test_github.py
index 9ff57cf..4b2e286 100644
--- a/tests/test_github.py
+++ b/tests/test_github.py
@@ -1,10 +1,12 @@
+from contextlib import contextmanager
 from textwrap import dedent
+from typing import Iterator
 from unittest.mock import mock_open
 
 from pytest_mock import MockerFixture
 
 from git_machete.github import (GitHubClient, GitHubToken,
-                                RemoteAndOrganizationAndRepository)
+                                OrganizationAndRepository)
 from tests.base_test import BaseTest
 from tests.mockers import (assert_failure, assert_success, launch_command,
                            mock__popen_cmd_with_fixed_results,
@@ -29,16 +31,15 @@ class TestGitHub(BaseTest):
         urls = urls + [url + '.git' for url in urls]
 
         for url in urls:
-            remote_and_organization_and_repository = RemoteAndOrganizationAndRepository.from_url(
-                domain=GitHubClient.DEFAULT_GITHUB_DOMAIN, url=url, remote='origin')
-            assert remote_and_organization_and_repository is not None
-            assert remote_and_organization_and_repository.organization == organization
-            assert remote_and_organization_and_repository.repository == repository
+            org_and_repo = OrganizationAndRepository.from_url(domain=GitHubClient.DEFAULT_GITHUB_DOMAIN, url=url)
+            assert org_and_repo is not None
+            assert org_and_repo.organization == organization
+            assert org_and_repo.repository == repository
 
     PR_COUNT_FOR_TEST_GITHUB_API_PAGINATION = 12
 
     github_api_state_for_test_github_api_pagination = MockGitHubAPIState([{
-        'head': {'ref': f'feature_{i:02d}', 'repo': {'full_name': 'testing/checkout_prs',
+        'head': {'ref': f'feature_{i:02d}', 'repo': {'full_name': 'tester/repo_sandbox',
                                                      'html_url': 'https://github.com/tester/repo_sandbox.git'}},
         'user': {'login': 'some_other_user'},
         'base': {'ref': 'develop'},
@@ -51,7 +52,7 @@ class TestGitHub(BaseTest):
         self.patch_symbol(mocker, 'builtins.input', mock_input_returning_y)
         self.patch_symbol(mocker, 'git_machete.github.GitHubClient.MAX_PULLS_PER_PAGE_COUNT', 3)
         self.patch_symbol(mocker, 'git_machete.github.GitHubToken.for_domain', mock_github_token_for_domain_none)
-        self.patch_symbol(mocker, 'git_machete.github.RemoteAndOrganizationAndRepository.from_url', mock_from_url)
+        self.patch_symbol(mocker, 'git_machete.github.OrganizationAndRepository.from_url', mock_from_url)
         self.patch_symbol(mocker, 'urllib.request.urlopen', mock_urlopen(self.github_api_state_for_test_github_api_pagination))
 
         (
@@ -79,7 +80,7 @@ class TestGitHub(BaseTest):
 
     def test_github_enterprise_domain_unauthorized_without_token(self, mocker: MockerFixture) -> None:
         self.patch_symbol(mocker, 'git_machete.github.GitHubToken.for_domain', mock_github_token_for_domain_none)
-        self.patch_symbol(mocker, 'git_machete.github.RemoteAndOrganizationAndRepository.from_url', mock_from_url)
+        self.patch_symbol(mocker, 'git_machete.github.OrganizationAndRepository.from_url', mock_from_url)
         self.patch_symbol(mocker, 'urllib.request.urlopen', mock_urlopen(MockGitHubAPIState([])))
 
         self.repo_sandbox.set_git_config_key('machete.github.domain', '403.example.org')
@@ -94,7 +95,7 @@ class TestGitHub(BaseTest):
 
     def test_github_enterprise_domain_unauthorized_with_token(self, mocker: MockerFixture) -> None:
         self.patch_symbol(mocker, 'git_machete.github.GitHubToken.for_domain', mock_github_token_for_domain_fake)
-        self.patch_symbol(mocker, 'git_machete.github.RemoteAndOrganizationAndRepository.from_url', mock_from_url)
+        self.patch_symbol(mocker, 'git_machete.github.OrganizationAndRepository.from_url', mock_from_url)
         self.patch_symbol(mocker, 'urllib.request.urlopen', mock_urlopen(MockGitHubAPIState([])))
 
         self.repo_sandbox.set_git_config_key('machete.github.domain', '403.example.org')
@@ -121,7 +122,7 @@ class TestGitHub(BaseTest):
 
     def test_github_enterprise_domain(self, mocker: MockerFixture) -> None:
         self.patch_symbol(mocker, 'git_machete.github.GitHubToken.for_domain', mock_github_token_for_domain_fake)
-        self.patch_symbol(mocker, 'git_machete.github.RemoteAndOrganizationAndRepository.from_url', mock_from_url)
+        self.patch_symbol(mocker, 'git_machete.github.OrganizationAndRepository.from_url', mock_from_url)
         self.patch_symbol(mocker, 'urllib.request.urlopen', mock_urlopen(self.github_api_state_for_test_github_enterprise_domain))
 
         github_enterprise_domain = 'git.example.org'
@@ -138,8 +139,47 @@ class TestGitHub(BaseTest):
         )
         launch_command('github', 'checkout-prs', '--all')
 
+    def test_github_invalid_config(self) -> None:
+        @contextmanager
+        def git_config_key(key: str, value: str) -> Iterator[None]:
+            self.repo_sandbox.set_git_config_key(key, value)
+            yield
+            self.repo_sandbox.unset_git_config_key(key)
+
+        with git_config_key('machete.github.organization', "example-org"):
+            assert_failure(
+                ['github', 'checkout-prs', '--all'],
+                "machete.github.organization git config key is present, but machete.github.repository is missing. "
+                "Both keys must be present to take effect")
+
+        with git_config_key('machete.github.repository', "example-repo"):
+            assert_failure(
+                ['github', 'checkout-prs', '--all'],
+                "machete.github.repository git config key is present, but machete.github.organization is missing. "
+                "Both keys must be present to take effect")
+
+        with git_config_key('machete.github.remote', "non-existent-remote"):
+            assert_failure(
+                ['github', 'checkout-prs', '--all'],
+                "machete.github.remote git config key points to non-existent-remote remote, but such remote does not exist")
+
+        with git_config_key('machete.github.organization', "example-org"):
+            with git_config_key('machete.github.repository', "example-repo"):
+                assert_failure(
+                    ['github', 'checkout-prs', '--all'],
+                    'Both machete.github.organization and machete.github.repository git config keys are defined, '
+                    'but no remote seems to correspond to example-org/example-repo (organization/repository) on GitHub.\n'
+                    'Consider pointing to the remote via machete.github.remote config key')
+
+        self.repo_sandbox.add_remote("new-origin", "https://gitlab.com/example-org/example-repo.git")  # not a valid GitHub repo URL
+        with git_config_key('machete.github.remote', "new-origin"):
+            assert_failure(
+                ['github', 'checkout-prs', '--all'],
+                'machete.github.remote git config key points to new-origin remote, '
+                'but its URL https://gitlab.com/example-org/example-repo.git does not correspond to a valid GitHub repository')
+
     def test_github_token_retrieval_order(self, mocker: MockerFixture) -> None:
-        self.patch_symbol(mocker, 'git_machete.github.RemoteAndOrganizationAndRepository.from_url', mock_from_url)
+        self.patch_symbol(mocker, 'git_machete.github.OrganizationAndRepository.from_url', mock_from_url)
         self.patch_symbol(mocker, 'os.path.isfile', lambda _file: False)
         self.patch_symbol(mocker, 'shutil.which', mock_shutil_which(None))
         self.patch_symbol(mocker, 'urllib.request.urlopen', mock_urlopen(self.github_api_state_for_test_github_enterprise_domain))
diff --git a/tests/test_github_anno_prs.py b/tests/test_github_anno_prs.py
index c4a8868..19f484d 100644
--- a/tests/test_github_anno_prs.py
+++ b/tests/test_github_anno_prs.py
@@ -113,7 +113,7 @@ class TestGitHubAnnoPRs(BaseTest):
         (
             self.repo_sandbox
                 .remove_remote('new_origin')
-                .set_git_config_key('machete.github.remote', 'custom_origin')
+                .set_git_config_key('machete.github.remote', 'origin')
                 .set_git_config_key('machete.github.organization', 'custom_user')
                 .set_git_config_key('machete.github.repository', 'custom_repo')
         )
diff --git a/tests/test_github_checkout_prs.py b/tests/test_github_checkout_prs.py
index 6a7a833..16a813e 100644
--- a/tests/test_github_checkout_prs.py
+++ b/tests/test_github_checkout_prs.py
@@ -3,7 +3,7 @@ from tempfile import mkdtemp
 
 from pytest_mock import MockerFixture
 
-from git_machete.github import GitHubClient, RemoteAndOrganizationAndRepository
+from git_machete.github import GitHubClient, OrganizationAndRepository
 from tests.base_test import BaseTest, GitRepositorySandbox
 from tests.mockers import (assert_failure, assert_success, launch_command,
                            rewrite_branch_layout_file)
@@ -81,7 +81,7 @@ class TestGitHubCheckoutPRs(BaseTest):
             },
             {
                 'head': {'ref': 'bugfix/remove-n-option',
-                         'repo': {'full_name': 'testing/checkout_prs', 'html_url': GitRepositorySandbox.second_remote_path}},
+                         'repo': {'full_name': 'tester/repo_sandbox', 'html_url': GitRepositorySandbox.second_remote_path}},
                 'user': {'login': 'some_other_user'},
                 'base': {'ref': 'develop'},
                 'number': '5',
@@ -92,7 +92,7 @@ class TestGitHubCheckoutPRs(BaseTest):
     )
 
     def test_github_checkout_prs(self, mocker: MockerFixture) -> None:
-        self.patch_symbol(mocker, 'git_machete.github.RemoteAndOrganizationAndRepository.from_url', mock_from_url)
+        self.patch_symbol(mocker, 'git_machete.github.OrganizationAndRepository.from_url', mock_from_url)
         self.patch_symbol(mocker, 'git_machete.github.GitHubToken.for_domain', mock_github_token_for_domain_none)
         self.patch_symbol(mocker, 'urllib.request.urlopen', mock_urlopen(self.github_api_state_for_test_checkout_prs))
 
@@ -292,12 +292,13 @@ class TestGitHubCheckoutPRs(BaseTest):
             """
         )
 
-        # check against wrong pr number
-        remote_org_repo = RemoteAndOrganizationAndRepository.from_url(domain=GitHubClient.DEFAULT_GITHUB_DOMAIN,
-                                                                      url=self.repo_sandbox.remote_path,
-                                                                      remote='origin')
-        assert remote_org_repo is not None
-        expected_error_message = f"PR #100 is not found in repository {remote_org_repo.organization}/{remote_org_repo.repository}"
+        # check against wrong PR number
+        org_repo = OrganizationAndRepository.from_url(
+            domain=GitHubClient.DEFAULT_GITHUB_DOMAIN,
+            url=self.repo_sandbox.remote_path)
+
+        assert org_repo is not None
+        expected_error_message = f"PR #100 is not found in repository {org_repo.organization}/{org_repo.repository}"
         assert_failure(['github', 'checkout-prs', '100'], expected_error_message)
 
         assert_failure(['github', 'checkout-prs', '19', '100'], expected_error_message)
@@ -320,10 +321,10 @@ class TestGitHubCheckoutPRs(BaseTest):
         )
 
         expected_error_message = "Could not check out PR #5 because its head branch bugfix/remove-n-option " \
-                                 "is already deleted from testing."
+                                 "is already deleted from tester."
         assert_failure(['github', 'checkout-prs', '5'], expected_error_message)
 
-        # Check against pr come from fork
+        # Check against PR coming from fork
         (
             self.repo_sandbox
             .new_branch('bugfix/remove-n-option')
@@ -369,7 +370,7 @@ class TestGitHubCheckoutPRs(BaseTest):
             },
             {
                 'head': {'ref': 'sphinx_export',
-                         'repo': {'full_name': 'testing/checkout_prs', 'html_url': GitRepositorySandbox.second_remote_path}},
+                         'repo': {'full_name': 'tester/repo_sandbox', 'html_url': GitRepositorySandbox.second_remote_path}},
                 'user': {'login': 'some_other_user'},
                 'base': {'ref': 'comments/add_docstrings'},
                 'number': '23',
@@ -380,7 +381,7 @@ class TestGitHubCheckoutPRs(BaseTest):
     )
 
     def test_github_checkout_prs_freshly_cloned(self, mocker: MockerFixture) -> None:
-        self.patch_symbol(mocker, 'git_machete.github.RemoteAndOrganizationAndRepository.from_url', mock_from_url)
+        self.patch_symbol(mocker, 'git_machete.github.OrganizationAndRepository.from_url', mock_from_url)
         self.patch_symbol(mocker, 'urllib.request.urlopen', mock_urlopen(self.github_api_state_for_test_github_checkout_prs_fresh_repo))
 
         (
@@ -498,7 +499,7 @@ class TestGitHubCheckoutPRs(BaseTest):
 
     def test_github_checkout_prs_from_fork_with_deleted_repo(self, mocker: MockerFixture) -> None:
         # need to mock fetch_ref due to underlying `git fetch pull/head` calls
-        self.patch_symbol(mocker, 'git_machete.github.RemoteAndOrganizationAndRepository.from_url', mock_from_url)
+        self.patch_symbol(mocker, 'git_machete.github.OrganizationAndRepository.from_url', mock_from_url)
         self.patch_symbol(mocker, 'urllib.request.urlopen',
                           mock_urlopen(self.github_api_state_for_test_github_checkout_prs_from_fork_with_deleted_repo))
 
@@ -605,7 +606,7 @@ class TestGitHubCheckoutPRs(BaseTest):
             },
             {
                 'head': {'ref': 'bugfix/remove-n-option',
-                         'repo': {'full_name': 'testing/checkout_prs', 'html_url': GitRepositorySandbox.second_remote_path}},
+                         'repo': {'full_name': 'tester/repo_sandbox', 'html_url': GitRepositorySandbox.second_remote_path}},
                 'user': {'login': 'some_other_user'},
                 'base': {'ref': 'develop'},
                 'number': '5',
@@ -616,7 +617,7 @@ class TestGitHubCheckoutPRs(BaseTest):
     )
 
     def test_github_checkout_prs_of_current_user_and_other_users(self, mocker: MockerFixture) -> None:
-        self.patch_symbol(mocker, 'git_machete.github.RemoteAndOrganizationAndRepository.from_url', mock_from_url)
+        self.patch_symbol(mocker, 'git_machete.github.OrganizationAndRepository.from_url', mock_from_url)
         self.patch_symbol(mocker, 'git_machete.github.GitHubToken.for_domain', mock_github_token_for_domain_fake)
         self.patch_symbol(mocker, 'urllib.request.urlopen',
                           mock_urlopen(self.github_api_state_for_test_github_checkout_prs_of_current_user_and_other_users))
@@ -766,7 +767,7 @@ class TestGitHubCheckoutPRs(BaseTest):
         )
 
     def test_github_checkout_prs_misc_failures_and_warns(self, mocker: MockerFixture) -> None:
-        self.patch_symbol(mocker, 'git_machete.github.RemoteAndOrganizationAndRepository.from_url', mock_from_url)
+        self.patch_symbol(mocker, 'git_machete.github.OrganizationAndRepository.from_url', mock_from_url)
         self.patch_symbol(mocker, 'urllib.request.urlopen', mock_urlopen(MockGitHubAPIState([])))
 
         self.patch_symbol(mocker, 'git_machete.github.GitHubToken.for_domain', mock_github_token_for_domain_none)
@@ -806,12 +807,12 @@ class TestGitHubCheckoutPRs(BaseTest):
             """
         )
 
-    github_api_state_for_test_github_checkout_prs_remote_already_added = MockGitHubAPIState(
+    github_api_state_for_test_github_checkout_prs_single_pr = MockGitHubAPIState(
         [
             {
-                'head': {'ref': 'chore/redundant_checks', 'repo': mock_repository_info},
+                'head': {'ref': 'develop', 'repo': mock_repository_info},
                 'user': {'login': 'some_other_user'},
-                'base': {'ref': 'restrict_access'},
+                'base': {'ref': 'master'},
                 'number': '18',
                 'html_url': 'www.github.com',
                 'state': 'open'
@@ -822,7 +823,7 @@ class TestGitHubCheckoutPRs(BaseTest):
     def test_github_checkout_prs_remote_already_added(self, mocker: MockerFixture) -> None:
         self.patch_symbol(mocker, 'git_machete.git_operations.GitContext.fetch_remote', lambda _self, _remote: None)
         self.patch_symbol(mocker, 'urllib.request.urlopen', mock_urlopen(
-            self.github_api_state_for_test_github_checkout_prs_remote_already_added))
+            self.github_api_state_for_test_github_checkout_prs_single_pr))
         (
             self.repo_sandbox
             .remove_remote("origin")
@@ -830,5 +831,54 @@ class TestGitHubCheckoutPRs(BaseTest):
         )
         assert_failure(
             ["github", "checkout-prs", "--all"],
-            "Could not check out PR #18 because its head branch chore/redundant_checks is already deleted from origin-1."
+            "Could not check out PR #18 because its head branch develop is already deleted from origin-1."
+        )
+
+        (
+            self.repo_sandbox
+            .remove_remote("origin-1")
+            .add_remote("tester", 'https://github.com/tester/lolxd.git')
+        )
+        assert_failure(
+            ["github", "checkout-prs", "--all"],
+            "Could not check out PR #18 because its head branch develop is already deleted from tester."
+        )
+
+    def test_github_checkout_prs_org_and_repo_from_config(self, mocker: MockerFixture) -> None:
+        self.patch_symbol(mocker, 'git_machete.git_operations.GitContext.fetch_remote', lambda _self, _remote: None)
+        self.patch_symbol(mocker, 'urllib.request.urlopen', mock_urlopen(
+            self.github_api_state_for_test_github_checkout_prs_single_pr))
+
+        (
+            self.repo_sandbox
+            .new_branch("master").commit()
+            .new_branch("develop").commit().push()
+        )
+
+        self.repo_sandbox.set_remote_url("origin", "https://github.com/example-org/example-repo.git")
+        self.repo_sandbox.set_git_config_key('machete.github.organization', "example-org")
+        self.repo_sandbox.set_git_config_key('machete.github.repository', "example-repo")
+        assert_success(
+            ['github', 'checkout-prs', '--all'],
+            'Checking for open GitHub PRs... OK\n'
+            'Pull request #18 checked out at local branch develop\n'
+        )
+
+    def test_github_checkout_prs_remote_from_config(self, mocker: MockerFixture) -> None:
+        self.patch_symbol(mocker, 'git_machete.git_operations.GitContext.fetch_remote', lambda _self, _remote: None)
+        self.patch_symbol(mocker, 'urllib.request.urlopen', mock_urlopen(
+            self.github_api_state_for_test_github_checkout_prs_single_pr))
+
+        (
+            self.repo_sandbox
+            .new_branch("master").commit()
+            .new_branch("develop").commit().push()
+        )
+
+        self.repo_sandbox.set_remote_url("origin", "https://github.com/example-org/example-repo.git")
+        self.repo_sandbox.set_git_config_key('machete.github.remote', "origin")
+        assert_success(
+            ['github', 'checkout-prs', '--all'],
+            'Checking for open GitHub PRs... OK\n'
+            'Pull request #18 checked out at local branch develop\n'
         )
diff --git a/tests/test_github_create_pr.py b/tests/test_github_create_pr.py
index 8177f20..eae35cb 100644
--- a/tests/test_github_create_pr.py
+++ b/tests/test_github_create_pr.py
@@ -32,7 +32,7 @@ class TestGitHubCreatePR(BaseTest):
     def test_github_create_pr(self, mocker: MockerFixture) -> None:
         self.patch_symbol(mocker, 'builtins.input', mock_input_returning_y)
         self.patch_symbol(mocker, 'git_machete.github.GitHubToken.for_domain', mock_github_token_for_domain_fake)
-        self.patch_symbol(mocker, 'git_machete.github.RemoteAndOrganizationAndRepository.from_url', mock_from_url)
+        self.patch_symbol(mocker, 'git_machete.github.OrganizationAndRepository.from_url', mock_from_url)
         self.patch_symbol(mocker, 'urllib.request.urlopen', mock_urlopen(self.github_api_state_for_test_create_pr))
 
         (
@@ -116,7 +116,7 @@ class TestGitHubCreatePR(BaseTest):
               x-drop-constraint (untracked)
             """,
         )
-        #  untracked state (can only create pr when branch is pushed)
+        # untracked state (can only create PR when branch is pushed)
         self.repo_sandbox.check_out('chore/fields')
 
         self.repo_sandbox.write_to_file(".git/info/milestone", "42")
@@ -297,7 +297,7 @@ class TestGitHubCreatePR(BaseTest):
 
     def test_github_create_pr_missing_base_branch_on_remote(self, mocker: MockerFixture) -> None:
         self.patch_symbol(mocker, 'builtins.input', mock_input_returning_y)
-        self.patch_symbol(mocker, 'git_machete.github.RemoteAndOrganizationAndRepository.from_url', mock_from_url)
+        self.patch_symbol(mocker, 'git_machete.github.OrganizationAndRepository.from_url', mock_from_url)
         self.patch_symbol(mocker, 'git_machete.github.GitHubToken.for_domain', mock_github_token_for_domain_none)
         self.patch_symbol(mocker, 'urllib.request.urlopen', mock_urlopen(
             self.github_api_state_for_test_create_pr_missing_base_branch_on_remote))
@@ -351,7 +351,7 @@ class TestGitHubCreatePR(BaseTest):
     )
 
     def test_github_create_pr_with_multiple_non_origin_remotes(self, mocker: MockerFixture) -> None:
-        self.patch_symbol(mocker, 'git_machete.github.RemoteAndOrganizationAndRepository.from_url', mock_from_url)
+        self.patch_symbol(mocker, 'git_machete.github.OrganizationAndRepository.from_url', mock_from_url)
         self.patch_symbol(mocker, 'git_machete.github.GitHubToken.for_domain', mock_github_token_for_domain_none)
         self.patch_symbol(mocker, 'urllib.request.urlopen',
                           mock_urlopen(self.github_api_state_for_test_github_create_pr_with_multiple_non_origin_remotes))
@@ -412,6 +412,14 @@ class TestGitHubCreatePR(BaseTest):
             "Could not establish remote repository, pull request creation interrupted."
         )
 
+        self.patch_symbol(mocker, 'builtins.input', mock_input_returning('1', 'n'))
+        assert_failure(
+            ['github', 'create-pr'],
+            "Multiple non-origin remotes correspond to GitHub in this repository: origin_1, origin_2 -> aborting.\n"
+            "You can also select the repository by providing some or all of git config keys: "
+            "machete.github.{domain,remote,organization,repository}.\n"  # noqa: FS003
+        )
+
         expected_result = """
         Branch feature is untracked and there's no origin repository.
         [1] origin_1
@@ -591,7 +599,7 @@ class TestGitHubCreatePR(BaseTest):
         )
 
     def test_github_create_pr_for_no_push_qualifier(self, mocker: MockerFixture) -> None:
-        self.patch_symbol(mocker, 'git_machete.github.RemoteAndOrganizationAndRepository.from_url', mock_from_url)
+        self.patch_symbol(mocker, 'git_machete.github.OrganizationAndRepository.from_url', mock_from_url)
         self.patch_symbol(mocker, 'git_machete.github.GitHubToken.for_domain', mock_github_token_for_domain_none)
         self.patch_symbol(mocker, 'urllib.request.urlopen', mock_urlopen(MockGitHubAPIState([])))
 
@@ -627,7 +635,7 @@ class TestGitHubCreatePR(BaseTest):
         )
 
     def test_github_create_pr_for_branch_behind_remote(self, mocker: MockerFixture) -> None:
-        self.patch_symbol(mocker, 'git_machete.github.RemoteAndOrganizationAndRepository.from_url', mock_from_url)
+        self.patch_symbol(mocker, 'git_machete.github.OrganizationAndRepository.from_url', mock_from_url)
         self.patch_symbol(mocker, 'git_machete.github.GitHubToken.for_domain', mock_github_token_for_domain_none)
         self.patch_symbol(mocker, 'urllib.request.urlopen', mock_urlopen(MockGitHubAPIState([])))
 
@@ -691,7 +699,7 @@ class TestGitHubCreatePR(BaseTest):
         )
 
     def test_github_create_pr_for_branch_diverged_from_and_older_than_remote(self, mocker: MockerFixture) -> None:
-        self.patch_symbol(mocker, 'git_machete.github.RemoteAndOrganizationAndRepository.from_url', mock_from_url)
+        self.patch_symbol(mocker, 'git_machete.github.OrganizationAndRepository.from_url', mock_from_url)
         self.patch_symbol(mocker, 'git_machete.github.GitHubToken.for_domain', mock_github_token_for_domain_none)
         self.patch_symbol(mocker, 'urllib.request.urlopen', mock_urlopen(MockGitHubAPIState([])))
 
diff --git a/tests/test_github_retarget_pr.py b/tests/test_github_retarget_pr.py
index 4b6b6a7..52831e9 100644
--- a/tests/test_github_retarget_pr.py
+++ b/tests/test_github_retarget_pr.py
@@ -226,7 +226,7 @@ class TestGitHubRetargetPR(BaseTest):
         launch_command('github', 'retarget-pr', '--branch', 'branch-without-pr', '--ignore-if-missing')
 
     def test_github_retarget_pr_multiple_non_origin_remotes(self, mocker: MockerFixture) -> None:
-        self.patch_symbol(mocker, 'git_machete.github.RemoteAndOrganizationAndRepository.from_url', mock_from_url)
+        self.patch_symbol(mocker, 'git_machete.github.OrganizationAndRepository.from_url', mock_from_url)
         self.patch_symbol(mocker, 'urllib.request.urlopen', mock_urlopen(self.github_api_state_for_test_retarget_pr))
 
         branchs_first_commit_msg = "First commit on branch."
@@ -357,7 +357,7 @@ class TestGitHubRetargetPR(BaseTest):
     }])
 
     def test_github_retarget_pr_root_branch(self, mocker: MockerFixture) -> None:
-        self.patch_symbol(mocker, 'git_machete.github.RemoteAndOrganizationAndRepository.from_url', mock_from_url)
+        self.patch_symbol(mocker, 'git_machete.github.OrganizationAndRepository.from_url', mock_from_url)
         self.patch_symbol(mocker, 'urllib.request.urlopen', mock_urlopen(self.github_api_state_for_test_retarget_pr_root_branch))
 
         self.repo_sandbox.new_branch("master").commit()
diff --git a/tests/test_github_sync.py b/tests/test_github_sync.py
index bc75d01..d86dac5 100644
--- a/tests/test_github_sync.py
+++ b/tests/test_github_sync.py
@@ -25,7 +25,7 @@ class TestGitHubSync(BaseTest):
 
     def test_github_sync(self, mocker: MockerFixture) -> None:
         self.patch_symbol(mocker, 'builtins.input', mock_input_returning_y)
-        self.patch_symbol(mocker, 'git_machete.github.RemoteAndOrganizationAndRepository.from_url', mock_from_url)
+        self.patch_symbol(mocker, 'git_machete.github.OrganizationAndRepository.from_url', mock_from_url)
         self.patch_symbol(mocker, 'git_machete.github.GitHubToken.for_domain', mock_github_token_for_domain_fake)
         self.patch_symbol(mocker, 'urllib.request.urlopen', mock_urlopen(self.github_api_state_for_test_github_sync))