Do czego miałbym używać git-worktree?

211

Przeczytałem post Githuba na git-worktree . Piszą:

Załóżmy, że pracujesz w repozytorium Git w gałęzi o nazwie feature, gdy użytkownik zgłasza błąd o wysokim priorytecie master. Najpierw tworzysz połączone drzewo robocze z nową gałęzią, hotfixsprawdzane względem mistrza […] Możesz naprawić błąd, wcisnąć poprawkę i utworzyć żądanie ściągnięcia.

Kiedy pracuję nad gałęzią o nazwie funkcja i zgłaszany jest jakiś pilny błąd w programie głównym, zwykle ukrywam wszystko, nad czym pracuję, i tworzę nowy oddział. Kiedy skończę, mogę kontynuować pracę. To bardzo prosty model, pracuję tak od lat.

Z drugiej strony korzystanie z git-worktree ma swoje własne ograniczenia:

Na przykład niedozwolone jest wyewidencjonowanie tej samej gałęzi w dwóch połączonych działających drzewach jednocześnie, ponieważ pozwoliłoby to na dokonanie zmian w jednym działającym drzewie w celu zsynchronizowania drugiego.

Dlaczego miałbym wybrać bardziej skomplikowany przepływ pracy dla problemu, który został już rozwiązany?

Czy jest coś w git-worktreetym zakresie, czego nie można było zrobić wcześniej i to uzasadnia tę nową, złożoną funkcję?

awendt
źródło
12
Jedną rzeczą, której nie możesz ukryć, są nie połączone ścieżki po scaleniu lub zmianie bazy z konfliktami.
chirlu
11
Jeśli pracujesz ze skompilowanymi językami, ukrywanie oznacza, że ​​będziesz musiał ponownie skompilować wszystko, gdy będziesz odblokowywać.
mb14,
Mamy kilka różnych produktów opartych na tym samym kodzie źródłowym (300 MB), a ja planuję połączyć je wszystkie w jedno duże repozytorium i użyć drzewa roboczego, aby przechowywać wszystkie produkty w innym folderze, zamiast mieć mnóstwo klony, które nie pozostają w synchronizacji
endolith

Odpowiedzi:

196

Dla mnie git worktree to największa poprawa od dawna. Pracuję nad rozwojem oprogramowania dla przedsiębiorstw. Tam często zachowuje się stare wersje, takie jak wydane 3 lata temu. Oczywiście masz gałąź dla każdej wersji, dzięki czemu możesz łatwo przejść do niej i naprawić błąd. Jednak przełączanie jest kosztowne, ponieważ w międzyczasie całkowicie zrestrukturyzowałeś repozytorium i być może zbudowałeś system. Jeśli się przełączysz, twoje IDE oszaleje, próbując dostosować ustawienia projektu.

Dzięki worktree możesz uniknąć ciągłej rekonfiguracji. Sprawdź te stare gałęzie w osobnych folderach, korzystając z drzewa roboczego. Dla każdego oddziału masz niezależny projekt IDE.

Oczywiście można to było zrobić w przeszłości przez kilkakrotne klonowanie repozytorium i do tej pory takie było moje podejście. Oznaczało to jednak także marnowanie miejsca na dysku twardym i gorsze konieczność kilkakrotnego pobrania tych samych zmian z repozytorium.

