Shramba
Git shramba shrani spremembe delovnega imenika in indeksa, da lahko preklopite na drugo opravilo in jih pozneje obnovite. Pitmaster izvaja shrambo z uporabo refs/stash in refloga, v skladu s postavitvijo shrambe za git. Na Repository ni metode za shrambo; uporabite spodnji razred Stash.
Znani sta dve težavi: če je vnosov več kot eden, drop() (in zato tudi pop()) pusti vnos na seznamu (#10), apply() pa prepiše nepotrjene spremembe v datotekah, ki se jih shramba ne dotika (#11). Shrambe uveljavljajte v čistem delovnem drevesu.
Delovanje shrambe
Vsak vnos shrambe je potrditev z dvema nadrejenima potrditvama:
- Nadrejena potrditev 0: potrditev HEAD v času shranjevanja (osnovno stanje)
- Nadrejena potrditev 1: potrditev, ki zajame stanje indeksa (pripravljene spremembe)
Lastno drevo potrditve shrambe zajame stanje delovnega drevesa (vključno z nepripravljenimi spremembami).
»Sklad« shrambe je reflog za refs/stash. Najnovejša shramba je kar refs/stash. Starejši vnosi so vnosi refloga: stash@{0}, stash@{1} itd.
refs/stash -> stash commit (worktree state)
parent[0] -> HEAD at time of stash
parent[1] -> index state commit
parent[0] -> HEAD at time of stash
Ustvarjanje predmeta Stash
use Pitmaster\Stash\Stash;
$stash = new Stash(
$repo->objectDatabase(),
$repo->refDatabase(),
$repo->gitDir(),
$repo->workDir(),
);
Potisni (shrani spremembe)
// public function push(string $message = '', bool $includeUntracked = false): ObjectId
$stashId = $stash->push('Work in progress on login');
echo "Saved: {$stashId->hex}\n";
// Also stash untracked files
$stashId = $stash->push('With new files', includeUntracked: true);
Potisni izvede naslednje:
- Prebere trenutno potrditev HEAD
- Zgradi drevo iz trenutnega indeksa (pripravljeno stanje)
- Ustvari »potrditev indeksa« z nadrejeno potrditvijo HEAD
- Zgradi drevo iz trenutnega delovnega imenika (vključno z nepripravljenimi spremembami)
- Ustvari potrditev shrambe (drevo delovnega drevesa, nadrejeni potrditvi = HEAD + potrditev indeksa)
- Posodobi
refs/stash, da kaže na potrditev shrambe - Doda vnos refloga za sklad
- Ponastavi delovno drevo in indeks na HEAD
Po potisku se sledene datoteke ujemajo s HEAD. Nesledene datoteke ostanejo, razen če je nastavljen includeUntracked; v tem primeru se odstranijo in shranijo v lastno drevo potrditve shrambe (git jih namesto tega shrani v tretjo nadrejeno potrditev, zato jih git vidi kot sledene spremembe). push() ustvari vnos tudi, če ni bilo sprememb; v tem primeru git sporoči »Ni lokalnih sprememb za shranjevanje«.
S privzetim sporočilom
$stashId = $stash->push();
// Message: "WIP on <branch>: <short hash> <HEAD subject>"
// With a message: "On <branch>: <message>"
Pri odpetem HEAD je <branch> enak HEAD.
Izprazni (uveljavi in odstrani)
$stash->pop();
Uveljavi vrhnji vnos shrambe v delovnem imeniku in ga odstrani iz sklada. Enakovredno je apply(), ki mu sledi drop().
Izprazni določen vnos
$stash->pop(1); // Pop stash@{1}
Uveljavi (obnovi brez odstranitve)
$stash->apply(); // Apply stash@{0}
$stash->apply(2); // Apply stash@{2}
Uveljavi združi shrambo s trenutno datoteko HEAD po datotekah (osnova shrambe, trenutni HEAD, drevo shrambe). Vnos shrambe ostane v skladu, indeks pa se ne spremeni. Ob sporih v datotekah ostanejo označevalniki Updated upstream in Stashed changes, sproži pa se Pitmaster\Exceptions\MergeConflictException; pop() nato vnos ohrani. Uveljavi predhodno ne preveri lokalnih sprememb (glejte opombo na vrhu).
Seznam vnosov
$entries = $stash->listEntries();
foreach ($entries as $entry) {
echo "stash@{{$entry['index']}}: {$entry['message']}\n";
// stash@{0}: On main: Work in progress on login
// stash@{1}: WIP on main: f707601 Add login form
}
Vsak vnos vsebuje:
index: položaj shrambe (0 = najnovejša)message: sporočilo shrambehash: zgoščena vrednost potrditve shrambe
Izbriši (odstrani brez uveljavitve)
$stash->drop(); // Drop stash@{0}
$stash->drop(1); // Drop stash@{1}
Če izbrišete edini vnos, se odstranita refs/stash in njegov reflog. Če je vnosov več, drop() trenutno samo premakne refs/stash in refloga ne spremeni, zato vnos ostane v listEntries() (#10).
Podrobnosti shranjevanja
Struktura potrditve shrambe
commit <hash>
tree <worktree-tree-hash>
parent <HEAD-hash>
parent <index-commit-hash>
author <current identity>
committer <current identity>
<stash message>
Struktura potrditve indeksa
commit <hash>
tree <index-tree-hash>
parent <HEAD-hash>
author <current identity>
committer <current identity>
index on <branch>: <short hash> <HEAD subject>
Identiteta izhaja iz GIT_COMMITTER_NAME, nato GIT_AUTHOR_NAME, nato user.name v konfiguraciji repozitorija, nato Pitmaster (enak vrstni red velja za e-pošto, ki se konča z pitmaster@example.invalid). Datum izhaja iz GIT_COMMITTER_DATE, nato GIT_AUTHOR_DATE, nato iz trenutnega časa. Za razliko od potrditev shramba ne bere konstant PITMASTER_*.
Shranjevanje Reflog
Vnosi shrambe so shranjeni v .git/logs/refs/stash:
0000000000000000000000000000000000000000 abc123... Name <email> 1700000000 +0000 WIP on main: f707601 Add login form
abc123... def456... Name <email> 1700000001 +0000 On main: Work in progress on login
Reflog se bere v kronološkem vrstnem redu. Seznam shrambe ga obrne (najnovejše najprej). Reflog shrambe se zapiše ne glede na core.logallrefupdates.
Uporaba CLI
# Save current changes
./vendor/bin/pitmaster stash
./vendor/bin/pitmaster stash push
./vendor/bin/pitmaster stash push "Work in progress on login"
# Apply and remove top entry
./vendor/bin/pitmaster stash pop
# Apply without removing
./vendor/bin/pitmaster stash apply
# List all entries
./vendor/bin/pitmaster stash list
# Remove top entry without applying
./vendor/bin/pitmaster stash drop
Sporočilo je argument za push (ali save); -m ni podprt. pop, apply in drop vedno delujejo na stash@{0}; CLI nima --include-untracked.
Omejitve
- Samo shramba celotnega delovnega imenika (brez
--keep-index); nesledene datoteke so podprte samo prekpush($message, includeUntracked: true) - Ni načina
--patch(interaktivni izbor kosov) - Izprazni/uveljavi obnovi stanje delovnega drevesa; indeksa ne obnovi. Pripravljene spremembe se vrnejo kot nepripravljene, na novo pripravljene datoteke pa kot nesledene
stash@{n}ne sprejemaRepository::resolve()- Shramba v povezanem delovnem drevesu uporablja napačno mesto konfiguracije in refloga (#14)