Jesteś w trakcie zmian w trzech plikach na feature branchu, nic jeszcze nie zacommitowane, gdy kolega pisze o null-pointerze, który wywala produkcję. Standardowy ruch to git stash, checkout na main, poprawka, push, a potem git stash pop w nadziei, że nic w twojej niedokończonej funkcjonalności nie zależało od plików, od których właśnie odszedłeś. git worktree pomija całą tę żonglerkę. Robi checkout brancha z hotfixem do drugiego folderu, obok twojego feature brancha, a oba korzystają z tego samego repozytorium.
Co właściwie robi git worktree
Zwykły checkout daje ci pliki jednego brancha naraz. Przełączenie brancha nadpisuje te pliki w miejscu. git worktree daje ci kilka checkoutów tego samego repozytorium, każdy w swoim katalogu i na swoim branchu, które możesz edytować niezależnie od siebie.
To nie są osobne klony. Istnieje dokładnie jeden katalog .git, który przechowuje bazę obiektów, referencje i konfigurację, a każdy worktree czyta z niego i do niego zapisuje. W drugim worktree .git nie jest nawet katalogiem — to jednolinijkowy plik wskazujący z powrotem na wspólny katalog. Dlatego stworzenie worktree jest prawie natychmiastowe i nie dodaje żadnej historii na dysku.
Jedno ograniczenie ma znaczenie. Dwa worktree nie mogą mieć tego samego brancha zacheckoutowanego naraz, bo branch wskazuje na jeden aktualny commit, a dwa checkouty commitujące do niego rywalizowałyby o ten wskaźnik. Wszystko inne jest przypisane do konkretnego worktree: pliki nieśledzone, indeks i to, na jakim commicie stoi HEAD.
Jak stworzyć worktree na hotfix
Masz już checkout myapp, siedzisz na branchu feature/checkout-flow, z niezacommitowanymi zmianami:
| |
To tworzy ../myapp-hotfix obok twojego bieżącego katalogu, z nowym branchem hotfix/null-pointer, utworzonym z main i zacheckoutowanym w tym nowym worktree. Twój oryginalny katalog zostaje na feature/checkout-flow, niezapisany i nietknięty.
| |
Z powrotem w oryginalnym katalogu twoja praca nad funkcjonalnością jest dokładnie taka, jaką ją zostawiłeś. Nic do pop, żadnego stasha, o którym można zapomnieć.
Bez -b, git worktree add <path> nazywa branch po ostatnim elemencie ścieżki. Jeśli branch o tej nazwie nie istnieje, Git tworzy go z HEAD; jeśli istnieje i nie jest zacheckoutowany w innym worktree, Git po prostu go checkoutuje. Użyj -d (--detach), gdy chcesz pogrzebać w konkretnym commicie bez żadnego brancha.
Jak wylistować, usunąć i wyczyścić worktree
| |
| |
Gdy hotfix zostanie zmergowany, usuń worktree przez Gita, a nie przez usunięcie folderu:
| |
remove odmawia, jeśli worktree ma zmodyfikowane pliki śledzone albo nieśledzone. Dodaj -f, żeby to wymusić. Jeśli katalog zniknie w inny sposób (przypadkowy rm -rf, padnięty job CI), Git zachowuje swój wpis administracyjny i git worktree list wciąż go pokazuje. Usuń nieaktualny wpis:
| |
Najpierw uruchom to z -n, żeby zobaczyć, co by usunęło.
Niektóre worktree powinny zostać na tygodnie: długo żyjący branch z release’em albo checkout na dysku sieciowym, który nie jest zawsze zamontowany. Zablokuj je, żeby prune nie dotykał ich wpisu, a move i remove odmawiały na nich działania:
| |
Odblokuj najpierw, jeśli chcesz przenieść worktree za pomocą git worktree move <path> <new-path>. Przeniesienie albo usunięcie zablokowanego worktree bez odblokowania wymaga --force podanego dwa razy — to ma być świadome, celowe obejście.
Kiedy jeszcze używać git worktree, nie tylko do hotfixów
Zawsze, gdy potrzebujesz dwóch działających checkoutów naraz, nie jednego:
- Przegląd PR bez utraty miejsca pracy.
git worktree add ../myapp-review origin/some-pr-branchdaje ci kompilowalną kopię czyjegoś brancha, a twoja własna praca zostaje zacheckoutowana tam, gdzie była. - Odpalenie
git bisectbez blokowania wszystkiego innego. Bisect przesuwaHEADna każdym kroku, więc checkout, w którym działa, staje się bezużyteczny do czegokolwiek innego, aż skończysz albo zrobisz reset. Odpal go w dedykowanym worktree (zobacz Git Bisect: Jak Znaleźć Commit, który Wprowadził Buga) i pracuj dalej w głównym. - Dwa zadania na repo w tym samym czasie. Długi test suite na jednym branchu, podczas gdy edytujesz drugi, albo dwa agenty AI do kodowania na osobnych zadaniach: każdy potrzebuje swojego katalogu roboczego. Worktree dostarcza go bez drugiego
git clonei drugiego, wielogigabajtowego folderu.git.
Kiedy nie używać git worktree
Każdy worktree duplikuje working tree, nie bazę obiektów. Dziesięć worktree repozytorium z 50 MB checkoutem to z grubsza 500 MB plików na dysku, nawet z jednym .git. Na pięciominutowe przełączenie kontekstu git stash jest tańszy i nie zostawia nic do czyszczenia.
Submoduły są tutaj najsłabszym ogniwem. git worktree move nie przeniesie worktree, który zawiera submoduły, a nowy worktree zaczyna z pustymi katalogami submodułów, aż uruchomisz w nim git submodule update --init. Sama dokumentacja Gita nazywa wsparcie dla submodułów w wielu checkoutach niekompletnym, więc dla superprojektu z wieloma submodułami bezpieczniejszym wyborem jest osobny klon.
Część narzędzi też zakłada jeden katalog roboczy na repozytorium. IDE albo file-watcher, który buduje cache na podstawie absolutnej ścieżki repo, może się pogubić, widząc tę samą historię w dwóch miejscach. Otworzenie każdego worktree jako osobnego projektu, a nie jako podfolderu pierwszego, zwykle to rozwiązuje.
Jeśli potrzebujesz tylko odłożyć coś na bok albo cofnąć zmianę w tym, co już masz zacheckoutowane, lżejszym narzędziem jest git stash albo git reset, revert czy restore. Następnym razem, gdy hotfix wyląduje w środku pracy nad funkcjonalnością, spróbuj git worktree add przed git stash i zobacz, po którym łatwiej posprzątać.