diff --git a/config/set/code-quality/code-quality.yaml b/config/set/code-quality/code-quality.yaml
index 6965e49270a3..6f5f45747b6b 100644
--- a/config/set/code-quality/code-quality.yaml
+++ b/config/set/code-quality/code-quality.yaml
@@ -25,6 +25,7 @@ services:
Rector\CodeQuality\Rector\If_\ConsecutiveNullCompareReturnsToNullCoalesceQueueRector: null
Rector\CodeQuality\Rector\If_\SimplifyIfIssetToNullCoalescingRector: null
Rector\CodeQuality\Rector\If_\ExplicitBoolCompareRector: null
+ Rector\CodeQuality\Rector\If_\CombineIfRector: null
Rector\CodeQuality\Rector\Equal\UseIdenticalOverEqualWithSameTypeRector: null
Rector\CodeQuality\Rector\Ternary\SimplifyDuplicatedTernaryRector: null
Rector\CodeQuality\Rector\Identical\SimplifyBoolIdenticalTrueRector: null
diff --git a/docs/AllRectorsOverview.md b/docs/AllRectorsOverview.md
index 294121d32659..2a8268a0b667 100644
--- a/docs/AllRectorsOverview.md
+++ b/docs/AllRectorsOverview.md
@@ -1,4 +1,4 @@
-# All 429 Rectors Overview
+# All 430 Rectors Overview
- [Projects](#projects)
- [General](#general)
@@ -514,6 +514,29 @@ Change array_push() to direct variable assign
+### `CombineIfRector`
+
+- class: `Rector\CodeQuality\Rector\If_\CombineIfRector`
+
+Merges nested if statements
+
+```diff
+ class SomeClass {
+ public function run()
+ {
+- if ($cond1) {
+- if ($cond2) {
+- return 'foo';
+- }
++ if ($cond1 && $cond2) {
++ return 'foo';
+ }
+ }
+ }
+```
+
+
+
### `CombinedAssignRector`
- class: `Rector\CodeQuality\Rector\Assign\CombinedAssignRector`
diff --git a/packages/CodeQuality/src/Rector/If_/CombineIfRector.php b/packages/CodeQuality/src/Rector/If_/CombineIfRector.php
new file mode 100644
index 000000000000..2577d6b2b299
--- /dev/null
+++ b/packages/CodeQuality/src/Rector/If_/CombineIfRector.php
@@ -0,0 +1,102 @@
+shouldSkip($node)) {
+ return null;
+ }
+
+ /** @var Node\Stmt\If_ $subIf */
+ $subIf = $node->stmts[0];
+ $node->cond = new BooleanAnd($node->cond, $subIf->cond);
+ $node->stmts = $subIf->stmts;
+ return $node;
+ }
+
+ private function shouldSkip(If_ $node): bool
+ {
+ if ($node->else !== null) {
+ return true;
+ }
+
+ if (count($node->stmts) !== 1) {
+ return true;
+ }
+
+ if ($node->elseifs) {
+ return true;
+ }
+
+ if (! $node->stmts[0] instanceof If_) {
+ return true;
+ }
+
+ if ($node->stmts[0]->else !== null) {
+ return true;
+ }
+
+ if ($node->stmts[0]->elseifs) {
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/packages/CodeQuality/tests/Rector/If_/CombineIfRector/CombineIfRectorTest.php b/packages/CodeQuality/tests/Rector/If_/CombineIfRector/CombineIfRectorTest.php
new file mode 100644
index 000000000000..153c11dd5c0f
--- /dev/null
+++ b/packages/CodeQuality/tests/Rector/If_/CombineIfRector/CombineIfRectorTest.php
@@ -0,0 +1,30 @@
+doTestFile($file);
+ }
+
+ public function provideDataForTest(): Iterator
+ {
+ return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
+ }
+
+ protected function getRectorClass(): string
+ {
+ return CombineIfRector::class;
+ }
+}
diff --git a/packages/CodeQuality/tests/Rector/If_/CombineIfRector/Fixture/child_else.php.inc b/packages/CodeQuality/tests/Rector/If_/CombineIfRector/Fixture/child_else.php.inc
new file mode 100644
index 000000000000..a8bb998e3e13
--- /dev/null
+++ b/packages/CodeQuality/tests/Rector/If_/CombineIfRector/Fixture/child_else.php.inc
@@ -0,0 +1,16 @@
+
+-----
+
diff --git a/packages/CodeQuality/tests/Rector/If_/CombineIfRector/Fixture/more_statements.php.inc b/packages/CodeQuality/tests/Rector/If_/CombineIfRector/Fixture/more_statements.php.inc
new file mode 100644
index 000000000000..459a82d7101a
--- /dev/null
+++ b/packages/CodeQuality/tests/Rector/If_/CombineIfRector/Fixture/more_statements.php.inc
@@ -0,0 +1,17 @@
+
diff --git a/packages/CodeQuality/tests/Rector/If_/CombineIfRector/Fixture/parent_else.php.inc b/packages/CodeQuality/tests/Rector/If_/CombineIfRector/Fixture/parent_else.php.inc
new file mode 100644
index 000000000000..7606bf6fe425
--- /dev/null
+++ b/packages/CodeQuality/tests/Rector/If_/CombineIfRector/Fixture/parent_else.php.inc
@@ -0,0 +1,16 @@
+