Repository: VirtusLab/git-machete

Issue:
Problems around parsing branch names
```
$ git machete diff develop
...
AttributeError: 'str' object has no attribute 'full_name'

$ git machete log develop
(ok)

$ git machete diff refs/heads/develop
...
TypeError: LocalBranchShortName cannot accept refs/heads or refs/remotes. Given value: refs/heads/develop.
Consider posting an issue on https://github.com/VirtusLab/git-machete/issues/new

$ git machete log refs/heads/develop
...
TypeError: LocalBranchShortName cannot accept refs/heads or refs/remotes. Given value: refs/heads/develop.
Consider posting an issue on https://github.com/VirtusLab/git-machete/issues/new
```

Hell knows what other cases result in an error... let's get this sorted and provide decent regression tests.

Discussion:
PawelLipski: > @PawelLipski Can we safely assume that the user should provide branch short name, IMO that would be the most intuitive input type, wdyt?

Yes... but still, we should be prepared for the case of someone passing `refs/heads/develop`... we can crash git-machete but in a controlled way (now some random error is happening)
PawelLipski: > > @PawelLipski Can we safely assume that the user should provide branch short name, IMO that would be the most intuitive input type, wdyt?
> 
> Yes... but still, we should be prepared for the case of someone passing `refs/heads/develop`... we can crash git-machete but in a controlled way (now some random error is happening)

Although ideally the case of `git machete diff refs/heads/develop` should behave exacly as `git machete diff develop`
amalota: > > > @PawelLipski Can we safely assume that the user should provide branch short name, IMO that would be the most intuitive input type, wdyt?
> > 
> > 
> > Yes... but still, we should be prepared for the case of someone passing `refs/heads/develop`... we can crash git-machete but in a controlled way (now some random error is happening)
> 
> Although ideally the case of `git machete diff refs/heads/develop` should behave exactly as `git machete diff develop`

I can add a simple parser which would inference the type between `LocalBranchShortName` and `LocalBranchFullName`, so both would work, wdyt?
PawelLipski: > @PawelLipski I can add a simple parser which would inference the type between `LocalBranchShortName` and `LocalBranchFullName`, so both would work, wdyt?

