Ugrás a tartalomhoz

Munkafák

Git A munkafák lehetővé teszik, hogy több munkakönyvtár osztozzon egyetlen tárolón. Minden munkafának saját checkoutja van (HEAD, index, munkafájlok), miközben megosztja a fő tároló objektumtárolóját, konfigurációját és packed-refs állományát. A Pitmaster létrehozhatja, listázhatja, zárolhatja és eltávolíthatja az összekapcsolt munkafákat, és tárolóként is megnyithatja őket. A munkafák ritkázása, áthelyezése és javítása nincs megvalósítva.

Fogalmak

Egy szokásos git tárolónak egyetlen munkafája van:

Kód
project/
  .git/          (directory)
  src/
  README.md

Munkafákkal további checkoutokat is használhat:

Kód
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

Az összekapcsolt munkafa .git fájl, nem könyvtár; a munkafához viszonyított elérési utat tartalmazza:

Kód
gitdir: ../../path/to/project/.git/worktrees/review

Munkafa létrehozása

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)

A addWorktree() a következőket végzi:

  1. Létrehozza az ágat, ha még nem létezik (a HEAD-ből vagy a megadott $from commitból)
  2. Létrehozza a metaadatkönyvtárat itt: .git/worktrees/<name>/
  3. Megírja a munkakönyvtárban a .git fájlt
  4. Megírja a HEAD, a commondir és a gitdir metaadatfájlt
  5. Checkoutolja az ág fáját a munkakönyvtárba
  6. Megírja a munkafa indexét

Ha az ág már létezik, a $from figyelmen kívül marad. A gittel ellentétben a addWorktree() nem utasítja el azt az ágat, amelyet egy másik munkafában már checkoutoltak, és nem futtatja a post-checkout hookot.

Explicit metaadatnévvel

Használja az opcionális name argumentumot, ha több összekapcsolt munkafa azonos checkout-alapnevet használhat.

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

Ez a metaadatnév a .git/worktrees/<name>/ alatt szerepel a basename($path) helyett.

Adott commitból

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

Munkafák listázása

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

A lista mindig először a fő munkafát tartalmazza, majd az összekapcsolt munkafákat. A fő tároló fogantyúján hívja meg a worktrees() metódust: összekapcsolt munkafa fogantyúján a fő bejegyzés jelenleg az összekapcsolt munkafa saját elérési útját jelzi (#14).

Munkafa eltávolítása

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

Munkafa eltávolításakor:

  1. Ellenőrzi, hogy a munkafa zárolva van-e (sikertelen, hacsak a $force értéke nem true)
  2. Eltávolítja a munkakönyvtárból a .git fájlt
  3. Eltávolítja a metaadatkönyvtárat innen: .git/worktrees/

A munkafa fájljait nem törli automatikusan. Az ág továbbra is megmarad.

Összekapcsolt munkafa megnyitása

Az összekapcsolt munkafát ugyanúgy megnyithatja, mint bármely tárolót:

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'

A tárolóműveletek az alábbiak szerint oldják fel az elérési utakat:

  • Objektumok: a közös git könyvtárból olvas (project/.git/objects/), és oda ír
  • Konfiguráció: a közös git könyvtárból olvas (project/.git/config)
  • Packed-refs: a közös git könyvtárból olvas
  • HEAD: munkafánkénti (minden munkafa a saját ágát követi), a ORIG_HEAD, a MERGE_HEAD és a többi műveleti ref mellett
  • Index: munkafánkénti (minden munkafának saját staging területe van)
  • Laza refek: az ágak és címkék a közös könyvtárban vannak megosztva (project/.git/refs/)
  • Hookok: a munkafánkénti git könyvtárból olvasódnak, ezért a megosztott hookok nem futnak (#12)

A Stash még nem kezeli az összekapcsolt munkafákat: a munkafánkénti könyvtárból olvassa az identitást, ahol nincs konfiguráció, és oda írja a reflogot (#14).

Munkafa értékobjektum

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

Alacsony szintű munkafakezeléshez. A WorktreeManager::add() csak a metaadatokat és a .git fájlt írja meg: nem hozza létre az ágat, nem checkoutolja a fájlokat, és nem ír indexet. Használja a $repo->addWorktree() elemet használható checkouthoz. Az ágnak már léteznie kell (vagy teljes refnévnek kell lennie, például refs/tags/v1.0.0, ami leválasztja a HEAD-et).

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

Munkafák zárolása

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

A zárolás fájlként itt tárolódik: .git/worktrees/<name>/locked. A fájl tartalma a zárolás oka (üres is lehet).

Munkafák felismerése

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'

Fájlelrendezés

A fő munkafa metaadatai az összekapcsolt munkafákhoz

Kód
.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

Az összekapcsolt munkafa .git fájlja

Kód
gitdir: <relative path to>/project/.git/worktrees/<name>

Erőforrások megosztása

Erőforrás Hely Megosztva?
Objektumok $commonDir/objects/ Igen
Konfiguráció $commonDir/config Igen
Packed-refs $commonDir/packed-refs Igen
Hookok $gitDir/hooks/ Nem: a Pitmaster nem futtatja a megosztott hookokat az összekapcsolt munkafákban
HEAD $gitDir/HEAD Nem (munkafánkénti)
Index $gitDir/index Nem (munkafánkénti)
Laza refek $commonDir/refs/ Igen (a HEAD és a műveleti refek, például a MERGE_HEAD, munkafánkéntiek)