Sebi
źródło
4
Nie musiałeś kilkakrotnie pobierać tych samych zmian z repozytorium. Mogłeś po prostu skopiować katalog .git pierwszego klonu.
misiu_mp,
1
@ jdk1.0 przepraszam za zamieszanie, komentarz został skierowany do misiu_mp
mxttie
2
Jako ktoś, kto użył 2-3 wysoce replikowanych repozytoriów, dzięki czemu mogę zbudować jedną gałąź funkcji, a jednocześnie rozwijać się na innej, każdy lokalny repozytorium jest zdalny dla innych i całkowicie zgadzam się z charakterystycznymi wadami Sebiego (dużo pobierania i pchania! ). Po przejściu do drzewa roboczego stwierdzam, że nie będę się już musiał martwić rozbieżnościami w lokalnych oddziałach o tej samej nazwie (co zdarza się raz na 6–10 miesięcy, ponieważ jestem przerywany wielokrotnie w ciągu kilku dni i kończę działający w tej samej gałęzi funkcji z wielu repozytoriów, ale zapomnij zsynchronizować je z powrotem ...)
mędrzec
3
@iheanyi - (1). Jest to szybsze, jeśli IDE utrzymuje zewnętrzne pliki danych (takie jak indeksowanie baz danych) powiązane z danym katalogiem. Jeśli przerzucisz zawartość do tego samego katalogu, zwykle spowoduje to unieważnienie pamięci podręcznej danych IDE i konieczne będzie ponowne indeksowanie.
Steve Hollasch
5
@iheanyi - (2) Z biegiem czasu historia wszystkiego będzie znacznie większa niż pliki drzewa roboczego w danym momencie. Historia wszystkiego == .gitkatalog. Przy wielu lokalnych klonach z góry, masz wiele lokalnych kopii tej samej bazy danych, ponieważ każdy klon ma swoją własną .gitbazę danych. W przypadku wielu lokalnych działających drzew każde drzewo korzysta z tej samej .gitbazy danych. Tak, jeśli masz lokalne klony lokalnego środowiska roboczego, Git dokona twardego połączenia dużej części zawartości .git, ale nie w systemie Windows.
Steve Hollasch
70

Widzę w tym pewne zastosowania.

Jeśli masz zestaw testowy, który działa przez długi czas, wyobraź sobie godziny, a uruchomisz go skutecznie blokuje kopię roboczą do czasu zakończenia testów. Zmiana gałęzi podczas tych testów złamałaby je w sposób trudny do zrozumienia.

Dzięki temu git-worktreemogłem uruchomić drugi pomysł na inny dział, który tam pracuje.

Ponadto, kiedy przechodzę do innej gałęzi, aby przeprowadzić szybkie dochodzenie, moje IDE uważa, że ​​wiele plików nagle się zmieniło i zindeksuje wszystkie te zmiany, tylko po to, aby ponownie je zindeksować, kiedy wracam.

Trzecim przypadkiem użycia byłoby porównanie plików przy użyciu innych narzędzi niż git-diff, jak zwykle diff, między dwoma katalogami zamiast dwóch gałęzi.

Andreas Wederbrand
źródło
6
Czy nie git clonedziałałoby tak dobrze w przypadku wszystkich tych elementów?
jthill
12
Sklonowanie dużego repozytorium z pilota może zająć dużo czasu. Pracuję przeciwko jednemu repozytorium, którego klonowanie zajmuje kilka minut. Myślę, że możesz to zrobić git clone --reference. Ponadto zarządzanie wszystkimi innymi gałęziami będzie wykonywane tylko raz zamiast raz na katalog roboczy.
Andreas Wederbrand,
6
Nie klonuj z pilota, klonuj z lokalnego. Nie rozumiem problemu z zarządzaniem oddziałami, możesz to wyjaśnić?
jthill
14
Próbowałem użyć klonów i naprawdę istnieje problem z zarządzaniem. Zamiast jednego zestawu gałęzi mam zestaw klonów, których nie widzę wszystkich razem w jednym interfejsie użytkownika. Jeśli muszę wybrać kilka zmian, muszę je pobrać lub przepchnąć. Dodaje dodatkowe kroki do wszystkich działań. Wszystko jest wykonalne, ale zawsze występuje tarcie.
max630
2
A jeśli chodzi o konfigurowanie kopii zapasowej, pojedyncze repozytorium jest o wiele łatwiejsze.
max630
64

Jednym z oczywistych zastosowań jest jednoczesne porównanie zachowania (nie źródła) różnych wersji - na przykład różnych wersji strony internetowej lub po prostu strony internetowej.

Próbowałem tego lokalnie.

  • utwórz katalog page1.

  • w środku utwórz katalog srci git initto.

  • w srcstworzenie page1.htmlz małą zawartością i zobowiązać go.

  • $ git branch ver0

  • $ git worktree add ../V0 ver0

  • w srcmaster dodaj więcej tekstu page1.htmli zatwierdź go.

  • $ git branch sty1

  • edytuj page1.htmlw sty1gałęzi (dodaj charakterystyczny styl CSS) i dodaj zatwierdz.

  • $ git worktree add ../S1 sty1