Okay... let's give it a shot
codecov-commenter: # [Codecov](https://codecov.io/gh/VirtusLab/git-machete/pull/525?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=VirtusLab) Report
> Merging [#525](https://codecov.io/gh/VirtusLab/git-machete/pull/525?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=VirtusLab) (76cd995) into [develop](https://codecov.io/gh/VirtusLab/git-machete/commit/91fc20b6976a4bb63d3b72095667e1c9ff1799b1?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=VirtusLab) (91fc20b) will **increase** coverage by `0.77%`.
> The diff coverage is `100.00%`.

```diff
@@             Coverage Diff             @@
##           develop     #525      +/-   ##
===========================================
+ Coverage    66.09%   66.86%   +0.77%     
===========================================
  Files           10       10              
  Lines         2855     2855              
  Branches       694      694              
===========================================
+ Hits          1887     1909      +22     
+ Misses         706      682      -24     
- Partials       262      264       +2     
```


| [Impacted Files](https://codecov.io/gh/VirtusLab/git-machete/pull/525?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=VirtusLab) | Coverage Δ | |
|---|---|---|
| [git\_machete/\_\_init\_\_.py](https://codecov.io/gh/VirtusLab/git-machete/pull/525/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=VirtusLab#diff-Z2l0X21hY2hldGUvX19pbml0X18ucHk=) | `100.00% <100.00%> (ø)` | |
| [git\_machete/cli.py](https://codecov.io/gh/VirtusLab/git-machete/pull/525/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=VirtusLab#diff-Z2l0X21hY2hldGUvY2xpLnB5) | `69.89% <100.00%> (+2.79%)` | :arrow_up: |
| [git\_machete/options.py](https://codecov.io/gh/VirtusLab/git-machete/pull/525/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=VirtusLab#diff-Z2l0X21hY2hldGUvb3B0aW9ucy5weQ==) | `79.16% <100.00%> (ø)` | |
| [git\_machete/client.py](https://codecov.io/gh/VirtusLab/git-machete/pull/525/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=VirtusLab#diff-Z2l0X21hY2hldGUvY2xpZW50LnB5) | `61.97% <0.00%> (+0.29%)` | :arrow_up: |
| [git\_machete/git\_operations.py](https://codecov.io/gh/VirtusLab/git-machete/pull/525/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=VirtusLab#diff-Z2l0X21hY2hldGUvZ2l0X29wZXJhdGlvbnMucHk=) | `70.72% <0.00%> (+0.79%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/VirtusLab/git-machete/pull/525?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=VirtusLab).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=VirtusLab)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/VirtusLab/git-machete/pull/525?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=VirtusLab). Last update [91fc20b...76cd995](https://codecov.io/gh/VirtusLab/git-machete/pull/525?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=VirtusLab). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=VirtusLab).


Patch:
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index 64c9190..415d7be 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -1,5 +1,10 @@
 # Release notes
 
+## New in git-machete 3.10.1
+
+- fixed: `git machete diff` doesn't crash when supplied with the short branch name (`develop`)
+- fixed: `git machete {log, add, anno, fork-point, is-managed, show}` doesn't crash when supplied with the full branch name (`refs/heads/develop`)
+
 ## New in git-machete 3.10.0
 
 - added: boolean git config key `machete.status.extraSpaceBeforeBranchName` that enable configurable rendering of `status` command
diff --git a/git_machete/__init__.py b/git_machete/__init__.py
index 3f3750c..e88098e 100644
--- a/git_machete/__init__.py
+++ b/git_machete/__init__.py
@@ -1,1 +1,1 @@
-__version__ = '3.10.0'
+__version__ = '3.10.1'
diff --git a/git_machete/cli.py b/git_machete/cli.py
index 2bb1fee..fbfcb46 100644
--- a/git_machete/cli.py
+++ b/git_machete/cli.py
@@ -13,7 +13,7 @@ from git_machete import utils
 from git_machete.client import MacheteClient
 from git_machete.docs import short_docs, long_docs
 from git_machete.exceptions import MacheteException, StopInteraction
-from git_machete.git_operations import AnyRevision, GitContext, LocalBranchShortName, RemoteBranchShortName
+from git_machete.git_operations import AnyBranchName, AnyRevision, GitContext, LocalBranchShortName, RemoteBranchShortName
 from git_machete.utils import fmt, underline, excluding, warn, AnsiEscapeCodes
 
 T = TypeVar('T')
@@ -378,7 +378,7 @@ def update_cli_opts_using_parsed_args(
 
     for opt, arg in vars(parsed_args).items():
         if opt == "branch":
-            cli_opts.opt_branch = LocalBranchShortName.of(arg)
+            cli_opts.opt_branch = AnyBranchName.of(arg)
         elif opt == "checked_out_since":
             cli_opts.opt_checked_out_since = arg
         elif opt == "color":
@@ -475,9 +475,9 @@ def set_utils_global_variables(
     utils.verbose_mode = cli_opts.opt_verbose
 
 
-def get_branch_arg_or_current_branch(
-        cli_opts: git_machete.options.CommandLineOptions, git_context: GitContext) -> LocalBranchShortName:
-    return cli_opts.opt_branch or git_context.get_current_branch()
+def get_local_branch_short_name_from_arg_or_current_branch(
+        branch_from_arg: Optional[AnyBranchName], git_context: GitContext) -> LocalBranchShortName:
+    return LocalBranchShortName.of(branch_from_arg.replace('refs/heads/', '')) if branch_from_arg else git_context.get_current_branch()
 
 
 def exit_script(status_code: Optional[int] = None, error: Optional[BaseException] = None) -> None:
@@ -540,7 +540,7 @@ def launch(orig_args: List[str]) -> None:
         should_perform_interactive_slide_out = MacheteClient.should_perform_interactive_slide_out(cmd)
         if cmd == "add":
             machete_client.read_definition_file(perform_interactive_slide_out=should_perform_interactive_slide_out)
-            branch = get_branch_arg_or_current_branch(cli_opts, git)
+            branch = get_local_branch_short_name_from_arg_or_current_branch(cli_opts.opt_branch, git)
             machete_client.add(
                 branch=branch,
                 opt_onto=cli_opts.opt_onto,
@@ -560,7 +560,7 @@ def launch(orig_args: List[str]) -> None:
             if cli_opts.opt_sync_github_prs:
                 machete_client.sync_annotations_to_github_prs()
             else:
-                branch = cli_opts.opt_branch or git.get_current_branch()
+                branch = get_local_branch_short_name_from_arg_or_current_branch(cli_opts.opt_branch, git)
                 machete_client.expect_in_managed_branches(branch)
                 if parsed_cli.annotation_text:
                     machete_client.annotate(branch, parsed_cli.annotation_text)
@@ -578,7 +578,8 @@ def launch(orig_args: List[str]) -> None:
             machete_client.delete_unmanaged(opt_yes=cli_opts.opt_yes)
         elif cmd in {"diff", alias_by_command["diff"]}:
             machete_client.read_definition_file(perform_interactive_slide_out=should_perform_interactive_slide_out)
-            machete_client.diff(branch=parsed_cli.branch, opt_stat=cli_opts.opt_stat)  # passing None if not specified
+            machete_client.diff(branch=get_local_branch_short_name_from_arg_or_current_branch(cli_opts.opt_branch, git),
+                                opt_stat=cli_opts.opt_stat)  # passing None if not specified
         elif cmd == "discover":
             # No need to read definition file.
             machete_client.discover_tree(
@@ -594,7 +595,7 @@ def launch(orig_args: List[str]) -> None:
             print(os.path.abspath(machete_client.definition_file_path))
         elif cmd == "fork-point":
             machete_client.read_definition_file(perform_interactive_slide_out=should_perform_interactive_slide_out)
-            branch = get_branch_arg_or_current_branch(cli_opts, git)
+            branch = get_local_branch_short_name_from_arg_or_current_branch(cli_opts.opt_branch, git)
             if cli_opts.opt_inferred:
                 print(machete_client.fork_point(
                     branch=branch,
@@ -670,7 +671,7 @@ def launch(orig_args: List[str]) -> None:
                 machete_client.delete_untracked(opt_yes=cli_opts.opt_yes)
         elif cmd == "is-managed":
             machete_client.read_definition_file(perform_interactive_slide_out=should_perform_interactive_slide_out)
-            branch = get_branch_arg_or_current_branch(cli_opts, git)
+            branch = get_local_branch_short_name_from_arg_or_current_branch(cli_opts.opt_branch, git)
             if branch is None or branch not in machete_client.managed_branches:
                 exit_script(1)
         elif cmd == "list":
@@ -714,7 +715,7 @@ def launch(orig_args: List[str]) -> None:
                 print("\n".join(res))
         elif cmd in {"log", alias_by_command["log"]}:
             machete_client.read_definition_file(perform_interactive_slide_out=should_perform_interactive_slide_out)
-            branch = get_branch_arg_or_current_branch(cli_opts, git)
+            branch = get_local_branch_short_name_from_arg_or_current_branch(cli_opts.opt_branch, git)
             machete_client.log(branch)
         elif cmd == "reapply":
             machete_client.read_definition_file(perform_interactive_slide_out=should_perform_interactive_slide_out)
@@ -732,7 +733,7 @@ def launch(orig_args: List[str]) -> None:
                 cli_opts.opt_no_interactive_rebase)
         elif cmd == "show":
             direction = parsed_cli.direction
-            branch = get_branch_arg_or_current_branch(cli_opts, git)
+            branch = get_local_branch_short_name_from_arg_or_current_branch(cli_opts.opt_branch, git)
             if direction == "current":
                 if 'branch' in parsed_cli:
                     raise MacheteException(
diff --git a/git_machete/options.py b/git_machete/options.py
index e8f854f..6d60661 100644
--- a/git_machete/options.py
+++ b/git_machete/options.py
@@ -1,14 +1,14 @@
 from typing import Optional, List
 
 from git_machete.exceptions import MacheteException
-from git_machete.git_operations import AnyRevision, LocalBranchShortName
+from git_machete.git_operations import AnyBranchName, AnyRevision, LocalBranchShortName
 
 
 class CommandLineOptions:
 
     def __init__(self) -> None:
         self.opt_as_root: bool = False
-        self.opt_branch: Optional[LocalBranchShortName] = None
+        self.opt_branch: Optional[AnyBranchName] = None
         self.opt_checked_out_since: Optional[str] = None
         self.opt_color: str = "auto"
         self.opt_debug: bool = False


Test patch:
diff --git a/tests/mockers.py b/tests/mockers.py
index 7e76788..d4199cb 100644
--- a/tests/mockers.py
+++ b/tests/mockers.py
@@ -27,21 +27,6 @@ def popen(command: str) -> str:
         return process.read().strip()
 
 
-def get_current_commit_hash() -> FullCommitHash:
-    """Returns hash of a commit of the current branch head."""
-    return FullCommitHash.of(popen("git rev-parse HEAD"))
-
-
-def mock_run_cmd(cmd: str, *args: str, **kwargs: Any) -> int:
-    completed_process: subprocess.CompletedProcess[bytes] = subprocess.run(
-        [cmd] + list(args), stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs)
-    exit_code: int = completed_process.returncode
-
-    if exit_code != 0:
-        print(dim(f"<exit code: {exit_code}>\n"), file=sys.stderr)
-    return completed_process.returncode
-
-
 class GitRepositorySandbox:
     second_remote_path = mkdtemp()
 
@@ -78,6 +63,12 @@ class GitRepositorySandbox:
         self.execute(f'git commit -m "{message}"')
         return self
 
+    def add_file_with_content_and_commit(self, file_name: str = 'file_name.txt', file_content: str = 'Some file content\n', message: str = "Some commit message.") -> "GitRepositorySandbox":
+        self.write_to_file(file_name=file_name, file_content=file_content)
+        self.execute(f"git add {file_name}")
+        self.execute(f'git commit -m "{message}"')
+        return self
+
     def commit_amend(self, message: str) -> "GitRepositorySandbox":
         self.execute(f'git commit --amend -m "{message}"')
         return self
@@ -111,6 +102,11 @@ class GitRepositorySandbox:
         self.execute(f'git config {key} {value}')
         return self
 
+    def write_to_file(self, file_name: str, file_content: str) -> "GitRepositorySandbox":
+        with open(file_name, 'w') as f:
+            f.write(file_content)
+        return self
+
 
 class MockGitHubAPIState:
     def __init__(self, pulls: List[Dict[str, Any]], issues: List[Dict[str, Any]] = None) -> None:
@@ -341,6 +337,21 @@ def rewrite_definition_file(new_body: str) -> None:
         def_file.writelines(new_body)
 
 
+def get_current_commit_hash() -> FullCommitHash:
+    """Returns hash of a commit of the current branch head."""
+    return FullCommitHash.of(popen("git rev-parse HEAD"))
+
+
+def mock_run_cmd(cmd: str, *args: str, **kwargs: Any) -> int:
+    completed_process: subprocess.CompletedProcess[bytes] = subprocess.run(
+        [cmd] + list(args), stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs)
+    exit_code: int = completed_process.returncode
+
+    if exit_code != 0:
+        print(dim(f"<exit code: {exit_code}>\n"), file=sys.stderr)
+    return completed_process.returncode
+
+
 def mock_run_cmd_and_forward_stdout(cmd: str, *args: str, **kwargs: Any) -> int:
     completed_process: subprocess.CompletedProcess[bytes] = subprocess.run(
         [cmd] + list(args), stdout=subprocess.PIPE, stderr=subprocess.PIPE, ** kwargs)
diff --git a/tests/test_add.py b/tests/test_add.py
index 1045e71..0a35cf1 100644
--- a/tests/test_add.py
+++ b/tests/test_add.py
@@ -1,7 +1,6 @@
 from typing import Any
 
-from .mockers import (GitRepositorySandbox, assert_command, launch_command,
-                      mock_run_cmd)
+from .mockers import (GitRepositorySandbox, assert_command, launch_command, mock_run_cmd)
 
 
 class TestAdd:
@@ -40,13 +39,32 @@ class TestAdd:
 
         self.repo_sandbox.new_branch("bugfix/feature_fail")
 
+        # Test `git machete add` without providing the branch name
         assert_command(
-            ['add', '-y', 'bugfix/feature_fail'],
+            ['add', '-y'],
             'Adding `bugfix/feature_fail` onto the inferred upstream (parent) branch `develop`\n'
             'Added branch `bugfix/feature_fail` onto `develop`\n',
             strip_indentation=False
         )
 
+        self.repo_sandbox.check_out('develop')
+        self.repo_sandbox.new_branch("bugfix/some_feature")
+        assert_command(
+            ['add', '-y', 'bugfix/some_feature'],
+            'Adding `bugfix/some_feature` onto the inferred upstream (parent) branch `develop`\n'
+            'Added branch `bugfix/some_feature` onto `develop`\n',
+            strip_indentation=False
+        )
+
+        self.repo_sandbox.check_out('develop')
+        self.repo_sandbox.new_branch("bugfix/another_feature")
+        assert_command(
+            ['add', '-y', 'refs/heads/bugfix/another_feature'],
+            'Adding `bugfix/another_feature` onto the inferred upstream (parent) branch `develop`\n'
+            'Added branch `bugfix/another_feature` onto `develop`\n',
+            strip_indentation=False
+        )
+
         # test with --onto option
         self.repo_sandbox.new_branch("chore/remove_indentation")
 
diff --git a/tests/test_anno.py b/tests/test_anno.py
new file mode 100644
index 0000000..f912764
--- /dev/null
+++ b/tests/test_anno.py
@@ -0,0 +1,72 @@
+from .mockers import (GitRepositorySandbox, assert_command, launch_command)
+
+
+class TestAnno:
+
+    def setup_method(self) -> None:
+
+        self.repo_sandbox = GitRepositorySandbox()
+
+        (
+            self.repo_sandbox
+            # Create the remote and sandbox repos, chdir into sandbox repo
+            .new_repo(self.repo_sandbox.remote_path, "--bare")
+            .new_repo(self.repo_sandbox.local_path)
+            .execute(f"git remote add origin {self.repo_sandbox.remote_path}")
+            .execute('git config user.email "tester@test.com"')
+            .execute('git config user.name "Tester Test"')
+        )
+
+    def test_anno(self) -> None:
+        """
+        Verify behaviour of a 'git machete anno' command.
+        """
+
+        (
+            self.repo_sandbox.new_branch("master")
+                .commit("master commit.")
+                .new_branch("develop")
+                .commit("develop commit.")
+                .new_branch("feature")
+                .commit("feature commit.")
+                .check_out("develop")
+                .commit("New commit on develop")
+        )
+        launch_command('discover', '-y')
+
+        # Test `git machete anno` without providing the branch name
+        launch_command('anno', 'Custom annotation for `develop` branch')
+        assert_command(
+            ["status"],
+            """
+            master (untracked)
+
+            develop *  Custom annotation for `develop` branch (untracked)
+            |
+            x-feature (untracked)
+            """,
+        )
+
+        launch_command('anno', '-b=feature', 'Custom annotation for `feature` branch')
+        assert_command(
+            ["status"],
+            """
+            master (untracked)
+
+            develop *  Custom annotation for `develop` branch (untracked)
+            |
+            x-feature  Custom annotation for `feature` branch (untracked)
+            """,
+        )
+
+        launch_command('anno', '-b=refs/heads/feature', 'Custom annotation for `feature` branch')
+        assert_command(
+            ["status"],
+            """
+            master (untracked)
+
+            develop *  Custom annotation for `develop` branch (untracked)
+            |
+            x-feature  Custom annotation for `feature` branch (untracked)
+            """,
+        )
diff --git a/tests/test_diff.py b/tests/test_diff.py
new file mode 100644
index 0000000..72d9c1a
--- /dev/null
+++ b/tests/test_diff.py
@@ -0,0 +1,52 @@
+from typing import Any
+
+from .mockers import (GitRepositorySandbox, assert_command, mock_run_cmd_and_forward_stdout)
+
+
+class TestDiff:
+
+    def setup_method(self) -> None:
+
+        self.repo_sandbox = GitRepositorySandbox()
+
+        (
+            self.repo_sandbox
+            # Create the remote and sandbox repos, chdir into sandbox repo
+            .new_repo(self.repo_sandbox.remote_path, "--bare")
+            .new_repo(self.repo_sandbox.local_path)
+            .execute(f"git remote add origin {self.repo_sandbox.remote_path}")
+            .execute('git config user.email "tester@test.com"')
+            .execute('git config user.name "Tester Test"')
+        )
+
+    def test_diff(self, mocker: Any) -> None:
+        """
+        Verify behaviour of a 'git machete diff' command.
+        """
+        mocker.patch('git_machete.utils.run_cmd', mock_run_cmd_and_forward_stdout)  # to hide git outputs in tests
+        (
+            self.repo_sandbox.new_branch("master")
+                .add_file_with_content_and_commit(message='master commit1')
+                .push()
+                .new_branch("develop")
+                .add_file_with_content_and_commit(file_name='develop_file_name.txt', file_content='Develop content\n', message='develop commit')
+                .push()
+        )
+
+        expected_status_output = (
+"""diff --git a/develop_file_name.txt b/develop_file_name.txt
+new file mode 100644
+index 0000000..a3bd4e5
+--- /dev/null
++++ b/develop_file_name.txt
+@@ -0,0 +1 @@
++Develop content
+
+"""  # noqa: E122
+        )
+        # Test `git machete diff` without providing the branch name
+        assert_command(["diff"], expected_status_output, strip_indentation=False)
+
+        assert_command(["diff", "develop"], expected_status_output, strip_indentation=False)
+
+        assert_command(["diff", "refs/heads/develop"], expected_status_output, strip_indentation=False)
diff --git a/tests/test_fork_point.py b/tests/test_fork_point.py
new file mode 100644
index 0000000..404bb40
--- /dev/null
+++ b/tests/test_fork_point.py
@@ -0,0 +1,52 @@
+from .mockers import (GitRepositorySandbox, assert_command, launch_command)
+
+import os
+
+
+class TestForkPoint:
+
+    def setup_method(self) -> None:
+
+        self.repo_sandbox = GitRepositorySandbox()
+
+        (
+            self.repo_sandbox
+            # Create the remote and sandbox repos, chdir into sandbox repo
+            .new_repo(self.repo_sandbox.remote_path, "--bare")
+            .new_repo(self.repo_sandbox.local_path)
+            .execute(f"git remote add origin {self.repo_sandbox.remote_path}")
+            .execute('git config user.email "tester@test.com"')
+            .execute('git config user.name "Tester Test"')
+        )
+
+    def test_fork_point(self) -> None:
+        """
+        Verify behaviour of a 'git machete fork-point' command.
+        """
+        fixed_committer_and_author_date = 'Mon 20 Aug 2018 20:19:19 +0200'
+        os.environ['GIT_COMMITTER_DATE'] = fixed_committer_and_author_date
+        os.environ['GIT_AUTHOR_DATE'] = fixed_committer_and_author_date
+        try:
+            (
+                self.repo_sandbox.new_branch("master")
+                    .add_file_with_content_and_commit(message="master commit.")
+                    .new_branch("develop")
+                    .add_file_with_content_and_commit(file_content='develop content', message="develop commit.")
+                    .new_branch("feature")
+                    .commit('feature commit.')
+            )
+        finally:
+            # Clean-up environment variables
+            os.environ.pop('GIT_COMMITTER_DATE', None)
+            os.environ.pop('GIT_AUTHOR_DATE', None)
+
+        launch_command('discover', '-y')
+
+        # Test `git machete fork-point` without providing the branch name
+        # hash 67007ed30def3b9b658380b895a9f62b525286e0 corresponds to the commit on develop branch
+        assert_command(["fork-point"], "67007ed30def3b9b658380b895a9f62b525286e0\n", strip_indentation=False)
+
+        # hash 515319fa0ab47f372f6159bcc8ac27b43ee8a0ed corresponds to the commit on master branch
+        assert_command(["fork-point", 'develop'], "515319fa0ab47f372f6159bcc8ac27b43ee8a0ed\n", strip_indentation=False)
+
+        assert_command(["fork-point", 'refs/heads/develop'], "515319fa0ab47f372f6159bcc8ac27b43ee8a0ed\n", strip_indentation=False)
diff --git a/tests/test_github.py b/tests/test_github.py
index 3af713a..90fe555 100644
--- a/tests/test_github.py
+++ b/tests/test_github.py
@@ -199,7 +199,7 @@ class TestGithub:
             o-call-ws  PR #31 (github_user) (ahead of origin)
               |
               x-drop-constraint (untracked)
-            """,
+            """
         )
 
         # Test anno-prs using custom remote URL provided by git config keys
diff --git a/tests/test_is_managed.py b/tests/test_is_managed.py
new file mode 100644
index 0000000..9fa7de4
--- /dev/null
+++ b/tests/test_is_managed.py
@@ -0,0 +1,46 @@
+import pytest
+
+from .mockers import (GitRepositorySandbox, launch_command)
+
+
+class TestIsManaged:
+
+    def setup_method(self) -> None:
+
+        self.repo_sandbox = GitRepositorySandbox()
+
+        (
+            self.repo_sandbox
+            # Create the remote and sandbox repos, chdir into sandbox repo
+            .new_repo(self.repo_sandbox.remote_path, "--bare")
+            .new_repo(self.repo_sandbox.local_path)
+            .execute(f"git remote add origin {self.repo_sandbox.remote_path}")
+            .execute('git config user.email "tester@test.com"')
+            .execute('git config user.name "Tester Test"')
+        )
+
+    def test_is_managed(self) -> None:
+        """
+        Verify behaviour of a 'git machete is-managed' command.
+        """
+        (
+            self.repo_sandbox.new_branch("master")
+                .commit("master commit.")
+                .new_branch("develop")
+                .commit("develop commit.")
+                .new_branch("feature")
+                .commit("feature commit.")
+                .check_out("develop")
+                .commit("New commit on develop")
+        )
+        launch_command("discover", "-y")
+
+        # Test `git machete is-managed` without providing the branch name
+        launch_command('is-managed')
+
+        launch_command('is-managed', 'develop')
+
+        launch_command('is-managed', 'refs/heads/develop')
+
+        with pytest.raises(SystemExit):
+            launch_command('is-managed', 'random_branch_name')
diff --git a/tests/test_log.py b/tests/test_log.py
index 706f4c5..263e78b 100644
--- a/tests/test_log.py
+++ b/tests/test_log.py
@@ -1,7 +1,6 @@
 from typing import Any
 
-from .mockers import (GitRepositorySandbox, get_current_commit_hash,
-                      launch_command, mock_run_cmd_and_forward_stdout)
+from .mockers import (GitRepositorySandbox, get_current_commit_hash, launch_command, mock_run_cmd_and_forward_stdout)
 
 
 class TestLog:
@@ -34,17 +33,17 @@ class TestLog:
         self.repo_sandbox.commit()
         childs_second_commit_hash = get_current_commit_hash()
 
-        log_content = launch_command('log')
+        log_contents = [launch_command('log'), launch_command('log', 'child'), launch_command('log', 'refs/heads/child')]
 
-        assert childs_first_commit_hash in log_content, \
+        assert all(childs_first_commit_hash in log_content for log_content in log_contents), \
             ("Verify that oldest commit from current branch is visible when "
              "executing `git machete log`."
              )
-        assert childs_second_commit_hash in log_content, \
+        assert all(childs_second_commit_hash in log_content for log_content in log_contents), \
             ("Verify that youngest commit from current branch is visible when "
              "executing `git machete log`."
              )
-        assert roots_only_commit_hash not in log_content, \
+        assert all(roots_only_commit_hash not in log_content for log_content in log_contents), \
             ("Verify that commits from parent branch are not visible when "
              "executing `git machete log`."
              )
diff --git a/tests/test_show.py b/tests/test_show.py
index 49378e3..3ece362 100644
--- a/tests/test_show.py
+++ b/tests/test_show.py
@@ -1,7 +1,6 @@
 from typing import Any
 
-from .mockers import (GitRepositorySandbox, assert_command, launch_command,
-                      mock_run_cmd)
+from .mockers import (GitRepositorySandbox, assert_command, launch_command, mock_run_cmd)
 
 
 class TestShow:
@@ -80,7 +79,7 @@ class TestShow:
             o-hotfix/add-trigger (diverged from origin)
               |
               o-ignore-trailing * (diverged from & older than origin)
-            """,
+            """
         )
 
     def test_show(self, mocker: Any) -> None:
@@ -90,6 +89,7 @@ class TestShow:
 
         assert launch_command("show", "up").strip() == "hotfix/add-trigger"
         assert launch_command("show", "up", "call-ws").strip() == "develop"
+        assert launch_command("show", "up", "refs/heads/call-ws").strip() == "develop"
         assert launch_command("show", "current").strip() == "ignore-trailing"
 
     def test_show_up(self, mocker: Any) -> None:
diff --git a/tests/test_traverse.py b/tests/test_traverse.py
index 9d5efe2..9906333 100644
--- a/tests/test_traverse.py
+++ b/tests/test_traverse.py
@@ -80,7 +80,7 @@ class TestTraverse:
             o-hotfix/add-trigger (diverged from origin)
               |
               o-ignore-trailing * (diverged from & older than origin)
-            """,
+            """
         )
 
     def test_traverse_no_push(self, mocker: Any) -> None: