Co to znamená
Plán nad pracovním stromem se odvozuje ze stromu v daném okamžiku. V repozitáři, na kterém pracuje vždy jeden člověk, je to detail. Tady je to otázka správnosti: několik workerů sdílí checkout, další sdílejí repozitář, a plán spočtený na jednom HEAD a provedený na jiném commituje soubory, které někdo jiný přidal do stage, pod zprávou o práci, která už není tím, co se změnilo.
Tvrzení zní, že plán říká, z čeho byl vytvořen, dost přesně na to, aby se jednání podle něj později dalo odmítnout.
Princip
PlanFingerprint nese čtyři hodnoty:
- repozitář — společný adresář gitu, který sdílí každý worktree jednoho repozitáře a žádné dva repozitáře;
- worktree — vlastní kanonická cesta tohoto checkoutu, která brání tomu, aby si dva worktree jednoho repozitáře sdílely plán;
- head — commit, ve kterém byl plán vytvořen, nebo
unborn; - changes — SHA-256 přes každou změnu s jejím stupněm a stavem, v pořadí. Přestagování jednoho souboru jej změní; dotek souboru, který plán neobsahuje, ne.
differs_from vrací větu, ne boolean, protože „plán je zastaralý“ není nic, podle čeho by se dalo jednat, zatímco „HEAD se od vytvoření plánu posunul z a1b2c3d4e na e4f5a6b70“ ano. Není to zámek a závod nezabrání; jen odmítá být tím, kdo ho potichu prohraje.
Tatáž hodnota nese druhou vlastnost, která s souběžností nemá nic společného. Sada změn obsahující generované soubory se plánuje jako jeden commit, ne několik, a zdůvodnění jmenuje project.derived-files-regenerated jako pravidlo, které rozhodlo: generovaný soubor je projekcí celého stromu, takže aktuální může nést jen poslední z několika commitů a každý dřívější commit by byl ze své podstaty zastaralý — což hook derived-current pak odmítne, commit po commitu, když už bylo rozdělení provedeno. Plánovač to zjistil při prvním skutečném běhu, proti vlastní sadě změn, kde navrhl dát třiadvacet generovaných souborů do samostatného commitu.
Jak to vidět
majordomus commit plan # the plan, with the fingerprint and each group's reason
majordomus commit plan --format json | jq .fingerprint
git add <one more file>
majordomus commit plan --format json | jq .fingerprint # the change hash moved
bash test/run.sh 274_commit_policy # the case proves all of it against real git
Případ připraví soubor ve stage a přečte otisk, připraví další a ověří, že se hash pohnul, commitne a ověří, že se pohnul HEAD, pak přidá druhý propojený worktree téhož repozitáře a ověří, že oba plány sdílejí repository a liší se v worktree.
Co nepokrývá
Detekuje, nebrání. Dva workeři mohou stále plánovat proti témuž stromu a závodit o provedení; nemůže se stát jen to, že plán poraženého se potichu aplikuje na strom, pro který nevznikl.
Otiskuje sadu změn, ne obsah. Soubor upravený a znovu upravený na stejný počet status písmen mezi dvěma plány dává stejný hash — vlastní zastaralost indexu, ne tohoto subsystému, a git status hlásí totéž.
Perzistovaný plán zatím nic nespotřebovává, protože ho nic nepersistuje: commit.plan je čistá funkce stromu a pokaždé odpoví znovu. Otisk existuje proto, aby se ten, kdo jeden drží — stránka Cockpitu otevřená deset minut, agent, který plánoval před spuštěním testů — mohl zeptat, zda stále popisuje strom před ním.
Proč existuje
V tomto repozitáři pracovalo až deset relací najednou, napříč primárním checkoutem a třiceti několika linked worktree. Selhání, proti kterému to chrání, není hypotetické: commit vytvořený z plánu, jehož strom se posunul, se potom nedá odlišit od commitu, který někdo zamýšlel.