GitHub Flow

Probleme cu git-flow

Viajez peste tot pentru a preda Git oamenilor și aproape fiecare clasă și atelier pe care l-am făcut recent m-a întrebat ce cred despre git-flow. Întotdeauna răspund că eu cred că este grozav – a luat un sistem (Git) care are un milion de fluxuri de lucru posibile și a documentat un flux de lucru bine testat, flexibil, care funcționează pentru o mulțime de dezvoltatori într-un mod destul de simplu. A devenit un fel de standard, astfel încât dezvoltatorii pot trece de la un proiect la altul sau de la o companie la alta și să fie familiarizați cu acest flux de lucru standardizat.

Cu toate acestea, are problemele sale. Am auzit o serie de păreri de la oameni de genul că nu le place faptul că noile ramuri de caracteristici sunt pornite de la develop mai degrabă decât de la master, sau modul în care se ocupă de hotfixes, dar acestea sunt destul de minore.

Una dintre cele mai mari probleme pentru mine este că este mai complicat decât cred că majoritatea dezvoltatorilor și echipelor de dezvoltare au nevoie de fapt. Este suficient de complicat încât a fost dezvoltat un script de ajutor mare pentru a ajuta la aplicarea fluxului. Deși acest lucru este grozav, problema este că nu poate fi impus într-o interfață grafică Git, ci doar în linia de comandă, astfel încât singurele persoane care trebuie să învețe foarte bine fluxul complex, deoarece trebuie să facă toți pașii manual, sunt aceleași persoane care nu se simt suficient de confortabil cu sistemul pentru a-l folosi din linia de comandă. Aceasta poate fi o problemă uriașă.

Ambele probleme pot fi rezolvate cu ușurință doar prin existența unui proces mult mai simplificat. La GitHub, noi nu folosim git-flow. Folosim, și am folosit întotdeauna, un flux de lucru Git mult mai simplu.

Simplicitatea sa îi conferă o serie de avantaje. Unul dintre ele este că este ușor de înțeles de către oameni, ceea ce înseamnă că îl pot deprinde rapid și rareori, dacă nu chiar niciodată, o dau în bară sau trebuie să anuleze pașii pe care i-au făcut greșit. Un altul este că nu avem nevoie de un script de înfășurare care să ne ajute să îl aplicăm sau să îl urmărim, așa că utilizarea interfețelor grafice și altele asemenea nu reprezintă o problemă.

GitHub Flow

Acum, de ce nu folosim git-flow la GitHub? Ei bine, principala problemă este că noi desfășurăm tot timpul. Procesul git-flow este conceput în mare parte în jurul „lansării”. Noi nu avem cu adevărat „versiuni”, deoarece implementăm în producție în fiecare zi – adesea de mai multe ori pe zi. Putem face acest lucru prin intermediul robotului nostru de chat, care este același loc în care sunt afișate rezultatele CI. Încercăm să facem ca procesul de testare și expediere să fie cât mai simplu posibil, astfel încât fiecare angajat să se simtă confortabil făcând acest lucru.

Există o serie de avantaje pentru a desfășura atât de regulat. Dacă desfășurați la fiecare câteva ore, este aproape imposibil să introduceți un număr mare de bug-uri mari. Pot fi introduse probleme mici, dar apoi acestea pot fi rezolvate și redistribuite foarte repede. În mod normal, ar trebui să faceți un „hotfix” sau ceva în afara procesului normal, dar face pur și simplu parte din procesul nostru normal – nu există nicio diferență în fluxul GitHub între un hotfix și o caracteristică foarte mică.

Un alt avantaj al desfășurării permanente este capacitatea de a rezolva rapid probleme de orice fel. Putem să răspundem la problemele de securitate care ne sunt aduse în atenție sau să implementăm cereri de caracteristici mici, dar interesante, incredibil de rapid, dar putem folosi exact același proces pentru a aborda aceste modificări ca și pentru a gestiona dezvoltarea normală sau chiar a unor caracteristici mari. Este vorba de același proces și totul este foarte simplu.

Cum o facem

