Repository: VirtusLab/git-machete
Pull request #1457 (2025-07-03 16:14:26)

No longer slide out branches marked as `slide-out=no` in `git machete slide-out --removed-from-remote`
<!-- start git-machete generated -->

# Based on PR #1456

## Chain of upstream PRs as of 2025-07-03

* PR #1454:
  `develop` ← `fix/bisect-recognize`

  * PR #1455:
    `fix/bisect-recognize` ← `chore/close-github-milestone`

    * PR #1456:
      `chore/close-github-milestone` ← `docs/more-spacing`

      * **PR #1457 (THIS ONE)**:
        `docs/more-spacing` ← `fix/slide-out-no-remove-from-remote`

<!-- end git-machete generated -->



Patch:
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index 942dcbc..48ad650 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -4,6 +4,7 @@
 
 - fixed: incorrect `Could not determine base branch for PR` error messages when creating PRs from `git machete traverse -H`
 - fixed: `git bisect` is recognized as a separate repository state by `git machete status` and side-effecting operations
+- fixed: branches marked as `slide-out=no` are no longer slid out by `git machete slide-out --removed-from-remote`
 
 ## New in git-machete 3.36.0
 
diff --git a/docs/man/git-machete.1 b/docs/man/git-machete.1
index a3b9054..5ceb92a 100644
--- a/docs/man/git-machete.1
+++ b/docs/man/git-machete.1
@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
 .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
 .in \\n[rst2man-indent\\n[rst2man-indent-level]]u
 ..
-.TH "GIT-MACHETE" "1" "Jun 27, 2025" "" "git-machete"
+.TH "GIT-MACHETE" "1" "Jul 03, 2025" "" "git-machete"
 .SH NAME
 git-machete \- git-machete 3.36.1
 .sp
diff --git a/git_machete/client/slide_out.py b/git_machete/client/slide_out.py
index d2e48e8..55f10df 100644
--- a/git_machete/client/slide_out.py
+++ b/git_machete/client/slide_out.py
@@ -117,8 +117,12 @@ class SlideOutMacheteClient(MacheteClient):
         slid_out_branches: List[LocalBranchShortName] = []
         for branch in self.managed_branches.copy():
             if self._git.is_removed_from_remote(branch) and not self.down_branches_for(branch):
-                print(fmt(f"Sliding out <b>{branch}</b>"))
-                slid_out_branches.append(branch)
+                anno = self.annotations.get(branch)
+                if anno and not anno.qualifiers.slide_out:
+                    print(fmt(f"Skipping <b>{branch}</b> as it's marked as `slide-out=no`"))
+                else:
+                    print(fmt(f"Sliding out <b>{branch}</b>"))
+                    slid_out_branches.append(branch)
 
         self._remove_branches_from_layout(slid_out_branches)
         if opt_delete:


Test patch:
diff --git a/tests/test_slide_out.py b/tests/test_slide_out.py
index ca99452..a47f8ff 100644
--- a/tests/test_slide_out.py
+++ b/tests/test_slide_out.py
@@ -1,3 +1,4 @@
+
 import pytest
 from pytest_mock import MockerFixture
 
@@ -435,6 +436,7 @@ class TestSlideOut(BaseTest):
         new_branch('has_downstream')
         commit()
         push()
+        delete_remote_branch('origin/has_downstream')
         new_branch('downstream')
         commit()
         check_out('main')
@@ -442,7 +444,11 @@ class TestSlideOut(BaseTest):
         commit()
         push()
         delete_remote_branch('origin/should_be_pruned')
-        delete_remote_branch('origin/has_downstream')
+        check_out('main')
+        new_branch('with_qualifier')
+        commit()
+        push()
+        delete_remote_branch('origin/with_qualifier')
         check_out('main')
 
         body: str = \
@@ -453,14 +459,24 @@ class TestSlideOut(BaseTest):
                 has_downstream
                     downstream
                 should_be_pruned PR #123
+                with_qualifier slide-out=no
             """
         rewrite_branch_layout_file(body)
 
         assert_success(
             ['slide-out', '--removed-from-remote', '--delete'],
-            "Sliding out should_be_pruned\nDeleting branch should_be_pruned...\n")
-
-        assert read_branch_layout_file() == "main\n    unpushed\n    not_deleted_remotely\n    has_downstream\n        downstream\n"
+            "Sliding out should_be_pruned\n"
+            "Skipping with_qualifier as it's marked as slide-out=no\n"
+            "Deleting branch should_be_pruned...\n")
+
+        assert read_branch_layout_file().splitlines() == [
+            "main",
+            "    unpushed",
+            "    not_deleted_remotely",
+            "    has_downstream",
+            "        downstream",
+            "    with_qualifier slide-out=no"
+        ]
 
         expected_status_output = (
             """
@@ -471,8 +487,10 @@ class TestSlideOut(BaseTest):
               o-not_deleted_remotely
               |
               o-has_downstream (untracked)
-                |
-                o-downstream (untracked)
+              | |
+              | o-downstream (untracked)
+              |
+              o-with_qualifier  slide-out=no (untracked)
             """
         )
         assert_success(['status'], expected_status_output)
@@ -487,7 +505,13 @@ class TestSlideOut(BaseTest):
         delete_remote_branch('origin/not_deleted_remotely')
         launch_command('slide-out', '--removed-from-remote', '--verbose')
 
-        assert read_branch_layout_file() == "main\n    unpushed\n    has_downstream\n        downstream\n"
+        assert read_branch_layout_file().splitlines() == [
+            "main",
+            "    unpushed",
+            "    has_downstream",
+            "        downstream",
+            "    with_qualifier slide-out=no"
+        ]
         branches = get_local_branches()
         assert 'not_deleted_remotely' in branches