Siirry sisältöön

Työhakemistot

Git-työhakemistot mahdollistavat useiden työhakemistojen käytön yhden arkiston kanssa. Jokaisella työhakemistolla on oma uloskirjaus (HEAD, indeksi ja tiedostot), mutta ne jakavat pääarkiston kanssa oliotallennustilan, asetukset ja pakatut viitteet. Pitmaster voi luoda, luetteloida, lukita ja poistaa linkitettyjä työhakemistoja sekä avata ne arkistoina. Karsimista, siirtämistä ja korjaamista ei ole toteutettu.

Käsitteet

Tavallisessa git-arkistossa on yksi työhakemisto:

Koodi
project/
  .git/          (directory)
  src/
  README.md

Työhakemistojen avulla voit tehdä lisäuloskirjauksia:

Koodi
project/                          (main worktree)
  .git/                           (the actual git directory)
    worktrees/
      review/                     (metadata for linked worktree)
        HEAD
        commondir
        gitdir

/tmp/review/                      (linked worktree)
  .git                            (file, not directory)
  src/
  README.md

Linkitetyn työhakemiston .git on tiedosto (ei hakemisto), joka sisältää suhteellisen polun työhakemistoon:

Koodi
gitdir: ../../path/to/project/.git/worktrees/review

Työhakemiston luominen

PHP
$repo = Pitmaster::open('/path/to/project');

// Create a linked worktree on a new branch
$wt = $repo->addWorktree('/tmp/review', 'feature/review');

echo $wt->path;        // '/tmp/review'
echo $wt->branch;      // 'feature/review'
echo $wt->gitDir;      // '/path/to/project/.git/worktrees/review'
var_dump($wt->isMain);      // bool(false)
var_dump($wt->isDetached);  // bool(false)

addWorktree() tekee seuraavaa:

  1. Luo haaran, jos sitä ei ole (HEADistä tai määritetystä $from-commitista)
  2. Luo metatietohakemiston kohteeseen .git/worktrees/<name>/
  3. Kirjoittaa .git-tiedoston työhakemiston hakemistoon
  4. Kirjoittaa metatietotiedostot HEAD, commondir ja gitdir
  5. Ottaa haaran puun käyttöön työhakemiston hakemistossa
  6. Kirjoittaa työhakemiston indeksin

Jos haara on jo olemassa, $from ohitetaan. Toisin kuin git, addWorktree() ei kieltäydy luomasta haaraa, joka on jo otettu käyttöön toisessa työhakemistossa, eikä suorita post-checkout-koukkua.

Määritetyllä metatietonimellä

Käytä valinnaista name-argumenttia, kun useat linkitetyt työhakemistot voivat jakaa saman uloskirjauksen perusnimen.

PHP
$wt = $repo->addWorktree(
    '/tmp/sandboxes/app',
    'feature/review',
    name: 'sandbox-app',
);

Metatietonimeä käytetään kohteessa .git/worktrees/<name>/ kohteen basename($path) sijaan.

Tietystä commitista

PHP
$wt = $repo->addWorktree('/tmp/hotfix', 'hotfix/urgent', $repo->resolve('v1.0.0'));

Työhakemistojen luettelointi

PHP
$worktrees = $repo->worktrees();

foreach ($worktrees as $wt) {
    $type = $wt->isMain ? 'main' : 'linked';
    $branch = $wt->branch ?? 'detached';
    $locked = $wt->isLocked ? ' [locked]' : '';

    echo "{$wt->path} ({$type}) [{$branch}]{$locked}\n";
}