Możesz teraz używać przeglądarki internetowej do jednoczesnego otwierania i przeglądania tych 3 wersji:

  • ..\page1\src\page1.html // cokolwiek git ma jako prąd

  • ..\page1\V0\page1.html // początkowa wersja

  • ..\page1\S1\page1.html // wersja w stylu eksperymentalnym

RodMcGuire
źródło
2
Nie rozumiem, jak to tłumaczy korzyść z używania do tego celu drzewa roboczego zamiast klonu.
iheanyi
@heheanyi Można powiedzieć to samo branch; odpowiedź jest taka sama: jest lżejsza i przystosowana do pracy.
OJFord
1
@OJFord, to trochę o to chodzi. Ta odpowiedź nie wyjaśnia mi, jakie jest to środowisko pracy. Oczywiście nie jest to alias dla gałęzi lub klonu, ale efekt, który tu widzę, wydaje się taki sam. Nie rozumiem, jak to jest lżejsze niż zwykłe używanie gałęzi lub klonowania.
iheanyi
@ iheanyi Różni się od korzystania z gałęzi - nie można używać samych gałęzi, aby uzyskać wiele stanów drzewa roboczego jednocześnie - i lżejszej niż drugi (.., n-ty) klon. Miałem na myśli to, że można również powiedzieć o oddziale „dlaczego nie klonować i wprowadzać zmian”, ale wiele gałęzi w jednym repozytorium jest lżejszym i łatwiejszym w zarządzaniu sposobem uzyskania takiego zachowania.
OJFord
@OJFord Nie sądzę, że to rozwiązuje mój problem z drzewem roboczym. Powiem to w ten sposób, bez względu na to, czy używasz gałęzi, klonu, czy czegoś innego, celem końcowym opisanego tutaj procesu jest porównanie trzech różnych wersji czegoś jednocześnie. W oparciu o to, co jest w odpowiedzi, nie rozumiem, dlaczego miałbym używać worktree zamiast jakiejś alternatywy. Odpowiedź nie wyjaśnia, co robi środowisko robocze, czego nie robią alternatywy. Twierdzisz, że coś jest lekkie (lub lżejsze), ale nie rozumiem, w jaki sposób środowisko robocze sprawia, że ​​gałęzie są mniej „ciężkie”.
iheanyi
29
  1. Istnieją uzasadnione powody, dla których możesz chcieć / potrzebować wielu drzew roboczych w systemie plików jednocześnie.

    • manipulowanie pobranymi plikami, gdy trzeba wprowadzić zmiany w innym miejscu (np. kompilacja / testowanie)

    • różnicowanie plików za pomocą zwykłych narzędzi do porównywania

    • podczas konfliktów scalania często chcę nawigować po kodzie źródłowym, ponieważ znajduje się on po stronie źródłowej, podczas rozwiązywania konfliktów w plikach.

    • Jeśli musisz często przełączać się w jedną i drugą stronę, tracisz czas na sprawdzanie i sprawdzanie, że nie musisz zajmować się wieloma stopniami roboczymi.

    • mentalny koszt przełączania kontekstu mentalnego między gałęziami za pomocą skrytki git nie jest tak naprawdę wymierny. Niektóre osoby uważają, że ukrywanie kosztu jest kosztem psychicznym, którego nie ma po prostu otwierając pliki z innego katalogu.

  2. Niektóre osoby pytają „dlaczego nie zrobić wielu lokalnych klonów”. Prawdą jest, że z flagą „--local” nie musisz się martwić o dodatkowe wykorzystanie miejsca na dysku. To (lub podobne pomysły) zrobiłem do tego momentu. Zalety funkcjonalne połączonych drzew roboczych w porównaniu z lokalnymi klonami to:

    1. W przypadku lokalnych klonów dodatkowe stoły robocze (które znajdują się w lokalnych klonach) po prostu nie mają dostępu do początkowych ani odgałęzień. „Pochodzenie” w klonie nie będzie takie samo jak „pochodzenie” w pierwszym klonie.

      • Bieganie git log @{u}..lub git diff origin/feature/other-featuremoże być bardzo pomocne, a albo nie są już możliwe, albo trudniejsze. Pomysły te są technicznie możliwe w przypadku lokalnych klonów za pomocą zestawu obejść, ale każde obejście, które można zrobić, jest wykonywane lepiej i / lub prościej za pośrednictwem powiązanych ze sobą drzew roboczych.
    2. Możesz udostępniać referencje między stołami roboczymi. Jeśli chcesz porównać lub pożyczyć zmiany z innego lokalnego oddziału, teraz możesz.

