
# Sapludināšana

Pitmaster veic zaru sapludināšanu, izmantojot trīsvirzienu sapludināšanu, tāpat kā `git merge`. Tā nosaka ātrās pārsūtīšanas iespējas, aprēķina sapludināšanas bāzes, veic koka un satura līmeņa sapludināšanu un konfliktu gadījumā izveido standarta konfliktu marķierus.

## Pamata sapludināšana

```php
$result = $repo->merge('feature/login');

if ($result->clean) {
    echo "Merged successfully: {$result->commitId->hex}\n";
} else {
    echo "Conflicts:\n";
    foreach ($result->conflictPaths as $path) {
        echo "  {$path}\n";
    }
}
```

## MergeResult

Klase `MergeResult` ir tikai lasāms vērtību objekts:

```php
use Pitmaster\Merge\MergeResult;

$result->clean;           // bool: true if merge completed without conflicts
$result->commitId;        // ?ObjectId: the merge commit (null if conflicts)
$result->conflictPaths;   // array: list of file paths with conflicts
$result->mergedContents;  // array: path => content with conflict markers (if conflicts)
```

Ja sapludināšana apstājas konfliktu dēļ, konflikta stāvoklis tiek ierakstīts indeksā un darba kokā. Atrisiniet konfliktus failos, pievienojiet `add()` un izsauciet `$repo->mergeContinue()` vai izsauciet `$repo->mergeAbort()`, lai atjaunotu stāvokli pirms sapludināšanas.

