Repository: git-town/git-town

Issue:
sync: does not honor --no-push flag anymore
### Steps to reproduce

Scenario `features/sync/current_branch/feature_branch/rebase_sync_strategy/no_push/top_level_feature_branch.feature` now contains a force-push.

### Command output

```shell
Then Git Town runs the commands
      | BRANCH  | COMMAND                                              |
      | feature | git fetch --prune --tags                             |
      |         | git checkout main                                    |
      | main    | git -c rebase.updateRefs=false rebase origin/main    |
      |         | git checkout feature                                 |
      | feature | git -c rebase.updateRefs=false rebase main           |
      |         | git -c rebase.updateRefs=false rebase origin/feature |
      |         | git push --force-with-lease --force-if-includes      |
```

### Additional information

_No response_

Discussion:
@kevgo: This is now available as part of [Git Town 20.2](https://github.com/git-town/git-town/releases/tag/v20.2.0).

Solution patch:
diff --git a/features/sync/current_branch/feature_branch/compress_sync_strategy/no_push/enabled.feature b/features/sync/current_branch/feature_branch/compress_sync_strategy/no_push/enabled.feature
index 75c5f712a..18ff0557e 100644
--- a/features/sync/current_branch/feature_branch/compress_sync_strategy/no_push/enabled.feature
+++ b/features/sync/current_branch/feature_branch/compress_sync_strategy/no_push/enabled.feature
@@ -28,22 +28,20 @@ Feature: sync the current feature branch using the "compress" strategy in no-pus
       |         | git merge --no-edit --ff origin/feature           |
       |         | git reset --soft main                             |
       |         | git commit -m "local feature commit 1"            |
-      |         | git push --force-with-lease                       |
     And these commits exist now
       | BRANCH  | LOCATION      | MESSAGE                |
       | main    | local, origin | origin main commit     |
       |         | local         | local main commit      |
-      | feature | local, origin | local feature commit 1 |
-      |         | origin        | local main commit      |
+      | feature | local         | local feature commit 1 |
+      |         | origin        | origin feature commit  |
 
   Scenario: undo
     When I run "git-town undo"
     Then Git Town runs the commands
-      | BRANCH  | COMMAND                                                                                |
-      | feature | git reset --hard {{ sha-before-run 'local feature commit 2' }}                         |
-      |         | git push --force-with-lease origin {{ sha-in-origin 'origin feature commit' }}:feature |
-      |         | git checkout main                                                                      |
-      | main    | git reset --hard {{ sha 'local main commit' }}                                         |
-      |         | git checkout feature                                                                   |
+      | BRANCH  | COMMAND                                                        |
+      | feature | git reset --hard {{ sha-before-run 'local feature commit 2' }} |
+      |         | git checkout main                                              |
+      | main    | git reset --hard {{ sha 'local main commit' }}                 |
+      |         | git checkout feature                                           |
     And the initial commits exist now
     And the initial branches and lineage exist now
diff --git a/features/sync/current_branch/feature_branch/rebase_sync_strategy/no_push/detached.feature b/features/sync/current_branch/feature_branch/rebase_sync_strategy/no_push/detached.feature
index 9dd8b69d7..20aa6f50c 100644
--- a/features/sync/current_branch/feature_branch/rebase_sync_strategy/no_push/detached.feature
+++ b/features/sync/current_branch/feature_branch/rebase_sync_strategy/no_push/detached.feature
@@ -24,31 +24,28 @@ Feature: detached syncing a stacked feature branch using --no-push
       | beta   | git fetch --prune --tags                           |
       |        | git checkout alpha                                 |
       | alpha  | git -c rebase.updateRefs=false rebase origin/alpha |
-      |        | git push --force-with-lease --force-if-includes    |
       |        | git checkout beta                                  |
       | beta   | git -c rebase.updateRefs=false rebase alpha        |
       |        | git -c rebase.updateRefs=false rebase origin/beta  |
       |        | git -c rebase.updateRefs=false rebase alpha        |
-      |        | git push --force-with-lease --force-if-includes    |
     And these commits exist now
       | BRANCH | LOCATION      | MESSAGE             |
       | main   | local         | local main commit   |
       |        | origin        | origin main commit  |
       | alpha  | local, origin | origin alpha commit |
-      |        |               | local alpha commit  |
-      | beta   | local, origin | origin beta commit  |
+      |        | local         | local alpha commit  |
+      | beta   | local         | origin beta commit  |
       |        |               | local beta commit   |
+      |        | origin        | origin beta commit  |
     And the initial branches and lineage exist now
 
   Scenario: undo
     When I run "git-town undo"
     Then Git Town runs the commands
-      | BRANCH | COMMAND                                                                                       |
-      | beta   | git checkout alpha                                                                            |
-      | alpha  | git reset --hard {{ sha 'local alpha commit' }}                                               |
-      |        | git push --force-with-lease origin {{ sha-in-origin-before-run 'origin alpha commit' }}:alpha |
-      |        | git checkout beta                                                                             |
-      | beta   | git reset --hard {{ sha 'local beta commit' }}                                                |
-      |        | git push --force-with-lease origin {{ sha-in-origin-before-run 'origin beta commit' }}:beta   |
+      | BRANCH | COMMAND                                         |
+      | beta   | git checkout alpha                              |
+      | alpha  | git reset --hard {{ sha 'local alpha commit' }} |
+      |        | git checkout beta                               |
+      | beta   | git reset --hard {{ sha 'local beta commit' }}  |
     And the initial commits exist now
     And the initial branches and lineage exist now
diff --git a/features/sync/current_branch/feature_branch/rebase_sync_strategy/no_push/stacked_feature_branch.feature b/features/sync/current_branch/feature_branch/rebase_sync_strategy/no_push/stacked_feature_branch.feature
index 68cbb8904..d3f524415 100644
--- a/features/sync/current_branch/feature_branch/rebase_sync_strategy/no_push/stacked_feature_branch.feature
+++ b/features/sync/current_branch/feature_branch/rebase_sync_strategy/no_push/stacked_feature_branch.feature
@@ -28,34 +28,31 @@ Feature: syncing a stacked feature branch using --no-push
       | parent | git -c rebase.updateRefs=false rebase main          |
       |        | git -c rebase.updateRefs=false rebase origin/parent |
       |        | git -c rebase.updateRefs=false rebase main          |
-      |        | git push --force-with-lease --force-if-includes     |
       |        | git checkout child                                  |
       | child  | git -c rebase.updateRefs=false rebase parent        |
       |        | git -c rebase.updateRefs=false rebase origin/child  |
       |        | git -c rebase.updateRefs=false rebase parent        |
-      |        | git push --force-with-lease --force-if-includes     |
     And these commits exist now
       | BRANCH | LOCATION      | MESSAGE              |
       | main   | local, origin | origin main commit   |
       |        | local         | local main commit    |
-      | child  | local, origin | origin child commit  |
+      | child  | local         | origin child commit  |
       |        |               | local child commit   |
-      | parent | local, origin | origin parent commit |
+      |        | origin        | origin child commit  |
+      | parent | local         | origin parent commit |
       |        |               | local parent commit  |
-      |        | origin        | local main commit    |
+      |        | origin        | origin parent commit |
     And the initial branches and lineage exist now
 
   Scenario: undo
     When I run "git-town undo"
     Then Git Town runs the commands
-      | BRANCH | COMMAND                                                                                         |
-      | child  | git reset --hard {{ sha 'local child commit' }}                                                 |
-      |        | git push --force-with-lease origin {{ sha-in-origin-before-run 'origin child commit' }}:child   |
-      |        | git checkout parent                                                                             |
-      | parent | git reset --hard {{ sha 'local parent commit' }}                                                |
-      |        | git push --force-with-lease origin {{ sha-in-origin-before-run 'origin parent commit' }}:parent |
-      |        | git checkout main                                                                               |
-      | main   | git reset --hard {{ sha 'local main commit' }}                                                  |
-      |        | git checkout child                                                                              |
+      | BRANCH | COMMAND                                          |
+      | child  | git reset --hard {{ sha 'local child commit' }}  |
+      |        | git checkout main                                |
+      | main   | git reset --hard {{ sha 'local main commit' }}   |
+      |        | git checkout parent                              |
+      | parent | git reset --hard {{ sha 'local parent commit' }} |
+      |        | git checkout child                               |
     And the initial commits exist now
     And the initial branches and lineage exist now
diff --git a/features/sync/current_branch/feature_branch/rebase_sync_strategy/no_push/top_level_feature_branch.feature b/features/sync/current_branch/feature_branch/rebase_sync_strategy/no_push/top_level_feature_branch.feature
index 1a6f8c552..3a8b22913 100644
--- a/features/sync/current_branch/feature_branch/rebase_sync_strategy/no_push/top_level_feature_branch.feature
+++ b/features/sync/current_branch/feature_branch/rebase_sync_strategy/no_push/top_level_feature_branch.feature
@@ -27,24 +27,23 @@ Feature: syncing a top-level feature branch using --no-push
       | feature | git -c rebase.updateRefs=false rebase main           |
       |         | git -c rebase.updateRefs=false rebase origin/feature |
       |         | git -c rebase.updateRefs=false rebase main           |
-      |         | git push --force-with-lease --force-if-includes      |
     And these commits exist now
       | BRANCH  | LOCATION      | MESSAGE               |
       | main    | local, origin | origin main commit    |
       |         | local         | local main commit     |
-      | feature | local, origin | origin feature commit |
+      | feature | local         | origin feature commit |
       |         |               | local feature commit  |
       |         | origin        | local main commit     |
+      |         |               | origin feature commit |
     And the initial branches and lineage exist now
 
   Scenario: undo
     When I run "git-town undo"
     Then Git Town runs the commands
-      | BRANCH  | COMMAND                                                                                           |
-      | feature | git reset --hard {{ sha 'local feature commit' }}                                                 |
-      |         | git push --force-with-lease origin {{ sha-in-origin-before-run 'origin feature commit' }}:feature |
-      |         | git checkout main                                                                                 |
-      | main    | git reset --hard {{ sha 'local main commit' }}                                                    |
-      |         | git checkout feature                                                                              |
+      | BRANCH  | COMMAND                                           |
+      | feature | git reset --hard {{ sha 'local feature commit' }} |
+      |         | git checkout main                                 |
+      | main    | git reset --hard {{ sha 'local main commit' }}    |
+      |         | git checkout feature                              |
     And the initial commits exist now
     And the initial branches and lineage exist now
diff --git a/internal/cmd/sync/sync_feature_branch.go b/internal/cmd/sync/sync_feature_branch.go
index d1791b46c..4936df169 100644
--- a/internal/cmd/sync/sync_feature_branch.go
+++ b/internal/cmd/sync/sync_feature_branch.go
@@ -19,6 +19,7 @@ func FeatureBranchProgram(syncStrategy configdomain.SyncStrategy, args featureBr
 				Offline:           args.offline,
 				InitialParentName: args.initialParentName,
 				InitialParentSHA:  args.initialParentSHA,
+				PushBranches:      args.pushBranches,
 				TrackingBranch:    args.trackingBranch,
 			},
 		)