Alexander Bird
źródło
11
Możesz także wyświetlić listę wszystkich drzew roboczych za pomocą jednego polecenia, z klonami, które musisz samemu śledzić.
Ian Ringrose
hmm Od wersji git 2.7.0 wydaje się, że tak jest. Dobrze wiedzieć.
Alexander Bird
9

tl; dr: Za każdym razem, gdy chcesz mieć jednocześnie sprawdzone dwa drzewa robocze z dowolnego powodu, git-worktreejest to szybki i zajmujący mało miejsca sposób.

Jeśli utworzysz inne środowisko robocze, większość części repozytorium (tj. .git) Zostanie udostępniona, co oznacza, że ​​jeśli utworzysz gałąź lub pobierzesz dane, gdy jesteś w jednym drzewie roboczym, będzie on również dostępny z dowolnego innego drzewa roboczego. Załóżmy, że chcesz uruchomić pakiet testowy na gałęzi foo bez konieczności wypychania go gdzieś w celu sklonowania go i chcesz uniknąć kłopotów z klonowaniem repozytorium lokalnie, użycie git-worktreejest dobrym sposobem na utworzenie tylko nowej kasy jakiegoś stanu w oddzielne miejsce, tymczasowo lub na stałe. Podobnie jak w przypadku klonu, wszystko, co musisz zrobić, gdy to zrobisz, to usuń go, a odwołanie do niego zostanie po pewnym czasie wyrzucone.

jsageryd
źródło
2
Dokumenty mówią, że nie możesz mieć tego samego oddziału w obu kopiach roboczych, co jest poważnym ograniczeniem. W przypadku Mercurial działał tylko z niewielkimi problemami.
hypersw
Oczywiście że możesz. Strona podręcznika mówi jak; szukać --force. Ale jest to niewygodne, jeśli aktualizujesz gałąź w jednym miejscu i spodziewasz się pracować nad nią w innym, ponieważ drzewo robocze nie jest aktualizowane.
jsageryd
Tak, oddziały w Mercurial są bardziej przejrzystą koncepcją w tym aspekcie. Jak pojawiają się gałęzie z jednego drzewa roboczego w drugim? Taki sam sposób jak wiele łączy w górę? Moje pierwsze eksperymenty z tabelami roboczymi, z uruchomieniem pobierania w obu, zakończyły się na dwóch (!) Różnych (!) Wskaźnikach o nazwie origin/master.
hypersw
Drzewo robocze (jak sama nazwa wskazuje) to tylko drzewo robocze z kilkoma dodatkowymi funkcjami; repozytorium jest wspólne dla wszystkich drzew roboczych. Jedyna różnica między dwoma drzewami roboczymi polega na tym, że gałąź wyewidencjonowana może być (a dla zdrowych przepływów pracy - inna). Możliwe jest zatwierdzenie w osobnym drzewie roboczym, więc ma on również własny indeks (inaczej obszar przejściowy), aby to działało. .gitPlik w oddzielnej worktree jest plik tekstowy, zawierający ścieżkę do konfiguracji, która znajduje się w pierwotnym repozytorium.
jsageryd
2
@WilsonF: git checkout --ignore-other-worktrees <branch> git-scm.com/docs/git-checkout/…
jsageryd
7