Pirms sapludināšanas apstipriniet lokālās izmaiņas vai noglabājiet tās: sapludināšanas rezultāts atjauno darba koku un pārraksta neapstiprinātās izmaiņas izsekotajos failos ([#2](https://github.com/inline0/pitmaster/issues/2)).

## Ātrās pārsūtīšanas sapludināšana

Ja pašreizējais HEAD ir mērķa zara priekštecis, Pitmaster veic ātrās pārsūtīšanas sapludināšanu: tas vienkārši pārvieto HEAD uz mērķa komitu, neveidojot sapludināšanas komitu.

```
Before:         After fast-forward:

A---B (main)    A---B---C---D (main)
     \
      C---D (feature)
```

```php
$result = $repo->merge('feature');
// $result->clean === true
// $result->commitId points to D
// No merge commit created
```

Pretējais gadījums vēl netiek noteikts: sapludinot zaru, kas jau ir iekļauts HEAD, tiek izveidots jauns sapludināšanas komits ar nemainītu koku, nevis ziņots “Already up to date” ([#6](https://github.com/inline0/pitmaster/issues/6)).

## Trīspusēja apvienošana

Ja zari ir atšķīrušies, Pitmaster veic trīsvirzienu sapludināšanu:

1. Atrod sapludināšanas bāzi (zemāko kopīgo priekšteci)
2. Salīdzina bāzi ar mūsu un viņu versiju kokiem
3. Katram failam, kas mainīts abos zaros, veic satura līmeņa sapludināšanu
4. Izveido sapludināšanas komitu ar diviem vecākiem

```
Before:              After merge:

      C---D (feature)         C---D
     /                       /     \
A---B---E---F (main)   A---B---E---F---G (main)
```

## Sapludināšanas bāze

Sapludināšanas bāze ir divu komitu jaunākais kopīgais priekštecis. Pitmaster to atrod, pārmeklējot komitu grafu. Ja ir vairākas sapludināšanas bāzes (krusteniska vēsture), `merge()` vispirms tās sapludina un izmanto rezultātu kā bāzi.

```php
$base = $repo->mergeBase(
    $repo->resolve('main'),
    $repo->resolve('feature/login'),
);

if ($base !== null) {
    echo "Common ancestor: {$base->hex}\n";
}
```

Lai piekļūtu algoritmam `MergeBase` tieši:

```php
use Pitmaster\Merge\MergeBase;

$finder = new MergeBase($repo->objectDatabase());
$base = $finder->find($commitA, $commitB);

// All merge bases (criss-cross histories can have more than one)
$bases = $finder->findAll($commitA, $commitB);

// Check ancestry
$isAncestor = $finder->isAncestor($oldCommit, $newCommit);
```

## Zaru sapludināšanas pārbaude

```php
if ($repo->isBranchMerged('feature/done')) {
    // All commits in feature/done are reachable from default branch
    $repo->deleteBranch('feature/done');
}

// Check against a specific target
if ($repo->isBranchMerged('feature/done', 'develop')) {
    // Merged into develop
}
```

## Konfliktu marķieri

Ja fails ir modificēts abos zaros un izmaiņas pārklājas, Pitmaster izveido standarta konfliktu marķierus. `merge()` marķē puses ar `HEAD` un sapludinātā zara nosaukumu:

```
<<<<<<< HEAD
    return $this->value + 1;
=======
    return $this->value * 2;
>>>>>>> feature
```

Klase `ConflictMarker` ietver divas versijas marķieros:

```php
use Pitmaster\Merge\ConflictMarker;

$marked = ConflictMarker::mark($oursContent, $theirsContent, 'HEAD', 'feature');

// diff3 style, with the base section
$marked = ConflictMarker::mark($oursContent, $theirsContent, 'HEAD', 'feature', $baseContent, 'base');
```

## Satura līmeņa trīsvirzienu sapludināšana

Klase `ThreeWayMerge` sapludina blob saturu (nevis failus):

```php
use Pitmaster\Merge\ThreeWayMerge;

$result = ThreeWayMerge::merge($baseContent, $oursContent, $theirsContent, 'HEAD', 'feature');

$result['content'];   // merged text, with conflict markers if needed
$result['clean'];     // true when nothing conflicted
$result['conflicts']; // number of conflict regions
```

Tā pieņem trīs virknes (bāzes versiju, mūsu versiju un viņu versiju), kā arī izvēles etiķetes un konflikta stilu (pēc noklusējuma `'merge'` vai `'diff3'`, lai iekļautu bāzes sadaļu).

## Sapludināšanas stratēģijas

### Rekursīvā sapludināšana

Noklusējuma stratēģija (`$repo->merge($branch)`) apstrādā krusteniskas sapludināšanas vēstures ar vairākām sapludināšanas bāzēm. CLI pieņem arī `-s ort` un `-s recursive`.

### Mūsu puses sapludināšana

Izveido sapludināšanas komitu, kas saglabā nemainītu HEAD koku. Noderīgi, lai uzturētu zara vēsturi, neiekļaujot tajā izmaiņas.

```php
$result = $repo->merge('feature/old', 'ours');
```

### Astoņkāju sapludināšana

Sapludina divus vai vairākus zarus vienā sapludināšanas komitā. Ja kādā zarā ir konflikts, tiek atgriezts nekorekts rezultāts, neierakstot sapludināšanas stāvokli un neveidojot komitu.

```php
$result = $repo->mergeOctopus(['feature/a', 'feature/b', 'feature/c']);
```

Klases `RecursiveMerge`, `OursMerge` un `OctopusMerge`, kas atrodas `Pitmaster\Merge`, ir satura līmeņa palīgrīki; `Repository` pašas īsteno iepriekš minētās stratēģijas.

## Rerere (ierakstīto atrisinājumu atkārtota izmantošana)

Pitmaster ietver atsevišķu klasi `Rerere`, kas glabā atrisinājumus git `rr-cache` izkārtojumā:

```php
use Pitmaster\Merge\Rerere;

$rerere = new Rerere($repo->gitDir());

if ($rerere->isEnabled()) {                     // rerere.enabled = true in .git/config
    $rerere->record($conflicted, $resolved);    // remember a resolution
    $resolved = $rerere->resolve($conflicted);  // replay it, or null
}
```

`merge()` to neizsauc: atrisinājumi tiek ierakstīti un atkārtoti izmantoti tikai tad, ja jūsu kods to dara. `isEnabled()` meklē burtisko tekstu `rerere.enabled = true` failā `.git/config` un neatpazīst sadaļu `[rerere]`, ko raksta `git config rerere.enabled true` ([#20](https://github.com/inline0/pitmaster/issues/20)).

## Sapludināšanas plūsma koka līmenī

Pilns sapludināšanas process:

1. `MergeBase::findAll()` atrod kopīgos priekštečus
2. Bāzes, mūsu un viņu koki tiek salīdzināti pa ceļiem
3. Failiem, kas mainīti tikai vienā zarā, tiek pārņemtas šīs izmaiņas
4. Failiem, kas mainīti abos zaros:
   - Ja abas puses mainījušas vienādi, tiek pārņemtas šīs izmaiņas
   - Ja izmaiņas atšķiras, saturam tiek veikta sapludināšana, izmantojot `ThreeWayMerge::merge()`
5. Ja visas sapludināšanas norit bez konfliktiem, tiek izveidots sapludinātais koks un sapludināšanas komits
6. Ja ir konflikti, tiek atgriezts `MergeResult` ar `clean = false` un konfliktu ceļiem

## CLI lietojums

```bash
./vendor/bin/pitmaster merge feature/login
```

Izvade veiksmīgas izpildes gadījumā:
```
Merge successful.
```

Izvade konflikta gadījumā:
```
CONFLICT in: src/File.php, src/Other.php
```