diff --git a/internal/vm/opcodes/sync_feature_branch_compress.go b/internal/vm/opcodes/sync_feature_branch_compress.go
index abaab93f7..bf5119445 100644
--- a/internal/vm/opcodes/sync_feature_branch_compress.go
+++ b/internal/vm/opcodes/sync_feature_branch_compress.go
@@ -14,6 +14,7 @@ type SyncFeatureBranchCompress struct {
 	InitialParentName       Option[gitdomain.LocalBranchName]
 	InitialParentSHA        Option[gitdomain.SHA]
 	Offline                 configdomain.Offline
+	PushBranches            configdomain.PushBranches
 	TrackingBranch          Option[gitdomain.RemoteBranchName]
 	undeclaredOpcodeMethods `exhaustruct:"optional"`
 }
@@ -68,7 +69,7 @@ func (self *SyncFeatureBranchCompress) Run(args shared.RunArgs) error {
 				Message:        commitMessage,
 			},
 		)
-		if self.Offline.IsOnline() && self.TrackingBranch.IsSome() {
+		if self.Offline.IsOnline() && self.TrackingBranch.IsSome() && self.PushBranches.IsTrue() {
 			opcodes = append(opcodes, &PushCurrentBranchForceIfNeeded{CurrentBranch: self.CurrentBranch, ForceIfIncludes: false})
 		}
 	}
