Git (WebCie)

From A-Eskwiki
Revision as of 16:55, 13 June 2019 by Jason (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Git (wat staat voor "Git") is het bovennatuurlijke systeem waarmee we controle houden op wat er gebeurt met alle WebCie-code. Als WebCie-lid heb je een kopie (een checkout) van het volledige systeem staan op je eigen account (in de map ~/wwwdebug). Deze code bepaalt wat jij te zien krijgt in je browser als je naar je persoonlijke debugpagina gaat (lijkt op https://bla-debug.a-eskwadraat.nl). Als je wijzigingen in deze code aanbrengt, veranderen dus alleen de pagina's op jouw persoonlijke debug-omgeving. Dat noemen we een sandbox, het zorgt er voor dat je rustig je code kan ontwikkelen zonder dat de rest van de WWW daar last van heeft. Bovendien is jouw debugpagina alleen benaderbaar door WebCie-leden, dus als je per ongeluk lekkende SQL-queries schrijft is dat geen ramp.

Op deze pagina staat basale info om aan de slag te gaan met Git. Je kan ook in de online handleiding kijken voor meer pro-tips.

De WebCie is onlangs overgestapt naar Git. Hierbij is ook de svn-geschiedenis gefilterd, dus pas op bij overstappen!

Workflow

Een ding waar je bij git waarschijnlijk aan moet wennen is dat iedereen een eigen idee heeft van de geschiedenis van alle code. Op de server staan een setje commitgeschiedenissen (oftewel branches), en op je debug staat ook zo'n setje. Met een beetje geluk komen ze ook nog overeen, maar dat hoeft dus niet! Er zijn commando's om van iemand anders de geschiedenis overnemen. Dan krijg je een kopietje binnen van hun geschiedenis, maar wordt jouw geschiedenis niet aangepast! Je hebt bijvoorbeeld de volgende branches, allemaal opgeslagen in je eigen debug:

  • master (jouw laatste editie van de livesite)
  • develop (jouw eigen editie van de "echte" code)
  • feature-watleuks (jouw eigen editie van deze feature)
  • feature-zoveel (een feature waarvan de server nog helemaal niet weet dat die bestaat)
  • HEAD (wijst naar de laatste commit die bij jou is gebeurd, dus als het goed is de branch waar je nu op werkt)
  • origin/master (wat jij denkt dat de servereditie van de livesite is)
  • origin/develop (wat jij denkt dat de servereditie van de "echte" code is)
  • origin/feature-watleuks (wat jij denkt dat de servereditie van de deze feature is)

Als je git fetch doet, zal git de laatste versie van elke branch van de server opvragen en die bewaren in origin/$branch. Dan kun je die weer in jouw branches stoppen met bijvoorbeeld git merge. Het commando git pull stuurt jouw editie van de huidige branch naar de server. (De server weet dus in principe niet welke gebruikers er zijn of welke branches ze hebben!)

We hebben twee hoofdbranches: master en develop. De livesite zou gelijk moeten lopen met de branch master, dus we moeten goed opletten wat we daarop zetten. Om makkelijk code te kunnen delen, gaan we in principe alle commits doen op de branch develop, maar het is nog netter om met branches te werken.

Handige commando's om het overzicht te bewaren:

  • git log om de commits op je huidige branch te bekijken.
  • git log $commit-of-branch-of-etc om de commits op een andere branch te bekijken. (Het is handig om hiervoor ook git fetch te doen.)
  • gitk als je beter tegen een grafische interface kan.
  • git status toont je branch, hoe die verschilt met origin/$branch en wat je ten opzichte van je branch hebt aangepast
  • git branch -a toont elke branch waar git in jouw debug van afweet
  • git log --graph --decorate --pretty=oneline --abbrev-commit om in de terminal een mooie gerichte graaf van commits te tonen (--all voor alle branches tegelijk)

Maak een feature

  1. git checkout develop en git pull om up to date te zijn
  2. maak een nieuwe branch met git checkout -b feature-$bla
  3. ga een stukje zitten programmeren
  4. heb je nieuwe bestanden toegevoegd: vertel dat aan git met git add $bestand
  5. wil je bestanden weggooien: doe dat en vertel het tegelijk aan git met git rm $bestand
  6. wil je kijken wat je allemaal hebt gedaan: gebruik git status en/of git diff
  7. ben je tevreden met een setje wijzigingen: commit ze met git add $gewijzigd_bestand1 $gewijzigd_bestand2 ... en git commit (het is netjes om eerst nog even te kijken wat je gaat committen zodat er geen troep meekomt)
  8. herhaal bovenstaande stappen tot je feature helemaal af is
  9. ben je klaar: stop je feature in develop met git checkout develop en dan git merge feature-$bla en maak het openbaar met git push (TODO: Of gaan we helemaal hardcore met pull requests beginnen?)
  10. alle webcie'ers krijgen nu een mailtje met de commits die je hebt gepleegd en zullen je feliciteren en/of afkraken op je programmeerstijl

Nu is werken in je eentje heel leuk, maar samenwerken geeft een veel mooier feestje! Daarom is het aan te raden dat je om de zoveel tijd commits van anderen opvraagt en met ze deelt:

  1. als iemand anders op je branch heeft gewerkt: doe git pull (krijg je een error in de trant van "geen remote voor branch", doe dan git branch --set-upstream-to origin/feature-$bla om de remote in te stellen en probeer opnieuw)
  2. als er dingen binnenkomen op develop: stop ze in je branch git fetch'en en dan git merge origin/develop. (Voor echte pro's is er ook git rebase, maar dat heeft meer problemen met samenwerken op de branch)
  3. als je je vooruitgang wilt delen: doe git push (krijg je een error in de trant van "geen remote voor branch", doe dan git branch --set-upstream-to origin/feature-$bla om de remote in te stellen en probeer opnieuw)

Fix een bug

(Je kan dit proces ook op develop doen als de bug niet zo heel hoge prioriteit heeft. Doe dan gewoon wat hierboven staat.)

Is er een bug die snel opgelost moet worden? Dan gaan we op basis van de livesite werken zodat we de fix apart kunnen houden van eventuele (halfbakken) features.

  1. git checkout master en git pull om up to date te zijn
  2. maak een nieuwe branch met git checkout -b bug-$bla
  3. doe precies hetzelfde programmeer-commitriedeltje als hiervoor beschreven
  4. als je in een commit een regel "Closes: #$bugnummer" zet, wordt de bug automatisch op gesloten gezet in Bugweb.
  5. ben je klaar: stop je fix in master met git checkout master en dan git merge bug-$bla en maak het openbaar met git push
  6. zorg ervoor dat develop up-to-date blijft: git checkout develop en dan git merge master en maak het openbaar met git push

Shit's on fire yo

Heb je er een potje van gemaakt, en wil je terug naar de laatste commit? Als je een enkel bestand wil terugzetten, heb je git checkout $bestand; alles wat je in het bestand hebt gedaan sinds de laatste commit wordt dan teruggezet zoals het was. De makkelijkste manier om echt helemaal alles weg te gooien is met git reset --hard HEAD; elk bestand dat je hebt veranderd t.o.v. je laatste commit wordt dan teruggezet zoals het was. Dit kan dus ook nuttige wijzigingen weggooien!

Heb je er een nog erger potje van gemaakt, en heb je een foute commit gemaakt? Als dit de laatste commit(s) was (waren) op je branch en je hebt ze nog niet gepusht, dan heb je git reset HEAD~1 om de laatste commit weg te gooien (en HEAD~n om n commits tegelijk ongedaan te maken.) Heb je ze al wel gepusht, dan moet je naar de aanpak hieronder overgaan.

Heeft iemand anders een enorm potje gemaakt, en wil je de commit ongedaan maken? Doe dan git revert $commit. Dat maakt een nieuwe commit waarin precies het tegenovergestelde gebeurt van die wijzigingen. De originele commit blijft nog wel in de geschiedenis staan! Als iemand dus geheime data heeft gecommit, moet je toch echt geavanceerde tools gebruiken.

Om iets live te zetten

Ten eerste: denk goed na of je dit echt wel wilt doen. Er kunnen nog wel eens gebruikers gaan klagen.

Doe gewoon een git push naar master op je eigen bakkie. Typ lekker ./zetLive.sh in de /scripts map en gaan met die banaan.

Migreren van SVN naar Git

Is jouw debug van voor de overstap? Dan is het niet heel lastig om te switchen!

Verhuizen van git-svn

Gebruik je al Git-SVN, dan kun je als volgt switchen:

  1. cd wwwdebug
  2. git remote add origin ssh://vm-www/srv/git
  3. git fetch
  4. git branch -t origin/develop

Nu moet je handmatig commits van je huidige branches op develop rebasen, want anders gaat de hele geschiedenis stuk. Check dat de 3e commit vanaf het begin begint met 9cf65047 ipv cc9c5bb. Zo niet, ga je allemaal antieke ledendata meepushen (die ik met pijn en moeite heb weggefilterd) en gaat de Autoriteit Persoonsgegevens je slaan.

Verhuizen zonder git-svn

Heb je wel een wwwdebug maar nog geen git? Dan moet je iets meer moeite doen om je laatste versie te bewaren:

  1. cd wwwdebug
  2. svn up
  3. svn log Kijk hier wat de laatste revisie is!
  4. git init
  5. git remote add origin ssh://vm-www/srv/git
  6. git fetch
  7. git commit --allow-empty -m "Initial empty commit" (want git snapt het niet als je geen commit hebt gedaan en wel branches wil beginnen, dan maar zo)
  8. git log origin/master Kijk hier welke git-commit overeenkomt met de laatste svn-revisie.
  9. git reset --mixed $laatste_revisie_commit
  10. git stash
  11. git checkout -t origin/develop
  12. git stash apply

Vertaalsleutel svn -> git

Het belangrijkste verschil is dat git heel veel verschillende commitgeschiedenissen heeft en svn maar eentje. Bij elk commando vraagt svn bijvoorbeeld aan de server of er nog commits bijgekomen zijn. Git doet dat alleen als je erom vraagt met git fetch. Het is daarom een goed idee om als svn'er voor elk commando git fetch te runnen totdat je doorhebt wanneer het echt nuttig is.

  • svn up -> git pull (vraag aan de remotes welke veranderingen er zijn, merge die automatisch)
  • svn st -> git status (vraag de huidige status op van jouw lokale kopie ten opzichte van jouw laatste commit)
  • svn diff -> git diff (bekijk alle wijzigingen die er zijn tussen jouw lokale kopie en jouw laatste commit)
  • svn ci -> git commit -a (stop al je wijzigingen in een nieuwe commit, die je zou kunnen opsturen naar de andere WebCie'ers)

Een nieuwe git-repo opzetten

Als je code die niet bij de livesite hoort wilt delen met de WebCie, kan dit via een aparte git-repo. Op deze manier maak je een nieuwe repo:

  • ssh vm-www
  • cd /srv
  • sudo mkdir git-$bla-repo
  • sudo chown webcie:webcie /srv/git-$bla-repo
  • sudo chmod o= /srv/git-$bla-repo
  • sudo chmod ug=rwx /srv/git-$bla-repo
  • sudo chmod g+s /srv/git-$bla-repo
  • cd /srv/git-$bla-repo
  • git init --bare --shared

Nu kun je als het goed is een git clone ssh://vm-www/srv/git-$bla-repo doen!

Migreren tussen Git-repo's

Als de repository ergens anders gehost gaat worden, wil je natuurlijk dat alle huidige code daar terechtkomt.

Stel dat er al een repository is aangemaakt voor de code (e.g. zoals hierboven beschreven), met bijvoorbeeld de URL git.example.com/user/repo.

Een WebCie'r moet dan doen:

  • git remote add new-origin $REMOTE_URL — Voeg de nieuwe repository als een remote toe.
  • git fetch origin — Haal alles op uit de huidige repository.
  • git push new-origin refs/remotes/origin/\*:refs/heads/\* — Hiermee pushen we alles van origin naar new-origin. (Aldus sprak StackOverflow) Let wel: misschien pusht dit juist iets te veel. Bij het testen hiervan kwam er bijvoorbeeld een branch op de nieuwe remote met de naam HEAD. Dit moet je dan weer even deleten met e.g. git push new-remote --delete HEAD.
  • git remote remove new-origin — Verwijder de remote.

Iedereen doet vervolgens:

  • git remote set-url origin $REMOTE_URL

En klaar is Kees! (Hopelijk...)

Git hooks

Om het leven van de WebCie wat makkelijker te maken zijn er git hooks die verschillende handmatige stappen automatiseren als ze nodig zijn. De volgende dingen zijn geautomatiseerd:

  • Het automatisch uitvoeren van ./composer install
  • Het automatisch uitvoeren van ./minify
  • Het automatisch uitvoeren van ./dia2php en ./dia2py