Początkowo natknąłem się na to pytanie, zastanawiając się, do czego można wykorzystać te fantazyjne stoły robocze. Od tego czasu zintegrowałem je z moim procesem pracy i pomimo początkowego sceptycyzmu uznałem je za całkiem przydatne.

Pracuję na dość dużej podstawie kodu, co zajmuje sporo czasu. Zazwyczaj mam na komputerze bieżącą gałąź programistyczną wraz z gałęzią funkcji, nad którą obecnie pracuję, oraz gałąź główną, która reprezentuje bieżący stan systemu na żywo.

Jedną z największych korzyści dla mnie jest oczywiście to, że nie muszę rekompilować całej rzeczy za każdym razem, gdy zmieniam gałęzie (czyli drzewa robocze). Fajnym efektem ubocznym jest to, że mogę przejść do drzewa programowania, zrobić tam rzeczy, zmienić katalog na drzewo pracy dla mojej bieżącej gałęzi funkcji, a następnie dokonać zmiany bazy bez konieczności ciągnięcia.

rethab
źródło
4

Mam dość nietypowy: programuję systemy Windows i Linux na tym samym komputerze . Mam VirtualBox z systemem Linux wewnątrz mojego systemu Windows. VirtualBox montuje niektóre katalogi Windows i używa ich bezpośrednio w komputerze z systemem Linux. To pozwala mi używać systemu Windows do zarządzania plikami, ale budować w systemie Linux. Jest to projekt wieloplatformowy, więc opiera się zarówno na systemie Windows, jak i Linux z tej samej struktury katalogów.

Problem polega na tym, że systemy kompilacji Linux i Windows ulegają awarii, gdy są używane w tym samym katalogu; istnieją pewne skomplikowane kroki kompilacji pobierania bibliotek itp., które używają tych samych nazw katalogów. Wersja systemu kompilacji dla systemu Windows pobiera biblioteki specyficzne dla systemu Windows, a wersja systemu kompilacji dla systemu Linux pobiera biblioteki specyficzne dla systemu Linux.

W idealnym świecie system kompilacji zostałby zmodyfikowany, aby systemy Windows i Linux mogły współistnieć w katalogu, ale na razie problem jest rozwiązywany za pomocą drzew roboczych. Folder „Linux” może generować artefakty kompilacji specyficzne dla systemu Linux, a folder „Windows” może generować artefakty kompilacji systemu Windows. Chociaż nie jest to idealne rozwiązanie, stanowi dobrą przerwę w oczekiwaniu na usunięcie błędów systemu kompilacji.

Trzeba przyznać, że nie stworzono do tego drzewa roboczego; Muszę zachować wersję Windows i Linuksa w osobnych gałęziach, mimo że naprawdę wolałbym, aby znajdowały się w tej samej gałęzi. Mimo to wykonuje swoją pracę i jest dość niekonwencjonalnym przypadkiem oszczędzania dnia przez środowisko pracy.

AHelps
źródło
+1 To wydaje się być bardzo skutecznym obejściem dla Make nie rób natywnych katalogów wyjściowych kompilacji konfiguracji. Mam podobną konfigurację VMware Workstation dla gości Ubuntu i macOS.
Tanz87
1

W nowym projekcie stworzyłem funkcję. Ale niektóre specyfikacje zawiodły. Aby porównać wyniki z masterutworzyłem work-treerepozytorium. Porównywałem wyniki krok po kroku w kodzie uruchomieniowym, aż zrozumiałem, co poszło nie tak.

itsnikolay
źródło
Jak jednak środowisko pracy czyni to łatwiejszym niż klon? Pytanie nie dotyczy osobistych preferencji, ale konkretnych różnic.
IInspectable
1

używam git worktree do rozwoju uczenia maszynowego.

Mam główny kod funkcjonalny, a następnie chcę podzielić gałęzie różnych eksperymentów (różne algorytmy i różne hiperparametry). git worktreepozwala mi zintegrować dvc z różnymi wersjami mojego kodu specjalizującymi się w różnych algorytmach. Po przeprowadzeniu wszystkich zadań szkoleniowych oceniam końcowe wskaźniki i łączę się, aby opanować najlepszą gałąź / model.

Ricardo MS
źródło