Združevanje
Pitmaster združuje veje s trosmernim združevanjem, tako kot git merge. Zazna možnosti hitrega pomika naprej, izračuna osnovne različice združitve, izvede združevanje na ravni dreves in vsebine ter ob sporih v datotekah ustvari standardne oznake sporov.
Osnovno združevanje
$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
Razred MergeResult je objekt vrednosti samo za branje:
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)
Ko se združevanje ustavi zaradi sporov, se stanje spora zapiše v indeks in delovno drevo. Razrešite spore v datotekah, jih dodajte v pripravo z add() in pokličite $repo->mergeContinue() ali pa pokličite $repo->mergeAbort(), da obnovite stanje pred združevanjem.
Pred združevanjem potrdite lokalne spremembe ali jih shranite na stran: združevanje znova sestavi delovno drevo na podlagi rezultata in prepiše nepotrjene spremembe v datotekah pod nadzorom različic (#2).
Združevanja s hitrim pomikom naprej
Če je trenutni HEAD prednik ciljne veje, Pitmaster izvede združevanje s hitrim pomikom naprej: HEAD preprosto premakne na ciljno potrditev, ne da bi ustvaril potrditev združitve.
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
Obratni primer še ni zaznan: združevanje veje, ki jo HEAD že vsebuje, ustvari novo potrditev združitve z nespremenjenim drevesom, namesto da bi sporočilo »Že posodobljeno« (#6).
Tristranska združitev
Ko se veje razidejo, Pitmaster izvede trosmerno združevanje:
- Poišče osnovno različico združitve (najnižjega skupnega prednika)
- Na ravni dreves primerja osnovo z našo in njihovo različico
- Za vsako datoteko, spremenjeno v obeh vejah, izvede združevanje na ravni vsebine
- Ustvari potrditev združitve z dvema nadrejenima potrditvama
Before: After merge:
C---D (feature) C---D
/ / \
A---B---E---F (main) A---B---E---F---G (main)
Osnovna različica združitve
Osnovna različica združitve je najnovejši skupni prednik dveh potrditev. Pitmaster jo poišče s sprehodom po grafu potrditev. Če je osnovnih različic združitve več (križajoča se zgodovina), jih merge() najprej združi in rezultat uporabi kot osnovo.
$base = $repo->mergeBase(
$repo->resolve('main'),
$repo->resolve('feature/login'),
);
if ($base !== null) {
echo "Common ancestor: {$base->hex}\n";
}
Za neposreden dostop do algoritma MergeBase:
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);
Preverjanje združitve vej
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
}
Oznake sporov
Če je datoteka spremenjena v obeh vejah in se spremembe prekrivajo, Pitmaster ustvari standardne oznake sporov. merge() označi strani z HEAD in imenom združene veje:
<<<<<<< HEAD
return $this->value + 1;
=======
return $this->value * 2;
>>>>>>> feature
Razred ConflictMarker ovije dve različici z oznakami:
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');
Trosmerno združevanje vsebine
Razred ThreeWayMerge združuje vsebino objektov blob (ne datotek):
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
Sprejme tri nize (osnovno različico, našo različico in njihovo različico), izbirne oznake in slog sporov (privzeto 'merge' ali 'diff3', da vključi razdelek z osnovno različico).
Strategije združevanja
Rekurzivno združevanje
Privzeta strategija ($repo->merge($branch)) obravnava zgodovino križajočih se združitev z več osnovnimi različicami. Razred CLI za to sprejema tudi -s ort in -s recursive.
Združevanje po naši različici
Zabeleži potrditev združitve, ki ohrani drevo HEAD nespremenjeno. Uporabno za vzdrževanje zgodovine veje brez vključevanja sprememb.
$result = $repo->merge('feature/old', 'ours');
Združevanje Octopus
Združi dve ali več vej v eno samo potrditev združitve. Če pride do spora v kateri koli veji, vrne nečist rezultat, ne da bi zapisalo stanje združitve ali ustvarilo potrditev.
$result = $repo->mergeOctopus(['feature/a', 'feature/b', 'feature/c']);
Razredi RecursiveMerge, OursMerge in OctopusMerge v Pitmaster\Merge so pomočniki za združevanje na ravni vsebine; Repository samega izvaja zgornje strategije.
Rerere (ponovna uporaba zabeležene razrešitve)
Pitmaster vključuje samostojen razred Rerere, ki shranjuje razrešitve v postavitvi rr-cache za git:
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() ga ne pokliče: razrešitve se zabeležijo in znova uporabijo samo, če to stori vaša koda. isEnabled() v .git/config išče dobesedno besedilo rerere.enabled = true in ne prepozna razdelka [rerere], ki ga zapiše git config rerere.enabled true (#20).
Potek združevanja na ravni dreves
Celoten postopek združevanja:
MergeBase::findAll()poišče skupne prednike- Drevesa osnove, naše in njihove različice se primerjajo po poteh
- Pri datotekah, spremenjenih samo v eni veji: uporabi to spremembo
- Pri datotekah, spremenjenih v obeh vejah:
- Če sta bili spremenjeni enako: uporabi katero koli različico (ujemata se)
- Če se spremembe razlikujejo: za vsebino zažene
ThreeWayMerge::merge()
- Če vsa združevanja uspejo brez sporov: sestavi združeno drevo in ustvari potrditev združitve
- Če pride do sporov: vrne
MergeResultzclean = falsein potmi do datotek v sporu
Uporaba CLI
./vendor/bin/pitmaster merge feature/login
Izhod ob uspehu:
Merge successful.
Izhod ob sporu:
CONFLICT in: src/File.php, src/Other.php