git worktree - ghdrako/doc_snipets GitHub Wiki
tags:
- git
- vcs
Git worktree
git worktree służy do pracy na wielu gałęziach (branchach) jednocześnie w osobnych katalogach, bez konieczności klonowania repozytorium od nowa i bez żonglowania zmianami przez git stash.
W klasycznym modelu Gita masz jeden katalog roboczy (working tree) i jeden katalog .git. Jeśli pracujesz nad dużą funkcją na gałęzi feature, a nagle musisz pilnie naprawić błąd na main lub hotfix, standardowa procedura wymaga:
- Schowania nieskończonej pracy (git stash).
- Przełączenia gałęzi (git checkout main).
- Zrobienia poprawki i commita.
- Powrotu (git checkout feature).
Przywrócenia zmian (git stash pop), co nierzadko kończy się konfliktami, a w projektach kompilowanych (np. C/C++, Rust) wymusza długi, pełny rebuild całego projektu od zera.
git worktree pozwala podpiąć dodatkowy katalog roboczy do tego samego lokalnego repozytorium.
# Będąc w głównym projekcie, tworzysz obok nowy katalog dla gałęzi hotfix:
git worktree add ../moj-projekt-hotfix hotfix-login
W tym momencie:
- Obok Twojego katalogu powstaje nowy folder moj-projekt-hotfix.
- Otwierasz go w osobnym oknie terminala lub IDE.
- Nie pobierasz danych z sieci – oba katalogi współdzielą tę samą bazę obiektów i historię z głównego folderu .git.
W starym katalogu nadal kompiluje się Twój feature, a w nowym natychmiast naprawiasz buga na hotfix-login.
Gdy skończysz pracę:
# Wracasz do głównego katalogu i usuwasz zbędne drzewo:
git worktree remove ../moj-projekt-hotfix
Kiedy worktree jest niezastąpione?
- Pilne hotfixy / Code Review: Przełączasz się na gałąź z PR-em kolegi w osobnym folderze, testujesz aplikację, podczas gdy Twoje lokalne, nieskommitowane pliki na głównym branchu leżą nienaruszone.
- Projekty kompilowane i bazy danych: Przełączenie brancha w locie w C/C++ dotyka nagłówków i unieważnia cache kompilacji (make, ninja, ccache), zmuszając do wielominutowego rebuildu. Dwa worktree oznaczają dwa niezależne foldery build/ – zero zbędnego rekompilowania.
- Długo działające procesy: Możesz na jednym branchu uruchomić testy integracyjne, a w drugim worktree pisać kolejny kod.
- Równoległe odpalanie dwóch wersji: Możesz postawić dwie instancje systemu (np. na różnych portach) i porównywać ich zachowanie na żywo obok siebie.
Zamiast kopiować cały folder .git (co zajęłoby mnóstwo miejsca i wymagało osobnego git fetch):
- Nowy folder nie ma własnego pełnego katalogu .git, a jedynie mały plik tekstowy .git, który zawiera ścieżkę wskazującą na katalog nadrzędny:
gitdir: /sciezka/do/glownego/.git/worktrees/moj-projekt-hotfix
- Wszystkie commity, drzewa i bloby są współdzielone. Nowy worktree ma jedynie własny stan indeksu (staging area) oraz wskaźnik HEAD.
Jedyna twarda zasada: Dwa różne katalogi robocze nie mogą mieć jednocześnie wymeldowanej (checked out) tej samej gałęzi, aby nie dopuścić do rozjechania się historii commitów.
git worktree add ../inny-katalog main
# albo wewnątrz istniejącego worktree:
git checkout main
zakończy się błędem:
fatal: 'main' is already checked out at '/sciezka/do/glownego-katalogu'