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'