Deci, ce este GitHub Flow?

  • Ceea ce se află în ramura master poate fi implementat
  • Pentru a lucra la ceva nou, creați o ramură cu nume descriptiv din master (de ex: new-oauth2-scopes)
  • Commiteți la acea ramură la nivel local și împingeți în mod regulat munca dvs. în aceeași ramură cu același nume pe server
  • Când aveți nevoie de feedback sau ajutor, sau când credeți că ramura este pregătită pentru fuziune, deschideți un pull request
  • După ce altcineva a revizuit și semnat caracteristica, o puteți unifica în master
  • După ce este unificată și împinsă în „master”, puteți și ar trebui să o implementați imediat

Acesta este întregul flux. Este foarte simplu, foarte eficient și funcționează pentru echipe destul de mari – GitHub are acum 35 de angajați, dintre care poate 15-20 lucrează în același timp la același proiect (github.com). Cred că majoritatea echipelor de dezvoltare – grupuri care lucrează la același cod logic în același timp, ceea ce ar putea produce conflicte – sunt cam de această dimensiune sau mai mici. Mai ales cele care sunt suficient de progresive pentru a face implementări rapide și consistente.

Așa că, să analizăm fiecare dintre acești pași pe rând.

#1 – orice din ramura master este implementabil

Aceasta este practic singura regulă dură a sistemului. Există doar o singură ramură care are o semnificație specifică și consistentă și am numit-o master. Pentru noi, aceasta înseamnă că a fost implementată sau, în cel mai rău caz, va fi implementată în câteva ore. Este incredibil de rar ca aceasta să fie derulată (ramura este mutată înapoi la o confirmare mai veche pentru a inversa munca) – dacă există o problemă, vor fi inversate confirmările sau vor fi introduse noi confirmări care rezolvă problema, dar ramura în sine nu este aproape niciodată derulată înapoi.

Ramura master este stabilă și este întotdeauna, întotdeauna sigur să desfășurăm din ea sau să creăm noi ramuri din ea. Dacă împingeți ceva în master care nu este testat sau care strică construcția, rupeți contractul social al echipei de dezvoltare și, în mod normal, vă simțiți destul de rău din această cauză. Fiecare ramură pe care o împingem are teste rulate pe ea și raportate în camera de chat, așa că, dacă nu le-ați rulat la nivel local, puteți pur și simplu să împingeți către o ramură tematică (chiar și o ramură cu o singură confirmare) de pe server și să așteptați ca Jenkins să vă spună dacă trece totul.

Ați putea avea o ramură deployed care să fie actualizată doar atunci când desfășurați, dar noi nu facem asta. Pur și simplu expunem SHA-ul desfășurat în prezent prin intermediul aplicației web propriu-zise și o curl dacă avem nevoie să facem o comparație.

#2 – creați ramuri descriptive din master

Când doriți să începeți să lucrați la ceva, creați o ramură cu nume descriptiv din ramura stabilă master. Câteva exemple din baza de cod GitHub în acest moment ar fi user-content-cache-key, submodules-init-task sau redis2-transition. Acest lucru are mai multe avantaje – unul este că, atunci când faceți fetch, puteți vedea subiectele la care au lucrat toți ceilalți. Un altul este că, dacă abandonați o ramură pentru o perioadă de timp și vă întoarceți la ea mai târziu, este destul de ușor să vă amintiți care a fost.

Acest lucru este plăcut pentru că, atunci când mergem la pagina cu lista de ramuri GitHub, putem vedea cu ușurință la ce ramuri s-a lucrat recent și aproximativ cât de multă muncă au pe ele.

Lista ramurilor Github

Este aproape ca o listă de caracteristici viitoare cu starea actuală aproximativă. Această pagină este minunată dacă nu o folosiți – vă arată doar ramurile care au o muncă unică pe ele în raport cu ramura selectată în prezent și le ordonează astfel încât cele la care s-a lucrat cel mai recent să fie în partea de sus. Dacă devin foarte curios, pot face clic pe butonul „Compare” (Compară) pentru a vedea care este lista reală unificată de diferențe și confirmări care este unică pentru acea ramură.

Atunci, în momentul în care scriu aceste rânduri, avem 44 de ramuri în depozitul nostru cu muncă neamestecată în ele, dar pot vedea, de asemenea, că doar aproximativ 9 sau 10 dintre ele au fost împinse în ultima săptămână.

#3 – push to named branches constantly

