Jak myśleć o TouchQuill
Zanim wpiszesz pierwszą komendę, warto złapać trzy idee, na których stoi cały system. Reszta dokumentacji będzie się do nich odwoływać.
1. Treść ma adres, nie nazwę
Każdy plik, drzewo katalogów i commit jest przechowywany pod adresem wyliczonym z jego zawartości (hash BLAKE3). Konsekwencje są praktyczne: identyczna tekstura w dwóch miejscach zajmuje miejsce raz; serwer wysyła tylko obiekty, których naprawdę nie masz; a jeśli cokolwiek przekłamie się w transferze, klient to wykryje, bo hash się nie zgodzi. Nie musisz w to wierzyć na słowo — możesz to policzyć.
2. Binariów się nie merguje — bierze się je na wyłączność
Tekstury, meshe i blueprinty nie mają sensownego merge'a. Zamiast udawać, że mają, TouchQuill wbudowuje lock w sam rdzeń: kto trzyma lock, ten commituje; serwer odrzuci push zmiany w zablokowanym pliku od kogokolwiek innego. Kolejka sprawia, że „czekanie na plik" nie wymaga pisania na Slacku.
3. Zmiana jest ważniejsza niż commit
Commit to techniczny zapis; logiczna zmiana (Change ID, ch-…) żyje dłużej — przetrwa poprawki (amend), zmianę opisu i rebase. Dzięki temu review, locki i historia odwołują się do czegoś stabilnego. Do tego dochodzi dziennik operacji: prawie wszystko da się cofnąć przez tq undo, łącznie z odzyskaniem niezapisanej pracy po omyłkowym restore.
Instalacja i pierwszy commit
Klient to jedna binarka tq (Linux, Windows, macOS). Serwer — tq-server — potrzebny dopiero, gdy chcesz współdzielić pracę.
# Linux: paczka rpm · Windows: instalator · albo build ze źródeł: cargo build --release -p tq-cli
tq init MojaGra echo "asset" > Content/hero.txt tq commit -m "pierwszy asset" tq log # ch-4f2a91 rev:1 pierwszy asset (ty) tq status # co się zmieniło od ostatniego commitu
Pomyłka? Nic straconego:
tq restore # wróć do stanu z ostatniego commitu tq undo # ...a jeśli restore był pomyłką — odzyskaj to, co nadpisał
undo potrafi przywrócić nawet niezacommitowane pliki.Praca z zespołem
tq clone https://vcs.studio.com MojaGra # świeży klon tq login tqt_xxxxx # token dostajesz od admina tq push tq pull
Twoja tożsamość na serwerze wynika z tokenu, nie z tego, co zadeklaruje klient — dlatego w historii i audycie nie da się podszyć pod kolegę. Push jest zawsze fast-forward: jeśli ktoś Cię wyprzedził, najpierw pull.
Workflow: dzień artysty
Typowa sesja pracy nad assetami wygląda tak:
Rano: świeży stan
Zacznij od pobrania zmian zespołu. Jeśli projekt używa flag buildów, możesz zamiast najnowszej wersji wziąć ostatnią stabilną — taką, która na pewno się otwiera w edytorze.
tq pull # albo: tq get stable # ostatnia rewizja z zielonym CI
Weź plik na wyłączność
Zanim otworzysz binarkę w edytorze — lock. Jeśli ktoś już pracuje, stajesz w kolejce i dostaniesz powiadomienie, gdy plik będzie Twój.
tq lock Content/Characters/Hero.uasset
✓ Lock zajęty.Pracuj i zapisuj
Commituj małymi krokami — commit jest tani (milisekundy nawet przy dużych plikach). Jak coś pójdzie nie tak, tq undo cofa operację.
tq commit -m "nowa zbroja bohatera"
Wyślij i zwolnij
Po pushu zwolnij lock — następna osoba z kolejki dostanie go automatycznie, razem z powiadomieniem.
tq push tq unlock Content/Characters/Hero.uasset
Przerwa w połowie pracy?
Niedokończonej zmiany nie commituj na siłę — odłóż ją na shelf. Możesz ją też udostępnić koledze do podejrzenia.
tq shelf create -m "zbroja wip" --expires 48h
Workflow: zadanie programisty
Osobny channel na zadanie
Task channel dziedziczy stan z main, ale Twoje commity nie ruszają nikogo, dopóki nie skończysz.
tq channel create task/GROM-447 --type task tq channel switch task/GROM-447
Commituj swobodnie, poprawiaj śmiało
amend dokleja poprawkę do ostatniego commitu, reword zmienia opis. Change ID zostaje ten sam, więc nic się nie gubi.
tq commit -m "system dodge"
tq amend # poprawka do tej samej zmianyBądź na bieżąco z main
integrate wciąga zmiany z parenta. Konflikt? Nie zatrzyma Cię — zostanie zapisany, a Ty decydujesz kiedy i jak go rozwiązać.
tq integrate
tq conflicts # co wisi do rozwiązania
tq conflict resolve cfl-a1 --take theirsZamknij zadanie
complete scala channel do parenta i go zamyka. Historia zadania zostaje czytelna.
tq complete
Workflow: lead — release i porządek
Release channel z ostrą polityką
Na release nie wchodzą commity z nierozwiązanymi konfliktami, a pushować może tylko wskazany krąg. Polityka mieszka w wersjonowanym pliku — jej zmiana też przechodzi przez historię.
tq channel create release/1.0 --type release
# tq-channel.toml:
[permissions]
write = ["lead", "server-admin"]
integrate = ["lead"]Spory o locki
Ktoś zostawił lock i pojechał na urlop? Poproś o oddanie, a w razie potrzeby przejmij — każde takie działanie zostaje w dzienniku audytu, z powodem.
tq lock --request Content/Boss.uasset
tq steal Content/Boss.uasset # wymaga uprawnienia lock.stealKonflikty pod kontrolą
Konflikty można przypisywać osobom i nadawać im terminy. Nierozwiązane po terminie eskalują — nic nie ginie w szumie.
tq conflict assign cfl-a1 marta tq conflict defer cfl-b2 --deadline 48h
Kto co zrobił
Dziennik audytu rejestruje działania administracyjne i próby przekroczenia uprawnień. Integralność sprawdzisz jedną komendą.
tq-server audit log --denied tq-server audit verify
Workflow: CI i buildy
Konto tylko do tego, co trzeba
CI dostaje token PAT ograniczony do konkretnych uprawnień — nawet jeśli wycieknie, nie zrobi nic ponad swój zakres.
tq-server user pat ci-build --user ci --scopes repo.read,build-flag.set
Buduj i oznaczaj
Po udanym buildzie CI ustawia flagę na rewizji. To jest sygnał „ta wersja działa".
tq build-flag set --rev rev:128 --flag ci --state ok
Zespół bierze stabilne
Artysta nie musi trafić na zepsuty commit programisty: get stable pobiera ostatnią rewizję ze wszystkimi wymaganymi flagami na zielono.
tq get stable
Channele
Channel to linia pracy — odpowiednik brancha, ale z typem i polityką. Typ niesie sensowne domyślne zachowania: na release nie wejdzie commit z konfliktem, task ma właściciela i cykl życia (create → integrate → complete), personal to Twoja piaskownica.
Wart poznania jest channel wirtualny: widok na wycinek repo. Zespół grafików może dostać samo Content/ — kod dla nich „nie istnieje", ale ich commity trafiają do wspólnej historii, z zachowaniem plików, których nie widzą.
tq channel create widok --type virtual --include "Content/..." --exclude "Source/..."
Locki
Model jest prosty: jeden właściciel, reszta w kolejce. Lock ma timeout bezczynności (domyślnie 4 h) — jak zapomnisz zwolnić i pójdziesz do domu, system nie zablokuje zespołu na noc. Możesz poprosić właściciela o oddanie (--request) albo przekazać lock konkretnej osobie (--give).
Serwer egzekwuje locki przy push: jeśli polityka channela mówi, że *.uasset wymaga locka, push zmiany bez locka zostanie odrzucony z czytelnym komunikatem. Praca offline też jest przewidziana — deklarujesz lock lokalnie, a po powrocie system synchronizuje; jeśli dwie osoby wzięły ten sam plik offline, powstaje spór, który blokuje obie strony do decyzji leada. Nikt nikomu cicho nie nadpisze pracy.
Konflikty
W większości systemów konflikt to ściana: merge staje, a Ty rzucasz wszystko, żeby go rozbroić. W TouchQuill konflikt to zapisany obiekt (cfl-…) z pełnym kontekstem: obie wersje, wspólny przodek, kto i kiedy. Integracja przechodzi zawsze; konflikty rozwiązujesz, kiedy masz na to przestrzeń — albo deleguje je lead.
tq conflict resolve cfl-a1 --take theirs # przyjmij ich wersję tq conflict resolve cfl-a1 --merge # scal pluginem (jeśli format ma differ)
Change ID
Hash commitu zmienia się przy każdej poprawce — Change ID nie. To rozróżnienie brzmi subtelnie, ale w praktyce oznacza, że komentarz z review „popraw to w ch-4f2a91" pozostaje trafny po Twoim amend i rebase. Historia operacji (tq op log) dopełnia obraz: każda operacja zostawia ślad i większość da się cofnąć.
Lens
Klasyczny blame odpowiada na pytanie „kto zmienił linijkę 40 w pliku X". Lens odpowiada na pytanie, które naprawdę zadajesz: „co się działo z tą funkcją?" — także wtedy, gdy plik zmieniał nazwę, a funkcja wędrowała między modułami. Zmiany czysto kosmetyczne (formatowanie, komentarze) nie zaśmiecają wyniku.
tq lens blame --symbol calculate_damage
CREATED ch-6f9 rev:1 krzysztof „pierwsza wersja"
MODIFIED ch-a12 rev:3 marta „buff obrażeń"
MOVED ch-c73 rev:5 krzysztof (Weapon.rs → Combat.rs)
Dobre praktyki
Kilka nawyków, które w praktyce robią największą różnicę:
- Lock przed otwarciem, nie przed zapisem. Najczęstszy scenariusz utraty pracy to godzina edycji pliku, do którego lock ma kto inny. Wyrób odruch: binarka → najpierw
tq lock. - Wymuś locki polityką, nie kulturą. Wpisz
require-lock-for = ["*.uasset", "*.fbx"]dotq-channel.toml. Ludzka pamięć zawodzi, serwer nie. - Commituj często — to nic nie kosztuje. Przy magazynie adresowanym treścią commit dużego repo to milisekundy, a każdy commit to punkt, do którego można wrócić.
- Shelf zamiast commitów „wip". Niedokończona praca nie musi brudzić historii channela. Shelf ma TTL i można go udostępnić do pary oczu.
- Jedno zadanie — jeden task channel. Male channele integrują się łatwo. Wielotygodniowy kombajn będzie bolał w każdym systemie kontroli wersji.
- CI ustawia flagi, zespół bierze
get stable. To najtańszy sposób, by artyści nigdy nie trafili na zepsuty build. - Konflikt przypisz albo odłóż — nie zostawiaj „na wisząco".
assign/deferz terminem sprawiają, że konflikty mają właściciela i deadline, a eskalacja zadziała sama. - Na maszynach deweloperskich włącz fsmonitor.
tq fsmonitor startraz na sesję i status/commit przestają zależeć od rozmiaru drzewa. Działa na Linuksie i Windowsie.
Migracja z Git i Perforce
Obie migracje zachowują historię: autorów, czasy, wiadomości. Change ID są wyliczane deterministycznie ze źródła, a Lens działa na zaimportowanej historii od pierwszego dnia. Sensowna kolejność: zmigruj kopię repo, zweryfikuj, przełącz zespół, a stare repo zostaw w trybie tylko-do-odczytu na okres przejściowy.
tq migrate from-git --repo /sciezka/repo --branch main tq migrate from-p4 --port perforce:1666 --user krzysztof --path //depot/... tq migrate verify --repo /sciezka/repo
Serwer i uprawnienia
Serwer wystawia gRPC (klienci), REST (integracje) i SSE (live feed zdarzeń). Uwierzytelnianie włącza się z pierwszym dodanym użytkownikiem — wcześniej działa tryb otwarty, wygodny na testy.
tq-server --data /var/tq --listen 0.0.0.0:7470 --tls-cert cert.pem --tls-key key.pem tq-server user add krzysztof --role developer
Siedem ról wbudowanych (od viewer po server-admin), custom role przez klonowanie z odjęciem uprawnień, ograniczenia ścieżek dla kontraktorów („tylko Content/Weapons/..."), PAT-y ze scope'ami dla automatów i override per channel. Do tego replikacja na regiony (locki zostają na primary — jedno źródło prawdy), mTLS między serwerami i kopie zapasowe jedną komendą.
Referencja komend
| Komenda | Opis |
|---|---|
tq init / clone / setup | utwórz / sklonuj / skonfiguruj repo |
tq add / edit / status / diff | zmiany w worktree |
tq commit / amend / reword | zapis rewizji (Change ID stabilny) |
tq log / show / cat / restore | historia i nawigacja |
tq rebase / revert | przebazowanie / rewizja-odwrotność |
tq op log / undo / redo | dziennik operacji i cofanie |
tq channel … | create / switch / list / policy |
tq integrate / complete | integracja i domknięcie channela |
tq lock / unlock / locks | locki z kolejką, request / give |
tq conflict(s) … | resolve / assign / defer |
tq shelf … | odkładanie pracy, udostępnianie, TTL |
tq lens blame / symbols | historia symboli |
tq build-flag / get stable | flagi buildów i stabilna wersja |
tq workspace … | save / sync / offline / mount / presence |
tq migrate from-git / from-p4 | import historii |
tq fsmonitor start / stop / status | demon zmian plików (Linux / Windows / macOS) |
tq notify … | powiadomienia, DND, digest |
tq plugin … | pluginy WASM: extractor / differ |
tq admin obliterate / channel | trwałe usuwanie treści, override uprawnień |
Specyfikacja techniczna i decyzje architektoniczne (ADR) leżą w repozytorium.