Repository: VirtusLab/git-machete
Pull request #804 (2023-02-03 18:36:35)

Release v3.15.0


Patch:
diff --git a/README.md b/README.md
index 1061cf2..69490b6 100644
--- a/README.md
+++ b/README.md
@@ -42,19 +42,19 @@ a port into a plugin for the IntelliJ Platform products, including PyCharm, WebS
 
 ## Install
 
-We suggest a couple of alternative ways of installation.
+We provide a couple of alternative ways of installation.
 
 **Instructions for installing bash, zsh, and fish completion scripts are provided in [completion/README.md](completion/README.md).**
 
 git-machete requires Python >= 3.6. Python 2.x is no longer supported.
 
-### Using Homebrew (macOS)
+### Using Homebrew (macOS & most Linux distributions)
 
 ```shell script
 brew install git-machete
 ```
 
-### Using Snappy (most Linux distributions)
+### Using snap (most Linux distributions)
 
 **Tip:** check the [guide on installing snapd](https://snapcraft.io/docs/installing-snapd) if you don't have Snap support set up yet in your system.
 
@@ -66,7 +66,7 @@ It can also be installed via Ubuntu Software (simply search for `git-machete`).
 
 **Note:** classic confinement is necessary to ensure access to the editor installed in the system (to edit e.g. .git/machete file or rebase TODO list).
 
-### Using PPA (Ubuntu)
+### Using apt-get via PPA (Ubuntu)
 
 **Tip:** run `sudo apt-get install -y software-properties-common` first if `add-apt-repository` is not available on your system.
 
@@ -81,9 +81,9 @@ sudo apt-get install -y python3-git-machete
 Download the rpm package from the [latest release](https://github.com/VirtusLab/git-machete/releases/latest)
 and install either by opening it in your desktop environment or with `rpm -i git-machete-*.noarch.rpm`.
 
-### Using AUR (Arch Linux)
+### Using Alpine, Arch, Gentoo & other Linux distro-specific package managers
 
-Install the AUR package [git-machete](https://aur.archlinux.org/packages/git-machete) using an AUR helper of your preference.
+Check [Repology](https://repology.org/project/git-machete/versions) for the available distro-specific packages.
 
 ### Using Nix (macOS & most Linux distributions)
 
@@ -177,10 +177,10 @@ git machete github create-pr [--draft]
 
 **Note**: for private repositories, a GitHub API token with `repo` access is required.
 This will be resolved from the first of:
-1. The `GITHUB_TOKEN` env var.
-2. The content of the `.github-token` file in the home directory (`~`). This file has to be manually created by the user.
-3. The auth token from the current [`gh`](https://cli.github.com/) configuration.
-4. The auth token from the current [`hub`](https://github.com/github/hub) configuration.
+1. `GITHUB_TOKEN` env var.
+2. Contents of the `.github-token` file in the home directory (`~`). This file has to be manually created by the user.
+3. Auth token from the current [`gh`](https://cli.github.com/) configuration.
+4. Auth token from the current [`hub`](https://github.com/github/hub) configuration.
 
 <br/>
 
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index b566d85..daed8bb 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -1,5 +1,10 @@
 # Release notes
 
+## New in git-machete 3.15.0
+
+- improved: formatting in `git machete` command prompts and outputs
+- added: `slide-out=no` branch qualifier that control the slide-out behaviour of `git machete traverse`
+
 ## New in git-machete 3.14.3
 
 - improved: docs for `machete.github.*` and other config keys
diff --git a/ci/homebrew/ci-deploy.sh b/ci/homebrew/ci-deploy.sh
index 47ec6ac..3388498 100644
--- a/ci/homebrew/ci-deploy.sh
+++ b/ci/homebrew/ci-deploy.sh
@@ -31,6 +31,8 @@ else
   echo "Refraining from push since it's a dry run"
   brew bump-formula-pr --write-only --no-browse --verbose --url "$url" --sha256 "$sha256" git-machete
 
+  export HOMEBREW_NO_INSTALL_FROM_API=1
+  brew config
   echo "Attempt to install the formula locally"
   attempts=5
   i=1
diff --git a/completion/README.md b/completion/README.md
index 177b74b..fce7fc0 100644
--- a/completion/README.md
+++ b/completion/README.md
@@ -110,7 +110,7 @@ exec $SHELL -l
 ## Fish
 
 ### Mac (via Homebrew)
-Please look at the section about [installation via Homebrew](../README.md#using-homebrew-macos).
+Please look at the section about [installation via Homebrew](../README.md#using-homebrew-macos--most-linux-distributions).
 ``brew install git-machete`` automatically installs fish completion files for ``git machete``.
 
 ### Linux
diff --git a/docs/source/cli_help/traverse.rst b/docs/source/cli_help/traverse.rst
index 3053022..98f3c60 100644
--- a/docs/source/cli_help/traverse.rst
+++ b/docs/source/cli_help/traverse.rst
@@ -65,16 +65,16 @@ It will pick up the walk from the current branch (unless ``--start-from=`` or ``
 Unlike with e.g. ``git rebase``, there is no special ``--continue`` flag, as ``traverse`` is stateless
 (doesn't keep a state of its own like ``git rebase`` does in ``.git/rebase-apply/``).
 
-The rebase and push behavior of ``traverse`` can also be customized for each branch separately using *branch qualifiers*.
-There are ``rebase=no`` and ``push=no`` qualifiers that can be used to opt out of default behavior (rebasing and pushing).
-The qualifier can appear anywhere in the annotation but needs to be separated by a whitespace from any other character, e.g. ``some_annotation_text rebase=no push=no``.
-Qualifiers can only be overwritten by manually editing ``.git/machete`` file or modifying it with ``git machete e[dit]`` or by updating annotations with ``git machete anno``.
+The rebase, push and slide-out behaviors of ``traverse`` can also be customized for each branch separately using *branch qualifiers*.
+There are ``rebase=no``, ``push=no`` and ``slide-out=no`` qualifiers that can be used to opt out of default behavior (rebasing, pushing and sliding the branch out of the dependency tree).
+The qualifier can appear anywhere in the annotation but needs to be separated by a whitespace from any other character, e.g. ``some_annotation_text rebase=no push=no slide-out=no``.
+Qualifiers can only be overwritten by manually editing ``.git/machete`` file or modifying it with ``git machete e[dit]``, or by updating annotations with ``git machete anno``.
 Example machete file with branch qualifiers:
 
 .. code-block::
 
     master
-      develop  rebase=no
+      develop  rebase=no slide-out=no
         my-branch  PR #123
         someone-elses-branch  PR #124 rebase=no push=no
         branch-for-local-experiments  push=no
diff --git a/git_machete/__init__.py b/git_machete/__init__.py
index 663664e..254db7b 100644
--- a/git_machete/__init__.py
+++ b/git_machete/__init__.py
@@ -1,1 +1,1 @@
-__version__ = '3.14.3'
+__version__ = '3.15.0'
diff --git a/git_machete/annotation.py b/git_machete/annotation.py
index db3b975..d0b326b 100644
--- a/git_machete/annotation.py
+++ b/git_machete/annotation.py
@@ -1,5 +1,4 @@
 import re
-from typing import Callable
 
 from git_machete import utils
 
@@ -13,11 +12,16 @@ class Qualifiers:
         self._annotation_without_qualifiers = annotation
         self._rebase_text = ''
         self._push_text = ''
+        self._slide_out_text = ''
         self.rebase = True
         self.push = True
+        self.slide_out = None
 
-        match_pattern: Callable[[str], str] = lambda text: f'.*\\b{text}=no\\b.*'
-        sub_pattern: Callable[[str], str] = lambda text: f'[ ]?{text}=no[ ]?'
+        def match_pattern(text: str) -> str:
+            return f'.*\\b{text}=no\\b.*'
+
+        def sub_pattern(text: str) -> str:
+            return f'[ ]?{text}=no[ ]?'
 
         rebase_match = re.match(match_pattern('rebase'), annotation)
         if rebase_match:
@@ -31,11 +35,17 @@ class Qualifiers:
             self._push_text = 'push=no'
             self._annotation_without_qualifiers = re.sub(sub_pattern('push'), ' ', self._annotation_without_qualifiers)
 
+        slide_out_match = re.match(match_pattern('slide-out'), annotation)
+        if slide_out_match:
+            self.slide_out = False
+            self._slide_out_text = 'slide-out=no'
+            self._annotation_without_qualifiers = re.sub(sub_pattern('slide-out'), ' ', self._annotation_without_qualifiers)
+
     def get_annotation_text_without_qualifiers(self) -> str:
         return self._annotation_without_qualifiers.strip()
 
     def get_qualifiers_text(self) -> str:
-        return f'{self._rebase_text.strip()} {self._push_text.strip()}'.replace('  ', ' ').strip()
+        return f'{self._rebase_text} {self._push_text} {self._slide_out_text}'.replace('  ', ' ').strip()
 
 
 class Annotation:
diff --git a/git_machete/cli.py b/git_machete/cli.py
index ac6d466..46ad902 100644
--- a/git_machete/cli.py
+++ b/git_machete/cli.py
@@ -8,7 +8,7 @@ import textwrap
 from typing import Any, Dict, List, Optional, Sequence, Tuple, TypeVar, Union
 
 import git_machete.options
-from git_machete import __version__, utils
+from git_machete import __version__, git_config_keys, utils
 from git_machete.client import MacheteClient
 from git_machete.exceptions import ExitCode, MacheteException, StopInteraction
 from git_machete.generated_docs import long_docs, short_docs
@@ -468,7 +468,7 @@ def update_cli_options_using_config_keys(
         cli_opts: git_machete.options.CommandLineOptions,
         git: GitContext
 ) -> None:
-    machete_traverse_push_config_key = git.get_boolean_config_attr_or_none(key='machete.traverse.push')
+    machete_traverse_push_config_key = git.get_boolean_config_attr_or_none(key=git_config_keys.TRAVERSE_PUSH)
     if machete_traverse_push_config_key is not None:
         if machete_traverse_push_config_key:
             cli_opts.opt_push_tracked, cli_opts.opt_push_untracked = True, True
@@ -630,7 +630,7 @@ def launch(orig_args: List[str]) -> None:
                     machete_client.set_fork_point_override(branch, upstream)
                 else:
                     raise MacheteException(
-                        f"Branch {branch} does not have upstream (parent) branch")
+                        f"Branch {bold(branch)} does not have upstream (parent) branch")
             elif cli_opts.opt_unset_override:
                 machete_client.unset_fork_point_override(branch)
             else:
diff --git a/git_machete/client.py b/git_machete/client.py
index f412852..3a69bab 100644
--- a/git_machete/client.py
+++ b/git_machete/client.py
@@ -9,7 +9,7 @@ from typing import Callable, Dict, Generator, List, Optional, Tuple
 
 import git_machete.github
 import git_machete.options
-from git_machete import utils
+from git_machete import git_config_keys, utils
 from git_machete.annotation import Annotation
 from git_machete.constants import (DISCOVER_DEFAULT_FRESH_BRANCH_COUNT,
                                    PICK_FIRST_ROOT, PICK_LAST_ROOT,
@@ -91,7 +91,7 @@ class MacheteClient:
     def expect_in_managed_branches(self, branch: LocalBranchShortName) -> None:
         if branch not in self.managed_branches:
             raise MacheteException(
-                f"Branch `{branch}` not found in the tree of branch dependencies.\n"
+                f"Branch {bold(branch)} not found in the tree of branch dependencies.\n"
                 f"Use `git machete add {branch}` or `git machete edit`")
 
     def expect_at_least_one_managed_branch(self) -> None:
@@ -128,7 +128,7 @@ class MacheteClient:
             if branch in self.managed_branches:
                 raise MacheteException(
                     f"{self._definition_file_path}, line {index + 1}: branch "
-                    f"`{branch}` re-appears in the tree definition. {hint}")
+                    f"{bold(branch)} re-appears in the tree definition. {hint}")
             if verify_branches and branch not in self.__git.get_local_branches():
                 invalid_branches += [branch]
             self.managed_branches += [branch]
@@ -141,8 +141,8 @@ class MacheteClient:
                     indent_expanded: str = "".join(mapping[c] for c in self.__indent)
                     raise MacheteException(
                         f"{self._definition_file_path}, line {index + 1}: "
-                        f"invalid indent `{prefix_expanded}`, expected a multiply"
-                        f" of `{indent_expanded}`. {hint}")
+                        f"invalid indent {bold(prefix_expanded)}, expected a multiply"
+                        f" of {bold(indent_expanded)}. {hint}")
             else:
                 depth = 0
 
@@ -150,7 +150,7 @@ class MacheteClient:
                 raise MacheteException(
                     f"{self._definition_file_path}, line {index + 1}: too much "
                     f"indent (level {depth}, expected at most {last_depth + 1}) "
-                    f"for the branch `{branch}`. {hint}")
+                    f"for the branch {bold(branch)}. {hint}")
             last_depth = depth
 
             at_depth[depth] = branch
@@ -170,19 +170,20 @@ class MacheteClient:
         if perform_interactive_slide_out:
             if len(invalid_branches) == 1:
                 ans: str = self.ask_if(
-                    f"Skipping `{invalid_branches[0]}` " +
+                    f"Skipping {bold(invalid_branches[0])} " +
                     "which is not a local branch (perhaps it has been deleted?).\n" +
                     "Slide it out from the definition file?" +
                     get_pretty_choices("y", "e[dit]", "N"), opt_yes_msg=None, opt_yes=False)
             else:
                 ans = self.ask_if(
-                    f"Skipping {', '.join(f'`{branch}`' for branch in invalid_branches)}"
+                    f"Skipping {', '.join(f'{bold(branch)}' for branch in invalid_branches)}"
                     " which are not local branches (perhaps they have been deleted?).\n"
                     "Slide them out from the definition file?" + get_pretty_choices("y", "e[dit]", "N"),
                     opt_yes_msg=None, opt_yes=False)
         else:
             if len(invalid_branches) > 0:
-                print(f"Warning: sliding invalid branches: {', '.join(invalid_branches)} out of the definition file", file=sys.stderr)
+                print(f"Warning: sliding invalid branches: {', '.join(f'{bold(branch)}' for branch in invalid_branches)} "
+                      f"out of the definition file", file=sys.stderr)
             ans = 'y'
 
         def recursive_slide_out_invalid_branches(branch_: LocalBranchShortName) -> List[LocalBranchShortName]:
@@ -247,7 +248,7 @@ class MacheteClient:
             ) -> None:
         if branch in self.managed_branches:
             raise MacheteException(
-                f"Branch `{branch}` already exists in the tree of branch dependencies")
+                f"Branch {bold(branch)} already exists in the tree of branch dependencies")
 
         if opt_onto:
             self.expect_in_managed_branches(opt_onto)
@@ -256,10 +257,10 @@ class MacheteClient:
             remote_branch: Optional[RemoteBranchShortName] = self.__git.get_sole_remote_branch(branch)
             if remote_branch:
                 common_line = (
-                    f"A local branch `{branch}` does not exist, but a remote "
-                    f"branch `{remote_branch}` exists.\n")
-                msg = common_line + f"Check out `{branch}` locally?" + get_pretty_choices('y', 'N')
-                opt_yes_msg = common_line + f"Checking out `{branch}` locally..."
+                    f"A local branch {bold(branch)} does not exist, but a remote "
+                    f"branch {bold(remote_branch)} exists.\n")
+                msg = common_line + f"Check out {bold(branch)} locally?" + get_pretty_choices('y', 'N')
+                opt_yes_msg = common_line + f"Checking out {bold(branch)} locally..."
                 if self.ask_if(msg, opt_yes_msg, opt_yes=opt_yes, verbose=verbose) in ('y', 'yes'):
                     self.__git.create_branch(branch, remote_branch.full_name(), switch_head=switch_head_if_new_branch)
                 else:
@@ -268,10 +269,10 @@ class MacheteClient:
                 # specified via `--onto`, we'll try to infer it now.
             else:
                 out_of = LocalBranchShortName.of(opt_onto).full_name() if opt_onto else HEAD
-                out_of_str = f"`{opt_onto}`" if opt_onto else "the current HEAD"
-                msg = (f"A local branch `{branch}` does not exist. Create (out "
+                out_of_str = f"{bold(opt_onto)}" if opt_onto else "the current HEAD"
+                msg = (f"A local branch {bold(branch)} does not exist. Create (out "
                        f"of {out_of_str})?" + get_pretty_choices('y', 'N'))
-                opt_yes_msg = (f"A local branch `{branch}` does not exist. "
+                opt_yes_msg = (f"A local branch {bold(branch)} does not exist. "
                                f"Creating out of {out_of_str}")
                 if self.ask_if(msg, opt_yes_msg, opt_yes=opt_yes, verbose=verbose) in ('y', 'yes'):
                     # If `--onto` hasn't been explicitly specified, let's try to
@@ -287,7 +288,7 @@ class MacheteClient:
         if opt_as_root or not self.__roots:
             self.__roots += [branch]
             if verbose:
-                print(fmt(f"Added branch `{branch}` as a new root"))
+                print(fmt(f"Added branch {bold(branch)} as a new root"))
         else:
             if not opt_onto:
                 upstream = self.__infer_upstream(
@@ -296,16 +297,16 @@ class MacheteClient:
                     reject_reason_message="this candidate is not a managed branch")
                 if not upstream:
                     raise MacheteException(
-                        f"Could not automatically infer upstream (parent) branch for `{branch}`.\n"
+                        f"Could not automatically infer upstream (parent) branch for {bold(branch)}.\n"
                         "You can either:\n"
                         "1) specify the desired upstream branch with `--onto` or\n"
-                        f"2) pass `--as-root` to attach `{branch}` as a new root or\n"
+                        f"2) pass `--as-root` to attach {bold(branch)} as a new root or\n"
                         "3) edit the definition file manually with `git machete edit`")
                 else:
-                    msg = (f"Add `{branch}` onto the inferred upstream (parent) "
-                           f"branch `{upstream}`?" + get_pretty_choices('y', 'N'))
-                    opt_yes_msg = (f"Adding `{branch}` onto the inferred upstream"
-                                   f" (parent) branch `{upstream}`")
+                    msg = (f"Add {bold(branch)} onto the inferred upstream (parent) "
+                           f"branch {bold(upstream)}?" + get_pretty_choices('y', 'N'))
+                    opt_yes_msg = (f"Adding {bold(branch)} onto the inferred upstream"
+                                   f" (parent) branch {bold(upstream)}")
                     if self.ask_if(msg, opt_yes_msg, opt_yes=opt_yes, verbose=verbose) in ('y', 'yes'):
                         opt_onto = upstream
                     else:
@@ -317,7 +318,7 @@ class MacheteClient:
             else:
                 self.__down_branches[opt_onto] = [branch]
             if verbose:
-                print(fmt(f"Added branch `{branch}` onto `{opt_onto}`"))
+                print(fmt(f"Added branch {bold(branch)} onto {bold(opt_onto)}"))
 
         self.managed_branches += [branch]
         self.save_definition_file()
@@ -341,18 +342,18 @@ class MacheteClient:
         if opt_merge:
             with_branch = self.up(
                 current_branch,
-                prompt_if_inferred_msg=("Branch `%s` not found in the tree of branch dependencies. "
-                                        "Merge with the inferred upstream `%s`?" + get_pretty_choices('y', 'N')),
-                prompt_if_inferred_yes_opt_msg=("Branch `%s` not found in the tree of branch dependencies. "
-                                                "Merging with the inferred upstream `%s`..."))
+                prompt_if_inferred_msg=("Branch <b>%s</b> not found in the tree of branch dependencies. "
+                                        "Merge with the inferred upstream <b>%s</b>?" + get_pretty_choices('y', 'N')),
+                prompt_if_inferred_yes_opt_msg=("Branch <b>%s</b> not found in the tree of branch dependencies. "
+                                                "Merging with the inferred upstream <b>%s</b>..."))
             self.__git.merge(with_branch, current_branch, opt_no_edit_merge)
         else:
             onto_branch = self.up(
                 current_branch,
-                prompt_if_inferred_msg=("Branch `%s` not found in the tree of branch dependencies. "
-                                        "Rebase onto the inferred upstream `%s`?" + get_pretty_choices('y', 'N')),
-                prompt_if_inferred_yes_opt_msg=("Branch `%s` not found in the tree of branch dependencies. "
-                                                "Rebasing onto the inferred upstream `%s`..."))
+                prompt_if_inferred_msg=("Branch <b>%s</b> not found in the tree of branch dependencies. "
+                                        "Rebase onto the inferred upstream <b>%s</b>?" + get_pretty_choices('y', 'N')),
+                prompt_if_inferred_yes_opt_msg=("Branch <b>%s</b> not found in the tree of branch dependencies. "
+                                                "Rebasing onto the inferred upstream <b>%s</b>..."))
             self.__git.rebase(
                 LocalBranchShortName.of(onto_branch).full_name(),
                 opt_fork_point or self.fork_point(
@@ -372,7 +373,7 @@ class MacheteClient:
             raise MacheteException("No local branches found")
         for root in opt_roots:
             if root not in self.__git.get_local_branches():
-                raise MacheteException(f"`{root}` is not a local branch")
+                raise MacheteException(f"{bold(root)} is not a local branch")
         if opt_roots:
             self.__roots = list(map(LocalBranchShortName.of, opt_roots))
         else:
@@ -465,7 +466,7 @@ class MacheteClient:
             warn(
                 "skipping %s since %s merged to another branch and would not "
                 "have any downstream branches.\n"
-                % (", ".join(f"`{branch}`" for branch in merged_branches_to_skip),
+                % (", ".join(f"{bold(branch)}" for branch in merged_branches_to_skip),
                    "it's" if len(merged_branches_to_skip) == 1 else "they're"))
             self.managed_branches = excluding(self.managed_branches, merged_branches_to_skip)
             for branch in merged_branches_to_skip:
@@ -515,7 +516,7 @@ class MacheteClient:
             self.expect_in_managed_branches(branch)
             new_upstream = self.up_branch.get(branch)
             if not new_upstream:
-                raise MacheteException(f"No upstream branch defined for `{branch}`, cannot slide out")
+                raise MacheteException(f"No upstream branch defined for {bold(branch)}, cannot slide out")
 
         if opt_down_fork_point:
             last_branch_to_slide_out = branches_to_slide_out[-1]
@@ -535,16 +536,16 @@ class MacheteClient:
         for bu, bd in zip(branches_to_slide_out[:-1], branches_to_slide_out[1:]):
             dbs = self.__down_branches.get(bu)
             if not dbs or len(dbs) == 0:
-                raise MacheteException(f"No downstream branch defined for `{bu}`, cannot slide out")
+                raise MacheteException(f"No downstream branch defined for {bold(bu)}, cannot slide out")
             elif len(dbs) > 1:
-                flat_dbs = ", ".join(f"`{x}`" for x in dbs)
+                flat_dbs = ", ".join(f"{bold(x)}" for x in dbs)
                 raise MacheteException(
-                    f"Multiple downstream branches defined for `{bu}`: {flat_dbs}; cannot slide out")
+                    f"Multiple downstream branches defined for {bold(bu)}: {flat_dbs}; cannot slide out")
             elif dbs != [bd]:
-                raise MacheteException(f"'{bd}' is not downstream of '{bu}', cannot slide out")
+                raise MacheteException(f"{bold(bd)} is not downstream of {bold(bu)}, cannot slide out")
 
             if self.up_branch[bd] != bu:
-                raise MacheteException(f"`{bu}` is not upstream of `{bd}`, cannot slide out")
+                raise MacheteException(f"{bold(bu)} is not upstream of {bold(bd)}, cannot slide out")
 
         # Get new branches
         new_upstream = self.up_branch[branches_to_slide_out[0]]
@@ -590,7 +591,7 @@ class MacheteClient:
     def advance(self, *, branch: LocalBranchShortName, opt_yes: bool) -> None:
         if not self.__down_branches.get(branch):
             raise MacheteException(
-                f"`{branch}` does not have any downstream (child) branches to advance towards")
+                f"{bold(branch)} does not have any downstream (child) branches to advance towards")
 
         def connected_with_green_edge(bd: LocalBranchShortName) -> bool:
             return bool(
@@ -603,17 +604,17 @@ class MacheteClient:
         candidate_downstreams = list(filter(connected_with_green_edge, self.__down_branches[branch]))
         if not candidate_downstreams:
             raise MacheteException(
-                f"No downstream (child) branch of `{branch}` is connected to "
-                f"`{branch}` with a green edge")
+                f"No downstream (child) branch of {bold(branch)} is connected to "
+                f"{bold(branch)} with a green edge")
         if len(candidate_downstreams) > 1:
             if opt_yes:
                 raise MacheteException(
-                    f"More than one downstream (child) branch of `{branch}` is "
-                    f"connected to `{branch}` with a green edge and `-y/--yes` option is specified")
+                    f"More than one downstream (child) branch of {bold(branch)} is "
+                    f"connected to {bold(branch)} with a green edge and `-y/--yes` option is specified")
             else:
                 down_branch = self.pick(
                     candidate_downstreams,
-                    f"downstream branch towards which `{branch}` is to be fast-forwarded")
+                    f"downstream branch towards which {bold(branch)} is to be fast-forwarded")
                 self.__git.merge_fast_forward_only(down_branch)
         else:
             down_branch = candidate_downstreams[0]
@@ -678,7 +679,7 @@ class MacheteClient:
 
         if opt_fetch:
             for remote in self.__git.get_remotes():
-                print(f"Fetching {remote}...")
+                print(f"Fetching {bold(remote)}...")
                 self.__git.fetch_remote(remote)
             if self.__git.get_remotes():
                 self.flush_caches()
@@ -709,6 +710,8 @@ class MacheteClient:
 
             needs_slide_out: bool = self.__is_merged_to_upstream(
                 branch, opt_no_detect_squash_merges=opt_no_detect_squash_merges)
+            if needs_slide_out and branch in self.annotations:
+                needs_slide_out = self.annotations[branch].qualifiers.slide_out
             s, remote = self.__git.get_strict_remote_sync_status(branch)
             if s in (
                     SyncToRemoteStatuses.BEHIND_REMOTE,
@@ -837,7 +840,7 @@ class MacheteClient:
                         # a subsequent 'git rebase --continue'.
                         rebased_branch = self.__git.get_currently_rebased_branch_or_none()
                         if rebased_branch:  # 'remote_branch' should be equal to 'branch' at this point anyway
-                            print(fmt(f"\nRebase of `{rebased_branch}` in progress; stopping the traversal"))
+                            print(fmt(f"\nRebase of {bold(rebased_branch)} in progress; stopping the traversal"))
                             return
                     if ans == 'yq':
                         return
@@ -983,7 +986,7 @@ class MacheteClient:
         hook_path = self.__git.get_hook_path("machete-status-branch")
         hook_executable = self.__git.check_hook_executable(hook_path)
 
-        maybe_space_before_branch_name = ' ' if self.__git.get_boolean_config_attr(key='machete.status.extraSpaceBeforeBranchName',
+        maybe_space_before_branch_name = ' ' if self.__git.get_boolean_config_attr(git_config_keys.STATUS_EXTRA_SPACE_BEFORE_BRANCH_NAME,
                                                                                    default_value=False) else ''
 
         def print_line_prefix(branch_: LocalBranchShortName, suffix: str) -> None:
@@ -1076,11 +1079,11 @@ class MacheteClient:
                 SyncToRemoteStatuses.NO_REMOTES: "",
                 SyncToRemoteStatuses.UNTRACKED: colored(" (untracked)", AnsiEscapeCodes.ORANGE),
                 SyncToRemoteStatuses.IN_SYNC_WITH_REMOTE: "",
-                SyncToRemoteStatuses.BEHIND_REMOTE: colored(f" (behind {remote})", AnsiEscapeCodes.RED),
-                SyncToRemoteStatuses.AHEAD_OF_REMOTE: colored(f" (ahead of {remote})", AnsiEscapeCodes.RED),
-                SyncToRemoteStatuses.DIVERGED_FROM_AND_OLDER_THAN_REMOTE: colored(f" (diverged from & older than {remote})",
+                SyncToRemoteStatuses.BEHIND_REMOTE: colored(f" (behind {bold(remote)})", AnsiEscapeCodes.RED),
+                SyncToRemoteStatuses.AHEAD_OF_REMOTE: colored(f" (ahead of {bold(remote)})", AnsiEscapeCodes.RED),
+                SyncToRemoteStatuses.DIVERGED_FROM_AND_OLDER_THAN_REMOTE: colored(f" (diverged from & older than {bold(remote)})",
                                                                                   AnsiEscapeCodes.RED),
-                SyncToRemoteStatuses.DIVERGED_FROM_AND_NEWER_THAN_REMOTE: colored(f" (diverged from {remote})", AnsiEscapeCodes.RED)
+                SyncToRemoteStatuses.DIVERGED_FROM_AND_NEWER_THAN_REMOTE: colored(f" (diverged from {bold(remote)})", AnsiEscapeCodes.RED)
             }[SyncToRemoteStatuses(s)]
 
             hook_output = ""
@@ -1104,12 +1107,12 @@ class MacheteClient:
         branches_in_sync_but_fork_point_off = [k for k, v in sync_to_parent_status.items() if v == SyncToParentStatus.InSyncButForkPointOff]
         if branches_in_sync_but_fork_point_off and warn_when_branch_in_sync_but_fork_point_off:
             if len(branches_in_sync_but_fork_point_off) == 1:
-                first_part = f"yellow edge indicates that fork point for `{branches_in_sync_but_fork_point_off[0]}` " \
+                first_part = f"yellow edge indicates that fork point for {bold(branches_in_sync_but_fork_point_off[0])} " \
                              f"is probably incorrectly inferred,\n or that some extra branch should be between " \
-                             f"`{self.up_branch[LocalBranchShortName.of(branches_in_sync_but_fork_point_off[0])]}` and " \
-                             f"`{branches_in_sync_but_fork_point_off[0]}`"
+                             f"{bold(self.up_branch[LocalBranchShortName.of(branches_in_sync_but_fork_point_off[0])])} and " \
+                             f"{bold(branches_in_sync_but_fork_point_off[0])}"
             else:
-                affected_branches = ", ".join(map(lambda x: f"`{x}`", branches_in_sync_but_fork_point_off))
+                affected_branches = ", ".join(map(lambda x: f"{bold(x)}", branches_in_sync_but_fork_point_off))
                 first_part = f"yellow edges indicate that fork points for {affected_branches} are probably incorrectly inferred,\n" \
                              f"or that some extra branch should be added between each of these branches and its parent"
 
@@ -1119,8 +1122,8 @@ class MacheteClient:
             elif len(branches_in_sync_but_fork_point_off) == 1:
                 second_part = "Consider using `git machete fork-point " \
                               f"--override-to=<revision>|--override-to-inferred|--override-to-parent " \
-                              f"{branches_in_sync_but_fork_point_off[0]}`,\nor reattaching `{branches_in_sync_but_fork_point_off[0]}` " \
-                              f"under a different parent branch"
+                              f"{bold(branches_in_sync_but_fork_point_off[0])}`,\nor reattaching " \
+                              f"{bold(branches_in_sync_but_fork_point_off[0])} under a different parent branch"
             else:
                 second_part = "Consider using `git machete fork-point " \
                               "--override-to=<revision>|--override-to-inferred|--override-to-parent <branch>` for each affected branch,\n" \
@@ -1130,7 +1133,7 @@ class MacheteClient:
             warn(f"{first_part}.\n\n{second_part}.")
 
     def delete_unmanaged(self, *, opt_yes: bool) -> None:
-        print(bold('Checking for unmanaged branches...'))
+        print('Checking for unmanaged branches...')
         branches_to_delete = excluding(self.__git.get_local_branches(), self.managed_branches)
         self._delete_branches(branches_to_delete=branches_to_delete, opt_yes=opt_yes)
 
@@ -1138,7 +1141,7 @@ class MacheteClient:
         current_branch = self.__git.get_current_branch_or_none()
         if current_branch and current_branch in branches_to_delete:
             branches_to_delete = excluding(branches_to_delete, [current_branch])
-            print(fmt(f"Skipping current branch `{current_branch}`"))
+            print(f"Skipping current branch {bold(current_branch)}")
         if branches_to_delete:
             branches_merged_to_head = self.__git.get_merged_local_branches()
 
@@ -1147,7 +1150,7 @@ class MacheteClient:
                 remote_branch = self.__git.get_strict_counterpart_for_fetching_of_branch(branch)
                 is_merged_to_remote = self.__git.is_ancestor_or_equal(branch.full_name(),
                                                                       remote_branch.full_name()) if remote_branch else True
-                msg_core = f"{bold(branch)} (merged to HEAD{'' if is_merged_to_remote else f', but not merged to {remote_branch}'})"
+                msg_core = f"{bold(branch)} (merged to HEAD{'' if is_merged_to_remote else f', but not merged to {bold(remote_branch)}'})"
                 msg = f"Delete branch {msg_core}?" + get_pretty_choices('y', 'N', 'q')
                 opt_yes_msg = f"Deleting branch {msg_core}"
                 ans = self.ask_if(msg, opt_yes_msg, opt_yes=opt_yes)
@@ -1215,7 +1218,7 @@ class MacheteClient:
                     f"falling back to {upstream} as fork point")
                 return self.__git.get_commit_hash_by_revision(upstream), []
             else:
-                raise MacheteException(f"Cannot find fork point for branch `{branch}`")
+                raise MacheteException(f"Cannot find fork point for branch {bold(branch)}")
         else:
             debug(f"commit {fp_hash} is the most recent point in history of {branch} to occur on "
                   "filtered reflog of any other branch or its remote counterpart "
@@ -1265,7 +1268,7 @@ class MacheteClient:
         self.expect_in_managed_branches(branch)
         dbs = self.__down_branches.get(branch)
         if not dbs:
-            raise MacheteException(f"Branch `{branch}` has no downstream branch")
+            raise MacheteException(f"Branch {bold(branch)} has no downstream branch")
         elif len(dbs) == 1:
             return [dbs[0]]
         elif pick_mode:
@@ -1288,14 +1291,14 @@ class MacheteClient:
         self.expect_in_managed_branches(branch)
         index: int = self.managed_branches.index(branch) + 1
         if index == len(self.managed_branches):
-            raise MacheteException(f"Branch `{branch}` has no successor")
+            raise MacheteException(f"Branch {bold(branch)} has no successor")
         return self.managed_branches[index]
 
     def prev_branch(self, branch: LocalBranchShortName) -> LocalBranchShortName:
         self.expect_in_managed_branches(branch)
         index: int = self.managed_branches.index(branch) - 1
         if index == -1:
-            raise MacheteException(f"Branch `{branch}` has no predecessor")
+            raise MacheteException(f"Branch {bold(branch)} has no predecessor")
         return self.managed_branches[index]
 
     def root_branch(self, branch: LocalBranchShortName, if_unmanaged: int) -> LocalBranchShortName:
@@ -1303,12 +1306,12 @@ class MacheteClient:
             if self.__roots:
                 if if_unmanaged == PICK_FIRST_ROOT:
                     warn(
-                        f"{branch} is not a managed branch, assuming "
+                        f"{bold(branch)} is not a managed branch, assuming "
                         f"{self.__roots[0]} (the first root) instead as root")
                     return self.__roots[0]
                 else:  # if_unmanaged == PICK_LAST_ROOT
                     warn(
-                        f"{branch} is not a managed branch, assuming "
+                        f"{bold(branch)} is not a managed branch, assuming "
                         f"{self.__roots[-1]} (the last root) instead as root")
                     return self.__roots[-1]
             else:
@@ -1326,7 +1329,7 @@ class MacheteClient:
             if upstream:
                 return upstream
             else:
-                raise MacheteException(f"Branch `{branch}` has no upstream branch")
+                raise MacheteException(f"Branch {bold(branch)} has no upstream branch")
         else:
             upstream = self.__infer_upstream(branch)
             if upstream:
@@ -1340,12 +1343,12 @@ class MacheteClient:
                     raise MacheteException("Aborting.")
                 else:
                     warn(
-                        f"branch `{branch}` not found in the tree of branch "
-                        f"dependencies; the upstream has been inferred to `{upstream}`")
+                        f"branch {bold(branch)} not found in the tree of branch "
+                        f"dependencies; the upstream has been inferred to {bold(upstream)}")
                     return upstream
             else:
                 raise MacheteException(
-                    f"Branch `{branch}` not found in the tree of branch "
+                    f"Branch {bold(branch)} not found in the tree of branch "
                     f"dependencies and its upstream could not be inferred")
 
     def get_slidable_branches(self) -> List[LocalBranchShortName]:
@@ -1387,7 +1390,7 @@ class MacheteClient:
                 "No commits to squash. Use `-f` or `--fork-point` to specify the "
                 "start of range of commits to squash.")
         if len(commits) == 1:
-            print(f"Exactly one commit ({commits[0].short_hash}) to squash, ignoring.\n")
+            print(f"Exactly one commit ({bold(commits[0].short_hash)}) to squash, ignoring.\n")
             print("Tip: use `-f` or `--fork-point` to specify where the range of "
                   "commits to squash starts.")
             return
@@ -1474,7 +1477,7 @@ class MacheteClient:
         _, org, repo = self.__derive_remote_and_github_org_and_repo(domain)
         print('Checking for open GitHub PRs... ', end='', flush=True)
         current_user: Optional[str] = git_machete.github.derive_current_user_login(domain)
-        debug('Current GitHub user is ' + (current_user or '<none>'))
+        debug('Current GitHub user is ' + (bold(current_user) or '<none>'))
         all_open_prs: List[GitHubPullRequest] = derive_pull_requests(domain, org, repo)
         print(fmt('<green><b>OK</b></green>'))
         self.__sync_annotations_to_definition_file(all_open_prs, current_user)
@@ -1492,9 +1495,9 @@ class MacheteClient:
                     anno += f' ({pr.user})'
                 upstream: Optional[LocalBranchShortName] = self.up_branch.get(LocalBranchShortName.of(pr.head))
                 if pr.base != upstream:
-                    warn(f'branch `{pr.head}` has a different base in PR #{pr.number} (`{pr.base}`) '
-                         f'than in machete file (`{upstream or "<none, is a root>"}`)')
-                    anno += f" WRONG PR BASE or MACHETE PARENT? PR has '{pr.base}'"
+                    warn(f'branch {bold(pr.head)} has a different base in PR #{bold(str(pr.number))} ({bold(pr.base)}) '
+                         f'than in machete file ({bold(upstream) if upstream else "<none, is a root>"})')
+                    anno += f" WRONG PR BASE or MACHETE PARENT? PR has {bold(pr.base)}"
                 old_annotation_text, old_annotation_qualifiers_text = '', ''
                 if LocalBranchShortName.of(pr.head) in self.__annotations:
                     old_annotation_text = self.__annotations[LocalBranchShortName.of(pr.head)].text
@@ -1502,11 +1505,11 @@ class MacheteClient:
 
                 if pr.user != current_user and old_annotation_qualifiers_text == '':
                     if verbose:
-                        print(fmt(f'Annotating `{pr.head}` as `{anno} rebase=no push=no`'))
+                        print(fmt(f'Annotating {bold(pr.head)} as `{anno} rebase=no push=no`'))
                     self.__annotations[LocalBranchShortName.of(pr.head)] = Annotation(f'{anno} rebase=no push=no')
                 elif old_annotation_text != anno:
                     if verbose:
-                        print(fmt(f'Annotating `{pr.head}` as `{anno}`'))
+                        print(fmt(f'Annotating {bold(pr.head)} as `{anno}`'))
                     self.__annotations[LocalBranchShortName.of(pr.head)] = Annotation(f'{anno} {old_annotation_qualifiers_text}') \
                         if old_annotation_text is not None else Annotation(anno)
             else:
@@ -1544,7 +1547,7 @@ class MacheteClient:
                                         ) -> Generator[Tuple[FullCommitHash, List[BranchPair]], None, None]:
 
         if branch not in self.__git.get_local_branches():
-            raise MacheteException(f"`{branch}` is not a local branch")
+            raise MacheteException(f"{bold(branch)} is not a local branch")
 
         if self.__branch_pairs_by_hash_in_reflog is None:
             def generate_entries() -> Generator[Tuple[FullCommitHash, BranchPair], None, None]:
@@ -1623,52 +1626,44 @@ class MacheteClient:
                     debug(f"upstream candidate {candidate} rejected ({reject_reason_message})")
         return None
 
-    @staticmethod
-    def config_key_for_override_fork_point_to(branch: LocalBranchShortName) -> str:
-        return f"machete.overrideForkPoint.{branch}.to"
-
-    @staticmethod
-    def config_key_for_override_fork_point_while_descendant_of(branch: LocalBranchShortName) -> str:
-        return f"machete.overrideForkPoint.{branch}.whileDescendantOf"
-
     # Also includes config that is incomplete (only one entry out of two) or otherwise invalid.
     def has_any_fork_point_override_config(self, branch: LocalBranchShortName) -> bool:
-        return (self.__git.get_config_attr_or_none(self.config_key_for_override_fork_point_to(branch)) or
-                self.__git.get_config_attr_or_none(self.config_key_for_override_fork_point_while_descendant_of(branch))) is not None
+        return (self.__git.get_config_attr_or_none(git_config_keys.override_fork_point_to(branch)) or
+                self.__git.get_config_attr_or_none(git_config_keys.override_fork_point_while_descendant_of(branch))) is not None
 
     def __get_fork_point_override_data(self, branch: LocalBranchShortName) -> Optional[ForkPointOverrideData]:
         to, while_descendant_of = None, None
-        to_key = self.config_key_for_override_fork_point_to(branch)
+        to_key = git_config_keys.override_fork_point_to(branch)
         if FullCommitHash.is_valid(value=self.__git.get_config_attr_or_none(to_key), git_context=self.__git):
             to = FullCommitHash.of(self.__git.get_config_attr_or_none(to_key))
-        while_descendant_of_key = self.config_key_for_override_fork_point_while_descendant_of(branch)
+        while_descendant_of_key = git_config_keys.override_fork_point_while_descendant_of(branch)
         if FullCommitHash.is_valid(value=self.__git.get_config_attr_or_none(while_descendant_of_key), git_context=self.__git):
             while_descendant_of = FullCommitHash.of(self.__git.get_config_attr_or_none(while_descendant_of_key))
         if not to and not while_descendant_of:
             return None
         if to and not while_descendant_of:
-            warn(f"{to_key} config is set but {while_descendant_of_key} config is missing or invalid")
+            warn(f"`{to_key}` config is set but `{while_descendant_of_key}` config is missing or invalid")
             return None
         if not to and while_descendant_of:
-            warn(f"{while_descendant_of_key} config is set but {to_key} config is missing or invalid")
+            warn(f"`{while_descendant_of_key}` config is set but `{to_key}` config is missing or invalid")
             return None
 
         to_hash: Optional[FullCommitHash] = self.__git.get_commit_hash_by_revision(to)
         while_descendant_of_hash: Optional[FullCommitHash] = self.__git.get_commit_hash_by_revision(while_descendant_of)
         if not to_hash or not while_descendant_of_hash:
             if not to_hash:
-                warn(f"{to_key} config value `{to}` does not point to a valid commit")
+                warn(f"`{to_key}` config value {bold(to)} does not point to a valid commit")
             if not while_descendant_of_hash:
-                warn(f"{while_descendant_of_key} config value `{while_descendant_of}` does not point to a valid commit")
+                warn(f"`{while_descendant_of_key}` config value {bold(while_descendant_of)} does not point to a valid commit")
             return None
         # This check needs to be performed every time the config is retrieved.
         # We can't rely on the values being validated in set_fork_point_override(),
         # since the config could have been modified outside of git-machete.
         if not self.__git.is_ancestor_or_equal(to_hash.full_name(), while_descendant_of_hash.full_name()):
             warn(
-                f"commit {self.__git.get_short_commit_hash_by_revision(to)} pointed by {to_key} config "
-                f"is not an ancestor of commit {self.__git.get_short_commit_hash_by_revision(while_descendant_of)} "
-                f"pointed by {while_descendant_of_key} config")
+                f"commit {bold(self.__git.get_short_commit_hash_by_revision(to))} pointed by `{to_key}` config "
+                f"is not an ancestor of commit {bold(self.__git.get_short_commit_hash_by_revision(while_descendant_of))} "
+                f"pointed by `{while_descendant_of_key}` config")
             return None
         return ForkPointOverrideData(to_hash, while_descendant_of_hash)
 
@@ -1685,9 +1680,9 @@ class MacheteClient:
         # branch currently points.
         if not self.__git.is_ancestor_or_equal(while_descendant_of.full_name(), branch.full_name()):
             warn(fmt(
-                f"since branch <b>{branch}</b> is no longer a descendant of commit "
-                f"{while_descendant_of}, ",
-                f"the fork point override to commit {to} no longer applies.\n",
+                f"since branch {bold(branch)} is no longer a descendant of commit "
+                f"{bold(while_descendant_of)}, ",
+                f"the fork point override to commit {bold(to)} no longer applies.\n",
                 f"Consider running:\n  `git machete fork-point --unset-override {branch}`\n"))
             return None
         debug(f"since branch {branch} is descendant of while_descendant_of={while_descendant_of}, "
@@ -1695,31 +1690,31 @@ class MacheteClient:
         return to
 
     def unset_fork_point_override(self, branch: LocalBranchShortName) -> None:
-        self.__git.unset_config_attr(self.config_key_for_override_fork_point_to(branch))
-        self.__git.unset_config_attr(self.config_key_for_override_fork_point_while_descendant_of(branch))
+        self.__git.unset_config_attr(git_config_keys.override_fork_point_to(branch))
+        self.__git.unset_config_attr(git_config_keys.override_fork_point_while_descendant_of(branch))
 
     def set_fork_point_override(self, branch: LocalBranchShortName, to_revision: AnyRevision) -> None:
         if branch not in self.__git.get_local_branches():
-            raise MacheteException(f"`{branch}` is not a local branch")
+            raise MacheteException(f"{bold(branch)} is not a local branch")
         to_hash = self.__git.get_commit_hash_by_revision(to_revision)
         if not to_hash:
-            raise MacheteException(f"Cannot find revision {to_revision}")
+            raise MacheteException(f"Cannot find revision {bold(to_revision)}")
         if not self.__git.is_ancestor_or_equal(to_hash.full_name(), branch.full_name()):
             raise MacheteException(
-                f"Cannot override fork point: {self.__git.get_revision_repr(to_revision)} is not an ancestor of {branch}")
+                f"Cannot override fork point: {bold(self.__git.get_revision_repr(to_revision))} is not an ancestor of {bold(branch)}")
 
-        to_key = self.config_key_for_override_fork_point_to(branch)
+        to_key = git_config_keys.override_fork_point_to(branch)
         self.__git.set_config_attr(to_key, to_hash)
 
-        while_descendant_of_key = self.config_key_for_override_fork_point_while_descendant_of(branch)
+        while_descendant_of_key = git_config_keys.override_fork_point_while_descendant_of(branch)
         branch_hash = self.__git.get_commit_hash_by_revision(branch)
         self.__git.set_config_attr(while_descendant_of_key, branch_hash)
 
         print(fmt(f"Fork point for <b>{branch}</b> is overridden to "
                   f"<b>{self.__git.get_revision_repr(to_revision)}</b>.\n",
-                  f"This applies as long as {branch} points to (or is descendant of)"
+                  f"This applies as long as <b>{branch}</b> points to (or is descendant of)"
                   " its current head (commit "
-                  f"{self.__git.get_short_commit_hash_by_revision(branch_hash)}).\n\n",
+                  f"<b>{self.__git.get_short_commit_hash_by_revision(branch_hash)}</b>).\n\n",
                   f"This information is stored under git config keys:\n"
                   f"  * `{to_key}`\n"
                   f"  * `{while_descendant_of_key}`\n\n",
@@ -1820,7 +1815,7 @@ class MacheteClient:
                 elif ans in ('q', 'quit'):
                     raise StopInteraction
                 else:
-                    raise MacheteException(f'Cannot create pull request from untracked branch `{branch}`')
+                    raise MacheteException(f'Cannot create pull request from untracked branch {bold(branch)}')
                 return
 
         relation: int = self.__git.get_relation_to_remote_counterpart(branch, remote_branch)
@@ -1968,8 +1963,8 @@ class MacheteClient:
                 earlier_revision=fork_point_hash.full_name(),
                 later_revision=branch.full_name()):
             raise MacheteException(
-                f"Fork point {fork_point_hash} is not ancestor of or the tip "
-                f"of the {branch} branch.")
+                f"Fork point {bold(fork_point_hash)} is not ancestor of or the tip "
+                f"of the {bold(branch)} branch.")
 
     def checkout_github_prs(self,
                             pr_nos: Optional[List[int]],
@@ -2011,7 +2006,7 @@ class MacheteClient:
 
         debug(f'organization is {org}, repository is {repo}')
         if verbose:
-            print(f"Fetching {remote}...")
+            print(f"Fetching {bold(remote)}...")
         self.__git.fetch_remote(remote)
 
         pr: Optional[GitHubPullRequest] = None
@@ -2029,20 +2024,21 @@ class MacheteClient:
                         remote_to_fetch = remote_already_added
                     if remote != remote_to_fetch:
                         if verbose:
-                            print(f"Fetching {remote_to_fetch}...")
+                            print(f"Fetching {bold(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(f"Could not check out PR #{pr.number} because its head branch `{pr.head}` "
-                                               f"is already deleted from `{remote_to_fetch}`.")
+                        raise MacheteException(f"Could not check out PR #{bold(str(pr.number))} "
+                                               f"because its head branch {bold(pr.head)} "
+                                               f"is already deleted from {bold(remote_to_fetch)}.")
             else:
-                warn(f'Pull request #{pr.number} comes from fork and its repository is already deleted. '
-                     f'No remote tracking data will be set up for `{pr.head}` branch.')
+                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.')
                 if verbose:
-                    print(fmt(f"Checking out `{pr.head}` locally..."))
+                    print(fmt(f"Checking out {bold(pr.head)} locally..."))
                 checkout_pr_refs(self.__git, remote, pr.number, LocalBranchShortName.of(pr.head))
                 self.flush_caches()
             if pr.state == 'closed':
-                warn(f'Pull request #{pr.number} is already closed.')
+                warn(f'Pull request #{bold(str(pr.number))} is already closed.')
             debug(f'found {pr}')
 
             path: List[LocalBranchShortName] = self.__get_path_from_pr_chain(pr, all_open_prs)
@@ -2066,7 +2062,7 @@ class MacheteClient:
                             verbose=verbose,
                             switch_head_if_new_branch=False)
                     if pr not in checked_out_prs:
-                        print(fmt(f"Pull request `#{pr.number}` checked out at local branch `{pr.head}`"))
+                        print(fmt(f"Pull request #{bold(str(pr.number))} checked out at local branch {bold(pr.head)}"))
                         checked_out_prs.append(pr)
 
         debug('Current GitHub user is ' + (current_user or '<none>'))
@@ -2074,7 +2070,7 @@ class MacheteClient:
         if len(applicable_prs) == 1:
             self.__git.checkout(LocalBranchShortName.of(pr.head))
             if verbose:
-                print(fmt(f"Switched to local branch `{pr.head}`"))
+                print(fmt(f"Switched to local branch {bold(pr.head)}"))
 
     @staticmethod
     def __get_path_from_pr_chain(current_pr: GitHubPullRequest, all_open_prs: List[GitHubPullRequest]) -> List[LocalBranchShortName]:
@@ -2106,26 +2102,26 @@ class MacheteClient:
                     if pr_from_github:
                         result.append(pr_from_github)
                     else:
-                        raise MacheteException(f"PR #{pr_no} is not found in repository `{org}/{repo}`")
+                        raise MacheteException(f"PR #{bold(str(pr_no))} is not found in repository {bold(org)}/{bold(repo)}")
             if not result:
                 raise MacheteException(
-                    f"Given PRs: {', '.join(map(str, prs_list))} are not found in repository `{org}/{repo}`")
+                    f"Given PRs: {', '.join(map(str, prs_list))} are not found in repository {bold(org)}/{bold(repo)}")
             return result
         if all:
             if not all_opened_prs_from_github:
-                warn(f"Currently there are no pull requests opened in repository `{org}/{repo}`")
+                warn(f"Currently there are no pull requests opened in repository {bold(org)}/{bold(repo)}")
                 return []
             return all_opened_prs_from_github
         elif my and user:
             result = [pr for pr in all_opened_prs_from_github if pr.user == user]
             if not result:
-                warn(f"Current user `{user}` has no open pull request in repository `{org}/{repo}`")
+                warn(f"Current user {bold(user)} has no open pull request in repository {bold(org)}/{bold(repo)}")
                 return []
             return result
         elif by:
             result = [pr for pr in all_opened_prs_from_github if pr.user == by]
             if not result:
-                warn(f"User `{by}` has no open pull request in repository `{org}/{repo}`")
+                warn(f"User {bold(by)} has no open pull request in repository {bold(org)}/{bold(repo)}")
                 return []
             return result
         return []
@@ -2157,22 +2153,22 @@ class MacheteClient:
 
         pr: Optional[GitHubPullRequest] = derive_pull_request_by_head(domain, org, repo, head)
         if not pr:
-            raise MacheteException(f'No PR is opened in `{org}/{repo}` for branch `{head}`')
+            raise MacheteException(f'No PR is opened in {bold(org)}/{bold(repo)} for branch {bold(head)}')
         debug(f'found {pr}')
 
         new_base: Optional[LocalBranchShortName] = self.up_branch.get(LocalBranchShortName.of(head))
         if not new_base:
             raise MacheteException(
-                f'Branch `{head}` does not have a parent branch (it is a root) '
-                f'even though there is an open PR #{pr.number} to `{pr.base}`.\n'
+                f'Branch {bold(head)} does not have a parent branch (it is a root) '
+                f'even though there is an open PR #{bold(str(pr.number))} to {bold(pr.base)}.\n'
                 'Consider modifying the branch definition file (`git machete edit`)'
-                f' so that `{head}` is a child of `{pr.base}`.')
+                f' so that {bold(head)} is a child of {bold(pr.base)}.')
 
         if pr.base != new_base:
             set_base_of_pull_request(domain, org, repo, pr.number, base=new_base)
-            print(fmt(f'The base branch of PR #{pr.number} has been switched to `{new_base}`'))
+            print(f'The base branch of PR #{bold(str(pr.number))} has been switched to {bold(new_base)}')
         else:
-            print(fmt(f'The base branch of PR #{pr.number} is already `{new_base}`'))
+            print(f'The base branch of PR #{bold(str(pr.number))} is already {bold(new_base)}')
 
         if self.__annotations.get(head) and self.__annotations[head].qualifiers_text:
             self.__annotations[head] = Annotation(f'PR #{pr.number} ' + self.__annotations[head].qualifiers_text)
@@ -2181,7 +2177,7 @@ class MacheteClient:
         self.save_definition_file()
 
     def __derive_github_domain(self) -> str:
-        return self.__git.get_config_attr_or_none("machete.github.domain") or DEFAULT_GITHUB_DOMAIN
+        return self.__git.get_config_attr_or_none(key=git_config_keys.GITHUB_DOMAIN) or DEFAULT_GITHUB_DOMAIN
 
     def __derive_remote_and_github_org_and_repo(self,
                                                 domain: str,
@@ -2230,9 +2226,9 @@ class MacheteClient:
             '`machete.github.{domain,remote,organization,repository}`.\n')  # noqa: FS003
 
     def __get_remote_and_organization_and_repository_name_from_config(self) -> RemoteAndOrganizationAndRepository:
-        return RemoteAndOrganizationAndRepository(remote=self.__git.get_config_attr_or_none("machete.github.remote"),
-                                                  organization=self.__git.get_config_attr_or_none("machete.github.organization"),
-                                                  repository=self.__git.get_config_attr_or_none("machete.github.repository"))
+        return RemoteAndOrganizationAndRepository(remote=self.__git.get_config_attr_or_none(key=git_config_keys.GITHUB_REMOTE),
+                                                  organization=self.__git.get_config_attr_or_none(key=git_config_keys.GITHUB_ORGANIZATION),
+                                                  repository=self.__git.get_config_attr_or_none(key=git_config_keys.GITHUB_REPOSITORY))
 
     def create_github_pr(
             self,
@@ -2247,15 +2243,15 @@ class MacheteClient:
 
         base: Optional[LocalBranchShortName] = self.up_branch.get(LocalBranchShortName.of(head))
         if not base:
-            raise MacheteException(f'Could not determine base branch for PR. Branch `{head}` is a root branch.')
+            raise MacheteException(f'Could not determine base branch for PR. Branch {bold(head)} is a root branch.')
         org: str
         repo: str
         domain = self.__derive_github_domain()
         remote, org, repo = self.__derive_remote_and_github_org_and_repo(domain, branch_used_for_tracking_data=head)
-        print(f"Fetching {remote}...")
+        print(f"Fetching {bold(remote)}...")
         self.__git.fetch_remote(remote)
         if '/'.join([remote, base]) not in self.__git.get_remote_branches():
-            warn(f'Base branch for this PR (`{base}`) is not found on remote, pushing...')
+            warn(f'Base branch for this PR ({bold(base)}) is not found on remote, pushing...')
             self.handle_untracked_branch(
                 branch=base,
                 new_remote=remote,
@@ -2271,36 +2267,35 @@ class MacheteClient:
 
         fork_point = self.fork_point(head, use_overrides=True, opt_no_detect_squash_merges=False)
         if not fork_point:
-            raise MacheteException(f"Could not find a fork-point for branch {head}.")
+            raise MacheteException(f"Could not find a fork-point for branch {bold(head)}.")
         commits: List[GitLogEntry] = self.__git.get_commits_between(fork_point, head)
         description_path = self.__git.get_main_git_subpath('info', 'description')
         description: str = utils.slurp_file_or_empty(description_path)
 
         ok_str = '<green><b>OK</b></green>'
-        print(fmt(f'Creating a {"draft " if opt_draft else ""}PR from `{head}` to `{base}`... '), end='', flush=True)
+        print(f'Creating a {"draft " if opt_draft else ""}PR from {bold(head)} to {bold(base)}... ', end='', flush=True)
         pr: GitHubPullRequest = create_pull_request(domain, org, repo, head=head, base=base, title=commits[0].subject,
                                                     description=description, draft=opt_draft)
-        print(fmt(f'{ok_str}, see <b>{pr.html_url}</b>'))
+        print(fmt(f'{ok_str}, see `{pr.html_url}`'))
 
         milestone_path: str = self.__git.get_main_git_subpath('info', 'milestone')
         milestone: str = utils.slurp_file_or_empty(milestone_path).strip()
         if milestone:
-            print(fmt(f'Setting milestone of PR #{pr.number} to {milestone}... '), end='', flush=True)
+            print(f'Setting milestone of PR #{bold(str(pr.number))} to {bold(milestone)}... ', end='', flush=True)
             set_milestone_of_pull_request(domain, org, repo, pr.number, milestone=milestone)
             print(fmt(ok_str))
 
         if current_user:
-            print(fmt(f'Adding `{current_user}` as assignee to PR #{pr.number}... '), end='', flush=True)
+            print(f'Adding {bold(current_user)} as assignee to PR #{bold(str(pr.number))}... ', end='', flush=True)
             add_assignees_to_pull_request(domain, org, repo, pr.number, [current_user])
             print(fmt(ok_str))
 
         reviewers_path = self.__git.get_main_git_subpath('info', 'reviewers')
         reviewers: List[str] = utils.get_non_empty_lines(utils.slurp_file_or_empty(reviewers_path))
         if reviewers:
-            print(
-                fmt(f'Adding {", ".join(f"`{reviewer}`" for reviewer in reviewers)} '
-                    f'as reviewer{"s" if len(reviewers) > 1 else ""} to PR #{pr.number}... '),
-                end='', flush=True)
+            print(f'Adding {", ".join(f"{bold(reviewer)}" for reviewer in reviewers)} '
+                  f'as reviewer{"s" if len(reviewers) > 1 else ""} to PR #{bold(str(pr.number))}... ',
+                  end='', flush=True)
             try:
                 add_reviewers_to_pull_request(domain, org, repo, pr.number, reviewers)
             except UnprocessableEntityHTTPError as e:
@@ -2382,7 +2377,7 @@ class MacheteClient:
                 opt_yes=opt_yes)
         else:
             # We know that there is at least 1 remote, otherwise 's' would be 'NO_REMOTES'
-            print(fmt(f"Branch `{bold(branch)}` is untracked and there's no `{bold('origin')}` repository."))
+            print(f"Branch {bold(branch)} is untracked and there's no {bold('origin')} repository.")
             self.__pick_remote(
                 branch=branch,
                 is_called_from_traverse=is_called_from_traverse,
@@ -2475,12 +2470,13 @@ class MacheteClient:
         up_branch: Optional[LocalBranchShortName] = self.up_branch.get(current_branch)
         if not up_branch:
             raise MacheteException(
-                f'Branch `{current_branch}` does not have a parent branch (it is a root), '
+                f'Branch {bold(current_branch)} does not have a parent branch (it is a root), '
                 'base branch for the PR cannot be established.')
 
         if self.__git.is_ancestor_or_equal(current_branch.full_name(), up_branch.full_name()):
             raise MacheteException(
-                f'All commits in `{current_branch}` branch are already included in `{up_branch}` branch.\nCannot create pull request.')
+                f'All commits in {bold(current_branch)} branch are already included in {bold(up_branch)} branch.\n'
+                f'Cannot create pull request.')
 
         s, remote = self.__git.get_strict_remote_sync_status(current_branch)
         statuses_to_push = (
@@ -2521,12 +2517,12 @@ class MacheteClient:
 
         else:
             if s == SyncToRemoteStatuses.BEHIND_REMOTE:
-                warn(f"Branch {current_branch} is in <b>BEHIND_REMOTE</b> state.\nConsider using 'git pull'.\n")
+                warn(f"Branch {bold(current_branch)} is in <b>BEHIND_REMOTE</b> state.\nConsider using 'git pull'.\n")
                 self.__print_new_line(False)
                 ans = self.ask_if("Proceed with pull request creation?" + get_pretty_choices('y', 'Q'),
                                   "Proceeding with pull request creation...", opt_yes=opt_yes)
             elif s == SyncToRemoteStatuses.DIVERGED_FROM_AND_OLDER_THAN_REMOTE:
-                warn(f"Branch {current_branch} is in <b>DIVERGED_FROM_AND_OLDER_THAN_REMOTE</b> state.\n"
+                warn(f"Branch {bold(current_branch)} is in <b>DIVERGED_FROM_AND_OLDER_THAN_REMOTE</b> state.\n"
                      f"Consider using 'git reset --keep'.\n")
                 self.__print_new_line(False)
                 ans = self.ask_if("Proceed with pull request creation?" + get_pretty_choices('y', 'Q'),
diff --git a/git_machete/generated_docs.py b/git_machete/generated_docs.py
index f47a2ed..17f432c 100644
--- a/git_machete/generated_docs.py
+++ b/git_machete/generated_docs.py
@@ -1017,14 +1017,14 @@ long_docs: Dict[str, str] = {
         Unlike with e.g. `git rebase`, there is no special `--continue` flag, as `traverse` is stateless
         (doesn't keep a state of its own like `git rebase` does in `.git/rebase-apply/`).
 
-        The rebase and push behavior of `traverse` can also be customized for each branch separately using branch qualifiers.
-        There are `rebase=no` and `push=no` qualifiers that can be used to opt out of default behavior (rebasing and pushing).
-        The qualifier can appear anywhere in the annotation but needs to be separated by a whitespace from any other character, e.g. `some_annotation_text rebase=no push=no`.
-        Qualifiers can only be overwritten by manually editing `.git/machete` file or modifying it with `git machete e[dit]` or by updating annotations with `git machete anno`.
+        The rebase, push and slide-out behaviors of `traverse` can also be customized for each branch separately using branch qualifiers.
+        There are `rebase=no`, `push=no` and `slide-out=no` qualifiers that can be used to opt out of default behavior (rebasing, pushing and sliding the branch out of the dependency tree).
+        The qualifier can appear anywhere in the annotation but needs to be separated by a whitespace from any other character, e.g. `some_annotation_text rebase=no push=no slide-out=no`.
+        Qualifiers can only be overwritten by manually editing `.git/machete` file or modifying it with `git machete e[dit]`, or by updating annotations with `git machete anno`.
         Example machete file with branch qualifiers:
         <dim>
           master
-            develop  rebase=no
+            develop  rebase=no slide-out=no
               my-branch  PR #123
               someone-elses-branch  PR #124 rebase=no push=no
               branch-for-local-experiments  push=no
diff --git a/git_machete/git_config_keys.py b/git_machete/git_config_keys.py
new file mode 100644
index 0000000..51eee9b
--- /dev/null
+++ b/git_machete/git_config_keys.py
@@ -0,0 +1,15 @@
+GITHUB_DOMAIN = 'machete.github.domain'
+GITHUB_REMOTE = 'machete.github.remote'
+GITHUB_ORGANIZATION = 'machete.github.organization'
+GITHUB_REPOSITORY = 'machete.github.repository'
+TRAVERSE_PUSH = 'machete.traverse.push'
+WORKTREE_USE_TOP_LEVEL_MACHETE_FILE = 'machete.worktree.useTopLevelMacheteFile'
+STATUS_EXTRA_SPACE_BEFORE_BRANCH_NAME = 'machete.status.extraSpaceBeforeBranchName'
+
+
+def override_fork_point_to(branch: str) -> str:
+    return f'machete.overrideForkPoint.{branch}.to'
+
+
+def override_fork_point_while_descendant_of(branch: str) -> str:
+    return f'machete.overrideForkPoint.{branch}.whileDescendantOf'
diff --git a/git_machete/git_operations.py b/git_machete/git_operations.py
index cc96614..d7415fd 100644
--- a/git_machete/git_operations.py
+++ b/git_machete/git_operations.py
@@ -7,7 +7,7 @@ from pathlib import Path
 from typing import (Any, Callable, Dict, Generator, Iterator, List, Match,
                     NamedTuple, Optional, Set, Tuple)
 
-from git_machete import utils
+from git_machete import git_config_keys, utils
 from git_machete.constants import (MAX_COUNT_FOR_INITIAL_LOG,
                                    GitFormatPatterns, SyncToRemoteStatuses)
 from git_machete.exceptions import MacheteException
@@ -324,7 +324,7 @@ class GitContext:
         return os.path.join(self.__get_main_git_dir(), *fragments)
 
     def get_git_machete_definition_file_path(self) -> str:
-        use_top_level_machete_file = self.get_boolean_config_attr(key='machete.worktree.useTopLevelMacheteFile',
+        use_top_level_machete_file = self.get_boolean_config_attr(key=git_config_keys.WORKTREE_USE_TOP_LEVEL_MACHETE_FILE,
                                                                   default_value=True)
         return os.path.join(self.__get_main_git_dir() if use_top_level_machete_file else self.__get_worktree_git_dir(), 'machete')
 
@@ -725,7 +725,8 @@ class GitContext:
         remote_branch = self.get_currently_rebased_branch_or_none()
         if remote_branch:
             raise MacheteException(
-                f"Rebase of `{remote_branch}` in progress. Conclude the rebase first with `git rebase --continue` or `git rebase --abort`.")
+                f"Rebase of {utils.bold(remote_branch)} in progress. "
+                f"Conclude the rebase first with `git rebase --continue` or `git rebase --abort`.")
         if self.is_am_in_progress():
             raise MacheteException(
                 "`git am` session in progress. Conclude `git am` first with `git am --continue` or `git am --abort`.")
diff --git a/git_machete/github.py b/git_machete/github.py
index f922b46..e3c103c 100644
--- a/git_machete/github.py
+++ b/git_machete/github.py
@@ -13,7 +13,7 @@ from typing import Any, Dict, List, NamedTuple, Optional
 from git_machete.exceptions import (MacheteException,
                                     UnprocessableEntityHTTPError)
 from git_machete.git_operations import GitContext, LocalBranchShortName
-from git_machete.utils import debug, fmt, warn
+from git_machete.utils import bold, debug, fmt, warn
 
 GITHUB_TOKEN_ENV_VAR = 'GITHUB_TOKEN'
 DEFAULT_GITHUB_DOMAIN = "github.com"
@@ -261,8 +261,8 @@ def __fire_github_api_request(domain: str, method: str, path: str,
             warn(f'GitHub API returned `{err.code}` HTTP status with error message: `{err.reason}`. \n'
                  'It looks like the organization or repository name got changed recently and is outdated.\n'
                  'Inferring current organization or repository... '
-                 f'New organization = `{current_repo_and_org.split("/")[0]}`, '
-                 f'new repository = `{current_repo_and_org.split("/")[1]}`.\n'
+                 f'New organization = {bold(current_repo_and_org.split("/")[0])}, '
+                 f'new repository = {bold(current_repo_and_org.split("/")[1])}.\n'
                  'You can update your remote repository via: `git remote set-url <remote_name> <new_repository_url>`.',
                  end='')
             return __fire_github_api_request(domain=domain, method=method, path=new_path, token=token, request_body=request_body)
diff --git a/requirements.coverage.txt b/requirements.coverage.txt
index b1b1bd6..aefbf82 100644
--- a/requirements.coverage.txt
+++ b/requirements.coverage.txt
@@ -1,3 +1,3 @@
-coverage==7.0.5
+coverage==7.1.0
 pytest==7.2.1
 pytest-mock==3.10.0
diff --git a/requirements.isort.txt b/requirements.isort.txt
index 3dfd857..d3cda9c 100644
--- a/requirements.isort.txt
+++ b/requirements.isort.txt
@@ -1,1 +1,1 @@
-isort==5.11.4
+isort==5.12.0
diff --git a/requirements.mypy.txt b/requirements.mypy.txt
index b91981a..4f7bd69 100644
--- a/requirements.mypy.txt
+++ b/requirements.mypy.txt
@@ -1,2 +1,2 @@
-mypy==0.991
+mypy==1.0.0
 pytest==7.2.1
diff --git a/requirements.py-docs.txt b/requirements.py-docs.txt
index d4c5b63..7b32133 100644
--- a/requirements.py-docs.txt
+++ b/requirements.py-docs.txt
@@ -1,3 +1,3 @@
 docutils==0.19
 pygments==2.14.0
-beautifulsoup4==4.11.1
+beautifulsoup4==4.11.2


Test patch:
diff --git a/tests/mockers.py b/tests/mockers.py
index 844670b..7fde6df 100644
--- a/tests/mockers.py
+++ b/tests/mockers.py
@@ -129,6 +129,10 @@ class GitRepositorySandbox:
             f.write(file_content)
         return self
 
+    def merge(self, branch_name: str) -> "GitRepositorySandbox":
+        self.execute(f'git merge {branch_name}')
+        return self
+
 
 class MockGitHubAPIState:
     def __init__(self, pulls: List[Dict[str, Any]], issues: List[Dict[str, Any]] = None) -> None:
@@ -161,7 +165,7 @@ class MockGitHubAPIResponse:
     def read(self) -> bytes:
         return json.dumps(self.response_data).encode()
 
-    def info(self) -> Dict[str, None]:
+    def info(self) -> Dict[str, Any]:
         return {"link": None}
 
 
diff --git a/tests/test_github.py b/tests/test_github.py
index 60d6022..97b98dd 100644
--- a/tests/test_github.py
+++ b/tests/test_github.py
@@ -1,3 +1,4 @@
+import json
 import os
 import subprocess
 from tempfile import mkdtemp
@@ -52,6 +53,38 @@ def mock_input(msg: str) -> str:
     return '1'
 
 
+prs_per_page = 3
+number_of_pages = 3
+
+
+def mock_read(self: Any) -> bytes:
+    response_data = [
+        {
+            'head': {'ref': f'feature_{i}', 'repo': {'full_name': 'testing/checkout_prs',
+                                                     'html_url': 'https://github.com/tester/repo_sandbox.git'}},
+            'user': {'login': 'github_user'},
+            'base': {'ref': 'develop'},
+            'number': f'{i}',
+            'html_url': 'www.github.com',
+            'state': 'open'
+        } for i in range(mock_read.counter * prs_per_page, (mock_read.counter + 1) * prs_per_page)]  # type: ignore[attr-defined]
+
+    mock_read.counter += 1  # type: ignore[attr-defined]
+    return json.dumps(response_data).encode()
+
+
+def mock_info(x: Any) -> Dict[str, Any]:
+    if mock_info.counter < number_of_pages - 1:  # type: ignore[attr-defined]
+        link = f'<https://api.github.com/repositories/1300192/pulls?page={mock_info.counter + 2}>; rel="next"'  # type: ignore[attr-defined]
+    else:
+        link = ''
+    mock_info.counter += 1  # type: ignore[attr-defined]
+    return {"link": link}
+
+
+mock_info.counter = mock_read.counter = 0  # type: ignore[attr-defined]
+
+
 class TestGithub:
     mock_repository_info: Dict[str, str] = {'full_name': 'testing/checkout_prs',
                                             'html_url': 'https://github.com/tester/repo_sandbox.git'}
@@ -127,7 +160,7 @@ class TestGithub:
         |
         o-branch-1
           |
-          o-feature *  PR #15 (github_user) WRONG PR BASE or MACHETE PARENT? PR has 'root' rebase=no push=no
+          o-feature *  PR #15 (github_user) WRONG PR BASE or MACHETE PARENT? PR has root rebase=no push=no
         """
         assert_command(
             ['status'],
@@ -1668,3 +1701,43 @@ class TestGithub:
             remote_and_organization_and_repository = get_parsed_github_remote_url('github.com', url, 'origin')
             assert remote_and_organization_and_repository.organization == organization
             assert remote_and_organization_and_repository.repository == repository
+
+    @mock.patch('git_machete.cli.exit_script', mock_exit_script)
+    # We need to mock GITHUB_REMOTE_PATTERNS in the tests for `test_github_checkout_prs`
+    # due to `git fetch` executed by `checkout-prs` subcommand.
+    @mock.patch('git_machete.github.github_remote_url_patterns', mock_github_remote_url_patterns)
+    @mock.patch('git_machete.options.CommandLineOptions', FakeCommandLineOptions)
+    @mock.patch('git_machete.utils.run_cmd', mock_run_cmd)  # to hide git outputs in tests
+    @mock.patch('git_machete.github.__get_github_token', mock__get_github_token_none)
+    @mock.patch('urllib.request.urlopen', MockContextManager)
+    @mock.patch('git_machete.github.derive_current_user_login', mock_derive_current_user_login)
+    @mock.patch('urllib.request.Request', MockGitHubAPIState([]).new_request())
+    @mock.patch('tests.mockers.MockGitHubAPIResponse.info', mock_info)
+    @mock.patch('tests.mockers.MockGitHubAPIResponse.read', mock_read)
+    def test_github_api_pagination(self, tmp_path: Any) -> None:
+        global prs_per_page
+        (
+            self.repo_sandbox.new_branch("develop")
+            .commit("first commit")
+            .push()
+        )
+        for i in range(number_of_pages * prs_per_page):
+            self.repo_sandbox.check_out('develop').new_branch(f'feature_{i}').commit().push()
+        self.repo_sandbox.check_out('develop')
+        launch_command('discover', '--checked-out-since=1 day ago')
+        expected_status_output = '  develop *\n' + '\n'.join([f' |\n o-feature_{i}'
+                                                              for i in range(number_of_pages * prs_per_page)]) + '\n'
+        assert_command(['status'], expected_status_output)
+
+        self.repo_sandbox.check_out('develop')
+        for i in range(number_of_pages * prs_per_page):
+            self.repo_sandbox.execute(f"git branch -D feature_{i}")
+        launch_command('discover', '--checked-out-since=1 day ago')
+        expected_status_output = '  develop *\n'
+        assert_command(['status'], expected_status_output)
+
+        launch_command('github', 'checkout-prs', '--all')
+        launch_command('discover', '--checked-out-since=1 day ago')
+        expected_status_output = '  develop *\n' + '\n'.join([f' |\n o-feature_{i}  rebase=no push=no'
+                                                              for i in range(number_of_pages * prs_per_page)]) + '\n'
+        assert_command(['status'], expected_status_output)
diff --git a/tests/test_traverse.py b/tests/test_traverse.py
index 0a5f6e8..11faaff 100644
--- a/tests/test_traverse.py
+++ b/tests/test_traverse.py
@@ -472,3 +472,45 @@ class TestTraverse:
               o-ignore-trailing *
             """,
         )
+
+    def test_traverse_qualifiers_no_slide_out(self, mocker: Any) -> None:
+        mocker.patch('git_machete.utils.run_cmd', mock_run_cmd)  # to hide git outputs in tests
+        self.setup_discover_standard_tree()
+
+        body: str = \
+            """
+            develop
+            \tallow-ownership-link
+            \t\tbuild-chain
+            \tcall-ws slide-out=no
+            \t\tdrop-constraint
+            master
+            \thotfix/add-trigger
+            \t\tignore-trailing
+            """
+
+        body = dedent(body).strip()
+        rewrite_definition_file(body)
+        self.repo_sandbox.check_out('develop').merge('call-ws')
+
+        launch_command("traverse", "-Wy")
+        assert_command(
+            ["status"],
+            """
+            develop *
+            |
+            o-allow-ownership-link
+            | |
+            | o-build-chain
+            |
+            m-call-ws  slide-out=no
+              |
+              o-drop-constraint
+
+            master
+            |
+            o-hotfix/add-trigger
+              |
+              o-ignore-trailing
+            """,
+        )