diff --git a/internal/vm/opcodes/sync_feature_branch_rebase.go b/internal/vm/opcodes/sync_feature_branch_rebase.go
index a3451d2b1..a2f8d706c 100644
--- a/internal/vm/opcodes/sync_feature_branch_rebase.go
+++ b/internal/vm/opcodes/sync_feature_branch_rebase.go
@@ -41,11 +41,15 @@ func (self *SyncFeatureBranchRebase) Run(args shared.RunArgs) error {
 						Branch:      self.Branch,
 						PreviousSHA: self.ParentLastRunSHA,
 					},
-					&PushCurrentBranchForceIfNeeded{
-						CurrentBranch:   self.Branch,
-						ForceIfIncludes: true,
-					},
 				)
+				if self.PushBranches {
+					program = append(program,
+						&PushCurrentBranchForceIfNeeded{
+							CurrentBranch:   self.Branch,
+							ForceIfIncludes: true,
+						},
+					)
+				}
 			}
 		}
 	}



Test patch:
diff --git a/internal/vm/statefile/save_load_test.go b/internal/vm/statefile/save_load_test.go
index 9e9b8d8dd..9bc8b73ad 100644
--- a/internal/vm/statefile/save_load_test.go
+++ b/internal/vm/statefile/save_load_test.go
@@ -130,7 +130,7 @@ func TestLoadSave(t *testing.T) {
 				&opcodes.StashPopIfExists{},
 				&opcodes.StashPopIfNeeded{InitialStashSize: 2},
 				&opcodes.StashOpenChanges{},
-				&opcodes.SyncFeatureBranchCompress{CommitMessage: Some(gitdomain.CommitMessage("commit message")), CurrentBranch: "branch", Offline: true, InitialParentName: gitdomain.NewLocalBranchNameOption("parent"), InitialParentSHA: Some(gitdomain.NewSHA("111111")), TrackingBranch: Some(gitdomain.NewRemoteBranchName("origin/branch"))},
+				&opcodes.SyncFeatureBranchCompress{CommitMessage: Some(gitdomain.CommitMessage("commit message")), CurrentBranch: "branch", Offline: true, InitialParentName: gitdomain.NewLocalBranchNameOption("parent"), InitialParentSHA: Some(gitdomain.NewSHA("111111")), TrackingBranch: Some(gitdomain.NewRemoteBranchName("origin/branch")), PushBranches: true},
 				&opcodes.SyncFeatureBranchMerge{Branch: "branch", InitialParentName: gitdomain.NewLocalBranchNameOption("original-parent"), InitialParentSHA: Some(gitdomain.NewSHA("123456")), TrackingBranch: Some(gitdomain.NewRemoteBranchName("origin/branch"))},
 				&opcodes.SyncFeatureBranchRebase{Branch: "branch", ParentLastRunSHA: Some(gitdomain.NewSHA("111111")), PushBranches: true, TrackingBranch: Some(gitdomain.NewRemoteBranchName("origin/branch"))},
 			},
@@ -737,6 +737,7 @@ func TestLoadSave(t *testing.T) {
         "InitialParentName": "parent",
         "InitialParentSHA": "111111",
         "Offline": true,
+        "PushBranches": true,
         "TrackingBranch": "origin/branch"
       },
       "type": "SyncFeatureBranchCompress"