Pāriet uz saturu

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.

Kods
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

PHP
use Pitmaster\Stash\Stash;

$stash = new Stash(
    $repo->objectDatabase(),
    $repo->refDatabase(),
    $repo->gitDir(),
    $repo->workDir(),
);

Push (saglabāt izmaiņas)

PHP
// 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:

  1. Nolasa pašreizējo HEAD komitu
  2. Izveido koku no pašreizējā indeksa (sagatavotais stāvoklis)
  3. Izveido „indeksa komitu”, kura vecāks ir HEAD
  4. Izveido koku no pašreizējās darba direktorijas (tostarp nesagatavotajām izmaiņām)
  5. Izveido stash komitu (darba koka koks, vecāki = HEAD + indeksa komits)
  6. Atjaunina refs/stash, lai tas norādītu uz stash komitu
  7. Pievieno stekam reflog ierakstu
  8. 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

PHP
$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)

PHP
$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

PHP
$stash->pop(1);  // Pop stash@{1}

Apply (atjaunot, nenoņemot)

PHP
$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

PHP
$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ņojums
  • hash: stash komita jaucējvērtība

Drop (noņemt, nelietojot)

PHP
$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

Kods
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

Kods
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

Kods
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

Apvalks
# 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 ar push($message, includeUntracked: true)
  • Nav --patch režī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ņemts Repository::resolve()
  • Stash saistītā darba kokā izmanto nepareizo konfigurāciju un reflog atrašanās vietu (#14)