Liigu sisu juurde

Salvestusloend

Git stash salvestab töökausta ja indeksi muudatused, et saaksid liikuda teise ülesande juurde ja need hiljem taastada. Pitmaster rakendab stash'i, kasutades refs/stash ja reflog'i, järgides git salvestuspaigutust. Meetodil Repository pole stash-funktsiooni; kasuta allpool olevat klassi Stash.

Teada on kaks probleemi: mitme kirje korral jätab drop() (ja seega ka pop()) kirje loendisse (#10), ning apply() kirjutab üle kinnitamata muudatused failides, mida salvestusloend ei puuduta (#11). Rakendage salvestusloendi kirjeid puhtas tööpuus.

Salvestusloendi toimimine

Iga salvestusloendi kirje on kahe vanemaga commit:

  • Vanem 0: HEAD-i commit salvestamise ajal (baasolek)
  • Vanem 1: indeksi oleku (lavastatud muudatuste) jäädvustav commit

Salvestusloendi commiti enda puu jäädvustab tööpuu oleku (sh lavastamata muudatused).

Salvestusloendi „pinu” on asukoha refs/stash reflog. Kõige uuem salvestusloend on refs/stash ise. Vanemad kirjed on reflogi kirjed: stash@{0}, stash@{1} jne.

Kood
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

Salvestusloendi objekti loomine

PHP
use Pitmaster\Stash\Stash;

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

Lükake peale (salvestage muudatused)

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);

Pealelükkamine teeb järgmist:

  1. Loeb praeguse HEAD-i commiti
  2. Koostab praegusest indeksist puu (lavastatud olek)
  3. Loob „indeksi commiti”, mille vanem on HEAD
  4. Koostab praegusest töökataloogist puu (sh lavastamata muudatused)
  5. Loob salvestusloendi commiti (tööpuu puu, vanemad = HEAD + indeksi commit)
  6. Uuendab väärtuse refs/stash salvestusloendi commitile
  7. Lisab pinule reflogi kirje
  8. Lähtestab tööpuu ja indeksi HEAD-i olekusse

Pärast push'i vastavad jälgitavad failid HEAD-ile. Jälgimata failid jäävad alles, kui pole määratud includeUntracked; sel juhul need eemaldatakse ja salvestatakse stash-kinnituse oma puusse (git salvestab need hoopis kolmandasse eellasse, seega git näeb neid jälgitavate muudatustena). push() loob kirje ka siis, kui midagi pole muutunud; sel juhul teatab git „No local changes to save”.

Vaikesõnumiga

PHP
$stashId = $stash->push();
// Message: "WIP on <branch>: <short hash> <HEAD subject>"
// With a message: "On <branch>: <message>"

Eraldatud HEAD-i korral on <branch> väärtus HEAD.

Pop (rakendage ja eemaldage)

PHP
$stash->pop();

Rakendab ülemise salvestusloendi kirje töökausta ja eemaldab selle pinust. Samaväärne toiminguga apply(), millele järgneb drop().

Kindla kirje pop-toiming

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

Rakenda (taasta eemaldamata)

PHP
$stash->apply();      // Apply stash@{0}
$stash->apply(2);     // Apply stash@{2}

Rakendamine ühendab salvestusloendi praeguse HEAD-i failidega ükshaaval (salvestusloendi baas, praegune HEAD, salvestusloendi puu). Kirje jääb pinusse ja indeksit ei puudutata. Konfliktide korral lisatakse failidesse märgenditega Updated upstream ja Stashed changes markerid ning tekib viga Pitmaster\Exceptions\MergeConflictException; pop() jätab seejärel kirje alles. Rakendamine ei kontrolli enne kohalikke muudatusi (vt ülal olevat märkust).

Kirjete loetlemine

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
}

Iga kirje sisaldab:

  • index: salvestusloendi asukoht (0 = kõige uuem)
  • message: salvestusloendi sõnum
  • hash: salvestusloendi commiti räsi

Eemaldamine (eemalda rakendamata)

PHP
$stash->drop();       // Drop stash@{0}
$stash->drop(1);      // Drop stash@{1}

Ainsa kirje eemaldamisel kustutatakse refs/stash ja selle reflog. Kui kirjeid on rohkem, liigutab drop() praegu ainult väärtust refs/stash ega muuda reflogi, mistõttu kirje jääb asukohta listEntries() (#10).

Salvestuse üksikasjad

Salvestusloendi commiti struktuur

Kood
commit <hash>
tree <worktree-tree-hash>
parent <HEAD-hash>
parent <index-commit-hash>
author <current identity>
committer <current identity>

<stash message>

Indeksi commiti struktuur

Kood
commit <hash>
tree <index-tree-hash>
parent <HEAD-hash>
author <current identity>
committer <current identity>

index on <branch>: <short hash> <HEAD subject>

Identiteet pärineb hoidla konfiguratsioonis esmalt väärtusest GIT_COMMITTER_NAME, seejärel GIT_AUTHOR_NAME, siis user.name ja lõpuks Pitmaster (sama järjekord kehtib e-posti puhul ning lõpus on pitmaster@example.invalid). Kuupäev pärineb esmalt väärtusest GIT_COMMITTER_DATE, seejärel GIT_AUTHOR_DATE ja lõpuks praegusest kellaajast. Erinevalt commitidest ei loe salvestusloend väärtusi PITMASTER_*.

Reflog-i salvestus

Salvestusloendi kirjed asuvad asukohas .git/logs/refs/stash:

Kood
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

Reflogi loetakse kronoloogilises järjekorras. Salvestusloendi loend pöörab selle ümber (uusim ees). Salvestusloendi reflog kirjutatakse olenemata väärtusest core.logallrefupdates.

CLI kasutamine

Shell
# 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

Sõnum on argument pärast push (või save); -m pole toetatud. pop, apply ja drop toimivad alati asukohas stash@{0}; CLI-il pole väärtust --include-untracked.

Piirangud

  • Ainult kogu töökausta salvestamine (ilma --keep-index-ta); jälgimata failid ainult väärtuse push($message, includeUntracked: true) kaudu
  • --patch režiimi pole (interaktiivne tükkide valik)
  • Pop/rakendamine taastab tööpuu oleku, kuid ei taasta indeksit. Lavastatud muudatused taastuvad lavastamata muudatustena ja äsja lavastatud failid jälgimata failidena
  • stash@{n} ei aktsepteeri Repository::resolve()
  • Salvestusloendi kasutamine lingitud tööpuus rakendab vale konfiguratsiooni- ja reflogiasukohta (#14)