Luettelo sisältää aina ensin päätyöhakemiston, jota seuraavat linkitetyt työhakemistot. Kutsu worktrees()-metodia pääarkiston kahvalla: linkitetyn työhakemiston kahvalla päämerkintä ilmoittaa tällä hetkellä linkitetyn työhakemiston oman polun (#14).

Työhakemiston poistaminen

PHP
$repo->removeWorktree('review');          // by metadata name
$repo->removeWorktree('/tmp/review');     // or by worktree path

// Force remove (even if locked)
$repo->removeWorktree('review', force: true);

Työhakemiston poistaminen:

  1. Tarkistaa, onko työhakemisto lukittu (epäonnistuu, ellei $force ole true)
  2. Poistaa työhakemiston hakemistosta .git-tiedoston
  3. Poistaa metatietohakemiston kohteesta .git/worktrees/

Työhakemiston tiedostoja ei poisteta automaattisesti. Haara säilyy.

Linkitetyn työhakemiston avaaminen

Voit avata linkitetyn työhakemiston kuten minkä tahansa arkiston:

PHP
$repo = Pitmaster::open('/tmp/review');

// Pitmaster detects the .git file and follows the gitdir reference
echo $repo->isLinkedWorktree();  // true
echo $repo->gitDir();            // '/path/to/project/.git/worktrees/review'
echo $repo->commonGitDir();      // '/path/to/project/.git'
echo $repo->workDir();           // '/tmp/review'

Arkistotoiminnot ratkaisevat polut seuraavasti:

  • Oliot: luetaan yhteisestä git-hakemistosta ja kirjoitetaan siihen (project/.git/objects/)
  • Asetukset: luetaan yhteisestä git-hakemistosta (project/.git/config)
  • Pakatut viitteet: luetaan yhteisestä git-hakemistosta
  • HEAD: työhakemistokohtainen (jokainen työhakemisto seuraa omaa haaraansa), samoin kuin ORIG_HEAD, MERGE_HEAD ja muut toimintaviitteet
  • Indeksi: työhakemistokohtainen (jokaisella työhakemistolla on oma valmistelualue)
  • Löysät viitteet: haarat ja tunnisteet jaetaan yhteisessä hakemistossa (project/.git/refs/)
  • Koukut: luetaan työhakemistokohtaisesta git-hakemistosta, joten jaetut koukut eivät toimi (#12)

Stash ei vielä tue linkitettyjä työhakemistoja: se lukee identiteetin työhakemistokohtaisesta hakemistosta, jossa ei ole asetuksia, ja kirjoittaa reflogin sinne (#14).

Työhakemiston arvokohde

PHP
use Pitmaster\Worktree\Worktree;

$wt->name;          // Metadata name (null for the main worktree)
$wt->path;          // Working directory path
$wt->gitDir;        // Per-worktree git dir
$wt->branch;        // Branch name (null if detached)
$wt->head;          // ObjectId of HEAD commit
$wt->isMain;        // true for the main worktree
$wt->isDetached;    // true if HEAD is detached
$wt->isLocked;      // true if worktree is locked
$wt->lockReason;    // Lock reason, or null when there is none (an empty reason is also null)

WorktreeManager

Matalan tason työhakemistojen hallintaan. WorktreeManager::add() kirjoittaa vain metatiedot ja .git-tiedoston: se ei luo haaraa, ota tiedostoja käyttöön eikä kirjoita indeksiä. Käytä $repo->addWorktree()-toimintoa käyttökelpoisen uloskirjauksen luomiseen. Haaran on oltava olemassa (tai sen on oltava täydellinen viitenimi, kuten refs/tags/v1.0.0, jolloin HEAD irrotetaan).

PHP
use Pitmaster\Worktree\WorktreeManager;

$manager = new WorktreeManager($repo->commonGitDir(), $mainWorkDir);

// List
$worktrees = $manager->list();

// Add
$wt = $manager->add('/tmp/review', 'feature/review');
$wt = $manager->add('/tmp/review', 'feature/review', 'review-app');

// Remove
$manager->remove('review');
$manager->remove('review', force: true);

// Lock/unlock (metadata name only)
$manager->lock('review', 'Do not delete, code review in progress');
$manager->unlock('review');

Työhakemistojen lukitseminen

PHP
// Lock (prevents removal)
$manager->lock('review', 'Code review in progress');

// Attempt to remove locked worktree
try {
    $manager->remove('review');
} catch (\RuntimeException $e) {
    // "Worktree is locked: review (Code review in progress)"
}

// Force remove ignores the lock
$manager->remove('review', force: true);

// Unlock
$manager->unlock('review');

Lukitus tallennetaan tiedostoon kohteessa .git/worktrees/<name>/locked. Tiedosto sisältää lukituksen syyn (voi olla tyhjä).

Työhakemistojen tunnistaminen

PHP
// Check if a path is a linked worktree
if (Pitmaster::isWorktree('/tmp/review')) {
    echo "This is a linked worktree\n";
}

// Resolve the common git dir from any path
$common = Pitmaster::commonGitDir('/tmp/review');
// '/path/to/project/.git'

// Resolve a .git file to the actual git directory
$gitDir = WorktreeManager::resolveGitFile('/tmp/review');
// '/path/to/project/.git/worktrees/review'

Tiedostorakenne

Linkitettyjen työhakemistojen päätyöhakemiston metatiedot

Koodi
.git/worktrees/<name>/
  HEAD         Per-worktree HEAD (symbolic ref or detached hash)
  commondir    Relative path to the shared git dir ("../..")
  gitdir       Path back to the worktree's .git file, as passed to addWorktree()
  locked       Present if locked (content = reason)
  index        Per-worktree index/staging area

Linkitetyn työhakemiston .git-tiedosto

Koodi
gitdir: <relative path to>/project/.git/worktrees/<name>

Jaetut resurssit

Resurssi Sijainti Jaettu?
Oliot $commonDir/objects/ Kyllä
Asetukset $commonDir/config Kyllä
Pakatut viitteet $commonDir/packed-refs Kyllä
Koukut $gitDir/hooks/ Ei: Pitmaster ei suorita linkitettyjen työhakemistojen jaettuja koukkuja
HEAD $gitDir/HEAD Ei (työhakemistokohtainen)
Indeksi $gitDir/index Ei (työhakemistokohtainen)
Löysät viitteet $commonDir/refs/ Kyllä (HEAD ja toimintaviitteet, kuten MERGE_HEAD, ovat työhakemistokohtaisia)