Preskoči na vsebino

Delovna drevesa

Git delovna drevesa omogočajo, da več delovnih imenikov uporablja isti repozitorij. Vsako delovno drevo ima svoj prevzem (HEAD, indeks, delovne datoteke), z glavnim repozitorijem pa si deli shrambo objektov, konfiguracijo in packed-refs. Pitmaster lahko ustvari, izpiše, zaklene in odstrani povezana delovna drevesa ter jih odpre kot repozitorije. Čiščenje, premikanje in popravljanje delovnih dreves niso podprti.

Pojmi

Običajen repozitorij git ima eno delovno drevo:

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

Z delovnimi drevesi lahko ustvarite dodatne delovne kopije:

Koda
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

Datoteka .git povezane delovne kopije vsebuje relativno pot glede na delovno kopijo (ne gre za imenik):

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

Ustvarjanje delovne kopije

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() naredi naslednje:

  1. Ustvari vejo, če ta še ne obstaja (iz HEAD-a ali določenega zapisa $from)
  2. Ustvari imenik metapodatkov v .git/worktrees/<name>/
  3. Zapiše datoteko .git v imenik delovne kopije
  4. Zapiše datoteke metapodatkov HEAD, commondir in gitdir
  5. Izpiše drevo veje v imenik delovne kopije
  6. Zapiše indeks za delovno kopijo

Če veja že obstaja, se $from prezre. V nasprotju z git addWorktree() ne zavrne veje, ki je že izpisana v drugi delovni kopiji, in ne zažene kljuke post-checkout.

Z izrecnim imenom metapodatkov

Uporabite neobvezni argument name, če si lahko več povezanih delovnih kopij deli isto osnovno ime izpisa.

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

To ime metapodatkov se uporabi v .git/worktrees/<name>/ namesto v basename($path).

Iz določene objave

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

Seznam delovnih kopij

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";
}

Seznam vedno najprej vključuje glavno delovno kopijo, nato pa povezane delovne kopije. Na ročaju glavnega repozitorija pokličite worktrees(): pri ročaju povezane delovne kopije glavni vnos trenutno sporoča lastno pot povezane delovne kopije (#14).

Odstranjevanje delovne kopije

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

Odstranjevanje delovne kopije:

  1. Preveri, ali je delovna kopija zaklenjena (ne uspe, razen če je $force true)
  2. Odstrani datoteko .git iz imenika delovne kopije
  3. Odstrani imenik metapodatkov iz .git/worktrees/

Datoteke v delovnem drevesu se ne izbrišejo samodejno. Veja še naprej obstaja.

Odpiranje povezane delovne kopije

Povezano delovno kopijo lahko odprete tako kot kateri koli drug repozitorij:

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'

Operacije repozitorija razrešujejo poti takole:

  • Objekti: berejo in zapisujejo se v skupni imenik git (project/.git/objects/)
  • Konfiguracija: bere se iz skupnega imenika git (project/.git/config)
  • Packed-refs: bere se iz skupnega imenika git
  • HEAD: za vsako delovno kopijo posebej (vsaka delovna kopija spremlja svojo vejo), skupaj z ORIG_HEAD, MERGE_HEAD in drugimi referencami operacij
  • Indeks: za vsako delovno kopijo posebej (vsaka delovna kopija ima svoje območje priprave)
  • Ohlapne reference: veje in oznake so v skupnem imeniku (project/.git/refs/)
  • Kljuke: berejo se iz imenika git posamezne delovne kopije, zato se skupne kljuke ne zaženejo (#12)

Stash še ne obravnava povezanih delovnih kopij: identiteto bere iz imenika posamezne delovne kopije, ki nima konfiguracije, in tam zapisuje svoj dnevnik referenc (#14).

Objekt vrednosti delovne kopije

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

Za upravljanje delovnih kopij na nizki ravni. WorktreeManager::add() zapiše le metapodatke in datoteko .git: ne ustvari veje, ne izpiše datotek in ne zapiše indeksa. Za uporabno delovno kopijo uporabite $repo->addWorktree(). Veja mora že obstajati (ali pa mora biti podana kot polno ime reference, na primer refs/tags/v1.0.0, ki odklopi HEAD).

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

Zaklepanje delovnih kopij

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

Zaklep je shranjen kot datoteka v .git/worktrees/<name>/locked. Vsebina datoteke je razlog za zaklep (lahko je prazna).

Zaznavanje delovnih kopij

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'

Razporeditev datotek

Metapodatki glavne delovne kopije za povezane delovne kopije

Koda
.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

Datoteka .git povezane delovne kopije

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

Skupna raba virov

Vir Mesto V skupni rabi?
Objekti $commonDir/objects/ Da
Konfiguracija $commonDir/config Da
Packed-refs $commonDir/packed-refs Da
Kljuke $gitDir/hooks/ Ne: Pitmaster v povezanih delovnih kopijah ne zažene skupnih kljuk
HEAD $gitDir/HEAD Ne (za vsako delovno kopijo posebej)
Indeks $gitDir/index Ne (za vsako delovno kopijo posebej)
Ohlapne reference $commonDir/refs/ Da (HEAD in reference operacij, kot je MERGE_HEAD, so za vsako delovno kopijo posebej)