Stash
Git stash saglabā izmaiņas darba direktorijā un indeksā, lai jūs varētu pārslēgties uz citu uzdevumu un vēlāk tās atjaunot. Pitmaster īsteno stash, izmantojot refs/stash un reflog git krātuves izkārtojumā. Klasē Repository nav stash metodes; izmantojiet tālāk norādīto klasi Stash.
Divas zināmas problēmas: ja ir vairāk nekā viens ieraksts, drop() (un līdz ar to arī pop()) atstāj ierakstu sarakstā (#10), bet apply() pārraksta neapstiprinātās izmaiņas failos, kurus stash neskar (#11). Lietojiet stash tikai ar tīru darba koku.
Kā darbojas stash
Katrs stash ieraksts ir komits ar diviem vecākiem:
- Vecāks 0: HEAD komits stash izveides brīdī (bāzes stāvoklis)
- Vecāks 1: komits, kurā fiksēts indeksa stāvoklis (sagatavotās izmaiņas)
Paša stash komita koks fiksē darba koka stāvokli (tostarp nesagatavotās izmaiņas).
Stash „steks” ir refs/stash reflog. Jaunākais stash ir pats refs/stash. Vecākie ieraksti ir reflog ieraksti: stash@{0}, stash@{1} utt.
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
Stash objekta izveide
use Pitmaster\Stash\Stash;
$stash = new Stash(
$repo->objectDatabase(),
$repo->refDatabase(),
$repo->gitDir(),
$repo->workDir(),
);
Push (saglabāt izmaiņas)
// 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);
Push veic tālāk norādīto:
- Nolasa pašreizējo HEAD komitu
- Izveido koku no pašreizējā indeksa (sagatavotais stāvoklis)
- Izveido „indeksa komitu”, kura vecāks ir HEAD
- Izveido koku no pašreizējās darba direktorijas (tostarp nesagatavotajām izmaiņām)
- Izveido stash komitu (darba koka koks, vecāki = HEAD + indeksa komits)
- Atjaunina
refs/stash, lai tas norādītu uz stash komitu - Pievieno stekam reflog ierakstu
- Atiestata darba koku un indeksu uz HEAD
Pēc push izsekojamie faili atbilst HEAD. Neizsekotie faili paliek, ja vien nav iestatīts includeUntracked; tad tie tiek noņemti un saglabāti pašā stash komita kokā (git tos glabā trešajā vecākā, tāpēc git tos uzskata par izsekotām izmaiņām). push() izveido ierakstu arī tad, ja nekas nav mainījies; šādā gadījumā git ziņo: „No local changes to save”.
Ar noklusējuma ziņojumu
$stashId = $stash->push();
// Message: "WIP on <branch>: <short hash> <HEAD subject>"
// With a message: "On <branch>: <message>"
Ja HEAD ir atdalīts, <branch> ir HEAD.
Pop (lietot un noņemt)
$stash->pop();
Lieto steka augšējo stash ierakstu darba direktorijai un noņem to no steka. Atbilst apply(), kam seko drop().
Izņemt konkrētu ierakstu
$stash->pop(1); // Pop stash@{1}
Apply (atjaunot, nenoņemot)
$stash->apply(); // Apply stash@{0}
$stash->apply(2); // Apply stash@{2}
Apply failu pa failam apvieno stash ar pašreizējo HEAD (stash bāze, pašreizējais HEAD, stash koks). Stash ieraksts paliek stekā, un indekss netiek skarts. Konfliktu marķieri Updated upstream un Stashed changes tiek ierakstīti failos, un tiek izraisīts Pitmaster\Exceptions\MergeConflictException; pēc tam pop() ierakstu saglabā. Apply vispirms nepārbauda, vai nav lokālu izmaiņu (skatiet piezīmi augšā).
Ierakstu saraksts
$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
}
Katrā ierakstā ir:
index: stash pozīcija (0 = jaunākais)message: stash ziņojumshash: stash komita jaucējvērtība
Drop (noņemt, nelietojot)
$stash->drop(); // Drop stash@{0}
$stash->drop(1); // Drop stash@{1}
Ja tiek dzēsts vienīgais ieraksts, refs/stash un tā reflog tiek noņemti. Ja ir vairāki ieraksti, drop() pašlaik tikai pārvieto refs/stash, bet reflog nemaina, tāpēc ieraksts paliek listEntries() (#10).
Glabāšanas informācija
Stash komita struktūra
commit <hash>
tree <worktree-tree-hash>
parent <HEAD-hash>
parent <index-commit-hash>
author <current identity>
committer <current identity>
<stash message>
Indeksa komita struktūra
commit <hash>
tree <index-tree-hash>
parent <HEAD-hash>
author <current identity>
committer <current identity>
index on <branch>: <short hash> <HEAD subject>
Identitāte tiek iegūta šādā secībā: GIT_COMMITTER_NAME, GIT_AUTHOR_NAME, user.name repozitorija konfigurācijā, pēc tam Pitmaster (tāda pati secība tiek izmantota e-pasta adresei, noslēdzoties ar pitmaster@example.invalid). Datums tiek iegūts no GIT_COMMITTER_DATE, pēc tam GIT_AUTHOR_DATE un visbeidzot no pašreizējā laika. Atšķirībā no komitiem stash nelasa PITMASTER_* konstantes.
Reflog glabāšana
Stash ieraksti tiek glabāti šeit: .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 tiek nolasīts hronoloģiskā secībā. Stash sarakstā tas tiek apgriezts (jaunākais vispirms). Stash reflog tiek ierakstīts neatkarīgi no core.logallrefupdates.
CLI lietojums
# 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
Ziņojums ir arguments aiz push (vai save); -m netiek atbalstīts. pop, apply un drop vienmēr darbojas ar stash@{0}; CLI nav --include-untracked.
Ierobežojumi
- Tiek saglabāts tikai viss darba direktorijas stash (bez
--keep-index); neizsekotie faili — tikai arpush($message, includeUntracked: true) - Nav
--patchrežīma (interaktīva fragmentu atlase) - Pop/apply atjauno darba koka stāvokli; indekss netiek atjaunots. Sagatavotie labojumi atgriežas kā nesagatavoti labojumi, bet tikko sagatavotie faili — kā neizsekoti faili
stash@{n}netiek pieņemtsRepository::resolve()- Stash saistītā darba kokā izmanto nepareizo konfigurāciju un reflog atrašanās vietu (#14)