Sujungimas
Pitmaster sujungia šakas trijų krypčių metodu, kaip git merge. Aptinka greitojo perslinkimo galimybes, apskaičiuoja sujungimo bazes, sujungia medžius ir turinį bei failams konfliktuojant įterpia standartinius konfliktų žymeklius.
Pagrindinis sujungimas
$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
MergeResult klasė yra tik skaitomas reikšmės objektas:
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)
Kai sujungimas sustoja dėl konfliktų, konfliktų būsena įrašoma į indeksą ir darbinį medį. Išspręskite konfliktus failuose, juos add() ir iškvieskite $repo->mergeContinue() arba iškvieskite $repo->mergeAbort(), kad atkurtumėte būseną prieš sujungimą.
Prieš sujungdami patvirtinkite arba padėkite į saugyklą vietinius pakeitimus: sujungimas iš naujo sukuria darbinį medį pagal rezultatą ir perrašo nepatvirtintus sekamų failų pakeitimus (#2).
Greitojo perslinkimo sujungimai
Kai dabartinis HEAD yra tikslinės šakos protėvis, Pitmaster atlieka greitojo perslinkimo sujungimą: tiesiog perkelia HEAD į tikslinį įrašą, nesukurdama sujungimo įrašo.
Before: After fast-forward:
A---B (main) A---B---C---D (main)
\
C---D (feature)
$result = $repo->merge('feature');
// $result->clean === true
// $result->commitId points to D
// No merge commit created
Atvirkštinis atvejis dar neaptinkamas: sujungus šaką, kurią HEAD jau apima, sukuriamas naujas sujungimo įrašas su nepakitusiu medžiu, užuot pranešus „Already up to date“ (#6).
Trijų krypčių sujungimas
Kai šakų istorijos išsiskiria, Pitmaster atlieka trijų krypčių sujungimą:
- Rasti sujungimo bazę (artimiausią bendrą protėvį)
- Palyginti bazę su mūsų ir su jų šakomis medžių lygmeniu
- Kiekvienam failui, pakeistam abiejose šakose, atlikti turinio lygmens sujungimą
- Sukurti sujungimo įrašą su dviem tėviniais įrašais
Before: After merge:
C---D (feature) C---D
/ / \
A---B---E---F (main) A---B---E---F---G (main)
Sujungimo bazė
Sujungimo bazė yra naujausias bendras dviejų įrašų protėvis. Pitmaster ją randa eidama įrašų grafu. Jei sujungimo bazių yra kelios (kryžminė istorija), merge() pirmiausia jas sujungia, o rezultatą naudoja kaip bazę.
$base = $repo->mergeBase(
$repo->resolve('main'),
$repo->resolve('feature/login'),
);
if ($base !== null) {
echo "Common ancestor: {$base->hex}\n";
}
Tiesioginei prieigai prie MergeBase algoritmo:
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);
Šakų sujungimo tikrinimas
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
}
Konfliktų žymekliai
Kai failas pakeičiamas abiejose šakose ir pakeitimai persidengia, Pitmaster įterpia standartinius konfliktų žymeklius. merge() pažymi puses HEAD ir sujungtos šakos pavadinimu:
<<<<<<< HEAD
return $this->value + 1;
=======
return $this->value * 2;
>>>>>>> feature
ConflictMarker klasė apgaubia dvi versijas žymekliais:
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');
Trijų krypčių sujungimas turinio lygmeniu
ThreeWayMerge klasė sujungia blob turinį (ne failus):
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
Ji priima tris eilutes (bazinę versiją, mūsų versiją ir jų versiją), pasirinktines etiketes ir konflikto stilių (pagal numatytuosius nustatymus 'merge', o 'diff3' įtraukia bazinę skiltį).
Sujungimo strategijos
Rekursinis sujungimas
Numatytoji strategija ($repo->merge($branch)) apdoroja kryžmines sujungimų istorijas su keliomis sujungimo bazėmis. Jai CLI taip pat priima -s ort ir -s recursive.
Mūsų pusės sujungimas
Sukuria sujungimo įrašą, paliekantį HEAD medį nepakeistą. Naudinga šakų istorijai palaikyti neįtraukiant pakeitimų.
$result = $repo->merge('feature/old', 'ours');
Aštuonkojo sujungimas
Sujungia dvi ar daugiau šakų į vieną sujungimo įrašą. Jei kurioje nors šakoje kyla konfliktų, grąžinamas nešvarus rezultatas, neįrašant sujungimo būsenos ir nesukuriant įrašo.
$result = $repo->mergeOctopus(['feature/a', 'feature/b', 'feature/c']);
Pitmaster\Merge esančios RecursiveMerge, OursMerge ir OctopusMerge klasės yra turinio lygmens pagalbinės priemonės; Repository pačios įgyvendina pirmiau nurodytas strategijas.
Rerere (pakartotinis įrašyto sprendimo panaudojimas)
Pitmaster turi atskirą Rerere klasę, kuri saugo sprendimus git rr-cache išdėstymu:
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() jos neiškviečia: sprendimai įrašomi ir pakartojami tik tada, kai taip nurodo jūsų kodas. isEnabled() ieško pažodinio teksto rerere.enabled = true faile .git/config ir neatpažįsta [rerere] skilties, kurią įrašo git config rerere.enabled true (#20).
Sujungimo eiga medžių lygmeniu
Visas sujungimo procesas:
MergeBase::findAll()nustato bendrus protėvius- Pagrindinis, mūsų ir jų medžiai lyginami pagal kiekvieną kelią
- Failams, pakeistiems tik vienoje šakoje: pritaikomas tas pakeitimas
- Failams, pakeistiems abiejose šakose:
- Jei pakeista vienodai: pritaikomas bet kuris variantas (jie sutampa)
- Jei pakeitimai skiriasi: turiniui paleidžiamas
ThreeWayMerge::merge()
- Jei visi sujungimai švarūs: sukuriamas sujungtas medis ir sujungimo įrašas
- Jei yra konfliktų: grąžinamas
MergeResultsuclean = falseir konfliktuojančiais keliais
CLI naudojimas
./vendor/bin/pitmaster merge feature/login
Išvestis sėkmės atveju:
Merge successful.
Konflikto atveju pateikiama:
CONFLICT in: src/File.php, src/Other.php