O altă mare diferență față de git-flow este că noi facem push to named branches pe server în mod constant. Din moment ce singurul lucru de care trebuie să ne facem griji cu adevărat este master din punct de vedere al implementării, împingerea pe server nu încurcă pe nimeni și nu confundă lucrurile – tot ceea ce nu este master este pur și simplu ceva la care se lucrează.

De asemenea, ne asigură că munca noastră este întotdeauna salvată în caz de pierdere a laptopului sau de defecțiune a hard disk-ului. Mai important, ne pune pe toți în comunicare constantă. Un simplu „git fetch” vă va oferi practic o listă TODO a ceea ce fiecare lucrează în prezent.

$ git fetchremote: Counting objects: 3032, done.remote: Compressing objects: 100% (947/947), done.remote: Total 2672 (delta 1993), reused 2328 (delta 1689)Receiving objects: 100% (2672/2672), 16.45 MiB | 1.04 MiB/s, done.Resolving deltas: 100% (1993/1993), completed with 213 local objects.From github.com:github/github * charlock-linguist -> origin/charlock-linguist * enterprise-non-config -> origin/enterprise-non-config * fi-signup -> origin/fi-signup 2647a42..4d6d2c2 git-http-server -> origin/git-http-server * knyle-style-commits -> origin/knyle-style-commits 157d2b0..d33e00d master -> origin/master * menu-behavior-act-i -> origin/menu-behavior-act-i ea1c5e2..dfd315a no-inline-js-config -> origin/no-inline-js-config * svg-tests -> origin/svg-tests 87bb870..9da23f3 view-modes -> origin/view-modes * wild-renaming -> origin/wild-renaming

De asemenea, permite tuturor să vadă, uitându-se la pagina GitHub Branch List, la ce lucrează ceilalți, astfel încât să le poată inspecta și să vadă dacă vor să ajute cu ceva.

#4 – deschideți o cerere de tragere în orice moment

GitHub are un sistem uimitor de revizuire a codului numit Pull Requests (cereri de tragere) despre care mă tem că nu știu destui oameni. Mulți oameni îl folosesc pentru munca open source – bifurcați un proiect, actualizați proiectul, trimiteți un pull request mentorului. Cu toate acestea, poate fi folosit cu ușurință și ca un sistem intern de revizuire a codului, ceea ce facem și noi.

De fapt, îl folosim mai mult ca o vizualizare a conversațiilor pe ramură decât ca un pull request. Puteți trimite pull requests de la o ramură la alta într-un singur proiect (public sau privat) în GitHub, așa că le puteți folosi pentru a spune „Am nevoie de ajutor sau de o revizuire a acestui lucru”, în plus față de „Vă rugăm să integrați acest lucru”.

Mesaj pr timpuriu

Aici îl puteți vedea pe Josh cc’ing Brian pentru revizuire și pe Brian venind cu un sfat pe una dintre liniile de cod. Mai jos îl putem vedea pe Josh recunoscând îngrijorările lui Brian și împingând mai mult cod pentru a le aborda.

mai multe discuții

În cele din urmă puteți vedea că suntem încă în faza de testare – aceasta nu este încă o ramură pregătită pentru desfășurare, folosim Pull Requests pentru a revizui codul cu mult înainte de a dori efectiv să îl unim în master pentru desfășurare.

Dacă sunteți blocat în progresul caracteristicii sau ramurii dvs. și aveți nevoie de ajutor sau de sfaturi, sau dacă sunteți un dezvoltator și aveți nevoie ca un designer să vă revizuiască munca (sau viceversa), sau chiar dacă aveți puțin sau deloc cod, dar câteva compuneri de capturi de ecran sau idei generale, deschideți o cerere de tragere. Puteți da cc oamenilor în sistemul GitHub adăugând un @ nume de utilizator, astfel încât, dacă doriți revizuirea sau feedback-ul unor persoane specifice, pur și simplu le dați cc în mesajul PR (așa cum ați văzut că a făcut Josh mai sus).

Acest lucru este grozav pentru că funcția Pull Request vă permite să comentați pe linii individuale în diff-ul unificat, pe comenzi individuale sau pe pull request în sine și atrage totul în linie într-o singură vizualizare de conversație.De asemenea, vă permite să continuați să faceți push la ramură, astfel încât, dacă cineva comentează că ați uitat să faceți ceva sau că există o eroare în cod, puteți să o remediați și să faceți push la ramură, GitHub va afișa noile comenzi în vizualizarea conversației și puteți continua să iterați pe o astfel de ramură.

