Liigu sisu juurde

Ühendamine

Pitmaster ühendab harusid kolmesuunalise ühendamise abil nagu git merge. See tuvastab kiiredasiedastuse võimalused, arvutab ühendamise baasid, ühendab puu- ja sisutasemel ning lisab failikonfliktide korral standardsed konfliktimarkerid.

Ühendamise alused

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

Klass MergeResult on kirjutuskaitstud väärtusobjekt:

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)

Kui ühendamine peatub konfliktide tõttu, kirjutatakse konfliktiolek indeksisse ja tööpuusse. Lahendage failid, lisage need add() abil ning kutsuge välja $repo->mergeContinue() või taastage ühendamiseelne olek käsuga $repo->mergeAbort().

Enne ühendamist kinnitage või pange kohalikud muudatused kõrvale: ühendamine koostab tööpuu tulemusest uuesti ja kirjutab jälgitavates failides kinnitamata muudatused üle (#2).

Kiiredasiedastusega ühendamised

Kui praegune HEAD on sihtharu eelkäija, teeb Pitmaster kiiredasiedastusega ühendamise: see liigutab HEAD-i lihtsalt sihtsissekandele, ilma ühendamississekannet loomata.

Kood
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

Tagurpidi juhu tuvastamine pole veel teostatud: juba HEAD-is sisalduva haru ühendamisel luuakse muutumatu puuga uus ühendamississekanne, selle asemel et teatada "Already up to date" (#6).

Kolmeosaline ühendamine

Kui harud on lahknenud, teeb Pitmaster kolmesuunalise ühendamise:

  1. Leia ühendamise baas (madalaim ühine eellane)
  2. Võrdle puutasemel baasi meie ja baasi nende puuga
  3. Tee mõlemas harus muudetud failide puhul sisutasemel ühendamine
  4. Loo kahe vanemaga ühendamississekanne
Kood
Before:              After merge:

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

Ühendamise baas

Ühendamise baas on kahe sissekande kõige hilisem ühine eellane. Pitmaster leiab selle sissekannete graafi läbides. Kui ühendamise baase on mitu (ristuv ajalugu), ühendab merge() need esmalt ja kasutab tulemust baasina.

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

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

Otse juurdepääsuks algoritmile MergeBase:

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);

Haru ühendamise kontroll

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
}

Konfliktimarkerid

Kui faili on muudetud mõlemas harus ja muudatused kattuvad, lisab Pitmaster standardsed konfliktimarkerid. merge() märgib pooled kui HEAD ja ühendatud haru nime:

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

Klass ConflictMarker ümbritseb kahte versiooni markeritega:

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');

Kolmesuunaline ühendamine sisutasemel

Klass ThreeWayMerge ühendab bloobide sisu (mitte faile):

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

See võtab kolm stringi (baasversiooni, meie versiooni ja nende versiooni), valikulised sildid ning konfliktistiili (vaikimisi 'merge' või 'diff3', mis lisab ka baasiosa).

Ühendamisstrateegiad

Rekursiivne ühendamine

Vaikestrateegia ($repo->merge($branch)) käsitleb ristuvate ühendamiste ajalugu mitme ühendamisbaasiga. CLI aktsepteerib selle jaoks ka väärtusi -s ort ja -s recursive.

Meie poole ühendamine

Salvestab ühendamississekande, jättes HEAD-i puu muutmata. Kasulik haruajaloo säilitamiseks ilma muudatusi kaasamata.

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

Kaheksajalgühendamine

Ühendab kaks või enam haru üheks ühendamississekandeks. Kui mõnes harus tekib konflikt, tagastab see mittepuhas tulemuse, kirjutamata ühendamisolekut ega loomata sissekannet.

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

Klassid RecursiveMerge, OursMerge ja OctopusMerge moodulis Pitmaster\Merge on sisutaseme abivahendid; Repository rakendab ülaltoodud strateegiad ise.

Rerere (salvestatud lahenduse taaskasutamine)

Pitmaster sisaldab iseseisvat klassi Rerere, mis salvestab lahendused git-i kataloogistruktuuri rr-cache järgi:

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() ei kutsu seda välja: lahendused salvestatakse ja taasesitatakse ainult siis, kui teie kood seda teeb. isEnabled() otsib stringi rerere.enabled = true failist .git/config ega tunne ära sektsiooni [rerere], mille kirjutab git config rerere.enabled true (#20).

Puutasemel ühendamise voog

Ühendamise täielik protsess:

  1. MergeBase::findAll() leiab ühised eellased
  2. Võrdleb baasi, meie ja nende puid tee kaupa
  3. Kui faili muudeti ainult ühes harus, võtab selle muudatuse üle
  4. Kui faili muudeti mõlemas harus:
    • Kui mõlemad muudeti ühtemoodi, võtab ükskõik kumma muudatuse (need kattuvad)
    • Kui muudatused erinevad, käivitab sisul ThreeWayMerge::merge()
  5. Kui kõik ühendamised õnnestuvad, koostab ühendatud puu ja loob ühendamississekande
  6. Kui tekib konflikt, tagastab MergeResult koos väärtusega clean = false ja konfliktsete radadega

CLI kasutamine

Shell
./vendor/bin/pitmaster merge feature/login

Eduka toimingu väljund:

Kood
Merge successful.

Väljund konflikti korral:

Kood
CONFLICT in: src/File.php, src/Other.php