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:
project/
.git/ (directory)
src/
README.md
Z delovnimi drevesi lahko ustvarite dodatne delovne kopije:
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):
gitdir: ../../path/to/project/.git/worktrees/review
Ustvarjanje delovne kopije
$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:
- Ustvari vejo, če ta še ne obstaja (iz HEAD-a ali določenega zapisa
$from) - Ustvari imenik metapodatkov v
.git/worktrees/<name>/ - Zapiše datoteko
.gitv imenik delovne kopije - Zapiše datoteke metapodatkov
HEAD,commondiringitdir - Izpiše drevo veje v imenik delovne kopije
- 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.
$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
$wt = $repo->addWorktree('/tmp/hotfix', 'hotfix/urgent', $repo->resolve('v1.0.0'));
Seznam delovnih kopij
$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
$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:
- Preveri, ali je delovna kopija zaklenjena (ne uspe, razen če je
$forcetrue) - Odstrani datoteko
.gitiz imenika delovne kopije - 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:
$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_HEADin 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
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).
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
// 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
// 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
.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
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) |