Dacă ramura este deschisă de prea mult timp și simțiți că nu mai este sincronizată cu ramura principală, puteți fuziona ramura principală în ramura dvs. tematică și puteți continua. Puteți vedea cu ușurință în discuția de tip pull request sau în lista de confirmări când a fost ultima dată când ramura a fost adusă la zi cu „master”.

master merge

Când totul este cu adevărat și cu adevărat făcut pe ramură și simțiți că este gata de implementare, puteți trece la următorul pas.

#5 – fuzionează numai după revizuirea cererii de tip pull request

Nu facem pur și simplu munca direct pe master sau lucrăm pe o ramură tematică și o fuzionăm atunci când credem că este gata – încercăm să obținem aprobarea din partea altcuiva din companie. Acesta este, în general, un +1 sau un emoji sau un comentariu „:shipit:„, dar încercăm să convingem pe altcineva să se uite la el.

Comentariu de la shipit

După ce obținem acest lucru, iar ramura trece de CI, putem să o fuzionăm în master pentru implementare, care va închide automat Pull Request atunci când o împingem.

#6 – desfășurați imediat după revizuire

În cele din urmă, munca dvs. este gata și fuzionată în ramura master. Acest lucru înseamnă că, chiar dacă nu o distribuiți acum, oamenii se vor baza pe ea pentru o nouă lucrare, iar următoarea distribuire, care va avea loc probabil în câteva ore, o va împinge. Deci, din moment ce chiar nu vreți ca altcineva să împingă ceva ce ați scris și care strică lucrurile, oamenii tind să se asigure că este într-adevăr stabil atunci când este fuzionat și, de asemenea, oamenii tind să împingă propriile modificări.

Botul nostru de campfire, hubot, poate face implementări pentru oricare dintre angajați, astfel încât un simplu:

hubot depoy github to production

va implementa codul și un timp de repaus zero va reporni toate procesele necesare. Puteți vedea cât de frecvent este acest lucru la GitHub:

registrele noastre de foc de tabără

Puteți vedea 6 persoane diferite (inclusiv un tip de asistență și un designer) desfășurând de aproximativ 24 de ori într-o zi.

Am făcut acest lucru pentru ramuri cu un singur commit care conținea o modificare de o linie. Procesul este simplu, direct, scalabil și puternic. Puteți face acest lucru cu ramuri de caracteristici cu 50 de confirmări pe ele, care au durat 2 săptămâni, sau 1 confirmare care a durat 10 minute. Este un proces atât de simplu și de lipsit de fricțiune încât nu te deranjează faptul că trebuie să îl faci chiar și pentru 1 commit, ceea ce înseamnă că oamenii rareori încearcă să sară sau să ocolească procesul, cu excepția cazului în care modificarea este atât de mică sau nesemnificativă încât pur și simplu nu contează.

Este un proces incredibil de simplu și puternic. Cred că majoritatea oamenilor ar fi de acord că GitHub are o platformă foarte stabilă, că problemele sunt rezolvate rapid, dacă apar vreodată, și că noile caracteristici sunt introduse într-un ritm rapid. Nu există niciun compromis în ceea ce privește calitatea sau stabilitatea, astfel încât să putem obține mai multă viteză sau simplitate sau mai puțin proces.

Concluzie

Git în sine este destul de complex de înțeles, a face fluxul de lucru pe care îl folosești cu el mai complex decât este necesar înseamnă pur și simplu să adaugi mai multă încărcătură mentală în ziua tuturor. Întotdeauna aș pleda pentru folosirea celui mai simplu sistem posibil care să funcționeze pentru echipa dvs. și să faceți acest lucru până când nu mai funcționează și apoi să adăugați complexitate doar dacă este absolut necesar.

Pentru echipele care trebuie să facă lansări formale pe un interval mai lung de timp (de la câteva săptămâni la câteva luni între lansări) și să poată face corecturi la cald și ramuri de întreținere și alte lucruri care apar din cauza livrărilor atât de rare, git-flow are sens și aș pleda cu tărie pentru utilizarea sa.

Pentru echipele care au creat o cultură de expediere, care împing la producție în fiecare zi, care testează și implementează în mod constant, aș pleda pentru alegerea a ceva mai simplu precum GitHub Flow.

.

Leave a Reply