Github a fost lansat în 2008. Dacă cariera dvs. de inginerie software, ca a mea, nu este mai veche decât Github, atunci Git poate fi singurul software de control al versiunii pe care l-ați folosit vreodată. În timp ce oamenii, uneori, grouse despre curba de învățare abruptă sauinterfață intuitivă, Git a devenit toată lumea pentru controlul versiunii. Sondajul dezvoltatorului InStack Overflow din 2015, 69,3% dintre respondenți au folosit Git,aproapede două ori mai mult decât a folosit cel de-al doilea cel mai popular sistem de control al versiunilor, Subversion.1 după 2015, Stack Overflow a încetat să mai întrebe dezvoltatorii despresistemele de control al versiunilor pe care le folosesc, poate pentru că Git devenise atât de popularcă întrebarea era neinteresantă.
Git în sine nu este mult mai vechi decât Github. Linus Torvalds a lansat primulversiune a Git în 2005. Deși astăzi dezvoltatorii mai tineri ar putea avea un timp greuconceperea unei lumi în care termenul „software de control al versiunii” nu a însemnat mai mult sau mai puțin doar Git, o astfel de lume nu a existat cu mult timp în urmă. Au fost o mulțime dealternative din care să alegi. Dezvoltatorii open source au preferat subversiunea, întreprinderile și companiile de jocuri video au folosit Perforce (unii încă o fac), în timp ce proiectul kernel-ului Linux s-a bazat faimos pe un sistem de control al versiunii numitbitkeeper.
unele dintre aceste sisteme, în special BitKeeper, s-ar putea simți familiare unui utilizator youngGit transportat înapoi în timp. Cele mai multe nu ar fi. BitKeeper deoparte, versiuneasistemele de control care au venit înainte de Git au funcționat în conformitate cu o paradigmă fundamentalădiferite. Într-o taxonomie oferită de Eric Sink, autorul VersionControl de exemplu, Git este un sistem de control al versiunilor de a treia generație, în timp ce majoritatea predecesorilor Git, sistemele populare în anii 1990 și începutul anilor 2000,sunt sisteme de control al versiunilor de a doua generație.2 În cazul în care sistemele de control al versiunilor de a treia generație sunt distribuite, sistemele de control al versiunilor de a doua generație sunt centralizate. Aproape sigur ați auzit Git descris ca un sistem de control al versiunii „distribuite” înainte. Nu am înțeles niciodată distincția distribuită/centralizată, cel puțin nu până când am instalat și am experimentat cu un sistem centralizat de control al versiunii de a doua generație.
sistemul pe care l-am instalat era CVS. CVS, prescurtare pentru sistemul de versiuni concurente, a fostprimul sistem de control al versiunilor din a doua generație. A fost, de asemenea, cel mai popular sistem de control al versiunilor timp de aproximativ un deceniu până când a fost înlocuit în 2000 de subversiune. Chiar și atunci, subversiunea trebuia să fie „CV-uri, dar mai bune”, ceea ce subliniază doar modul în care CV-urile dominante au devenit de-a lungul anilor 1990.CVS a fost dezvoltat pentru prima dată în 1986 de un informatician olandez pe nume Dick Grune,care căuta o modalitate de a colabora cu studenții săi la un proiect de compilator.3 CVS a fost inițial puțin mai mult decât o colecție de shell scriptswapping RCS (Revision Control System), un sistem de control al versiunii de primă generație pe care Grune a dorit să îl îmbunătățească. RCS funcționează conform unui pesimistmodel de blocare, ceea ce înseamnă că nici doi programatori nu pot lucra simultan pe un singur fișier. Pentru a edita un fișier, trebuie să cereți mai întâi RCS un blocaj exclusivpe fișier, pe care îl păstrați până când ați terminat editarea. Dacă altcineva estedespre editarea unui fișier pe care trebuie să îl editați, trebuie să așteptați. CV-urile s-au îmbunătățit pe RC-uri și au inaugurat a doua generație de sisteme de control al versiunilor prin tranzacționarea modelului de blocare pesimist pentru unul optimist. Programatorii ar putea edita acum același fișier în același timp, fuzionând modificările și rezolvând orice conflictmai târziu. (Brian Berliner, un inginer care a preluat ulterior proiectul CVS, a scris o lucrare foarte lizibilă despre inovațiile CVS în 1990.)
în acest sens, CVS nu era atât de diferit de Git, care funcționează și în conformitate cu un model optimist. Dar aici se termină asemănările. De fapt, când Linus Torvalds dezvolta Git, unul dintre principiile sale directoare a fostwwcvsnd, sau „ce nu ar face CVS.”Ori de câte ori avea îndoieli cu privire la o decizie,s-a străduit să aleagă opțiunea care nu fusese aleasă în proiectarea vehiculelor.4 deci, chiar dacă CV-urile precedă Git cu peste un deceniu, a influențat Git ca un fel de șablon negativ.
mi-a plăcut foarte mult să mă joc cu CV-urile. Cred că nu există o modalitate mai bună de a înțelege de ce natura distribuită a lui Git este o astfel de îmbunătățire față de ceea ce a venit înainte. Așadar, vă invit să veniți cu mine într-o călătorie interesantă și să petreceți următoarele zece minute din viața voastră învățând despre o bucată de software pe care nimeni nu a folosit-o în ultimul deceniu. (Vezi corecția.)
Noțiuni de bază cu CVS
instrucțiuni pentru instalarea CVS pot fi găsite pe pagina proiectului. Pe MacOS, puteți instala CV-uri folosindhomebrew.
deoarece CVS este centralizat, distinge între universul client-side și universul server-side într-un mod în care ceva de genul Git nu. Thedistincția nu este atât de pronunțată încât există diferite executabile. Dar pentru a începe să utilizați CVS, chiar și pe propria mașină, va trebui să configurați backend-ul TVs.
backend-ul CVS, magazinul central pentru tot codul dvs., se numește depozit.În timp ce în Git ați avea de obicei un depozit pentru fiecare proiect, În CV-uri magazia deține toate proiectele dvs. Există un depozit central pentrutotul, deși există modalități de a lucra doar cu un proiect la un moment dat.
pentru a crea un depozit local, executați comanda init
. Tu ar face thissomewhere global ca directorul de acasă.
$ cvs -d ~/sandbox init
CVS vă permite să treceți opțiunile fie la comanda cvs
în sine, fie la subcomandainit
. Opțiunile care apar după comanda cvs
Sunt innature globale, în timp ce opțiunile care apar după Subcomandă sunt specifice thesubcommand. În acest caz, steagul -d
este global. Aici se întâmplă să spunem Cvsunde vrem să creăm depozitul nostru, dar, în general, -d
semnalizeazălocația depozitului pe care dorim să îl folosim pentru orice acțiune dată. Se poate betedious pentru a furniza-d
Pavilion tot timpul, astfel încâtCVSROOT
environmentvariable poate fi setat în schimb.
Din moment ce lucrăm local, tocmai am trecut o cale pentru argumentul nostru-d
, dar am fi putut include și un nume de gazdă.
comanda creează un director numitsandbox
în directorul de acasă. Dacă listați conținutul sandbox
, veți găsi că acesta conține un alt directornumit CVSROOT
. Acest director, care nu trebuie confundat cu mediulvariabil, deține fișiere administrative pentru depozit.
Felicitări! Tocmai ați creat primul depozit CVS.
Verificarea Codului
Să presupunem că ați decis să păstrați o listă cu culorile preferate. Ești o persoană înclinată artistic, dar extrem de uitată. Tastați listof culori și salvați-l ca un fișier numit favorites.txt
:
blueorangegreendefinitely not yellow
Să presupunem, de asemenea, că ați salvat fișierul într-un nou director numitcolors
. Acum doriți să puneți lista de culori preferate sub controlul versiunii, deoarece peste cincizeci de ani va fi interesant să priviți înapoi și să vedeți cumgusturile dvs. s-au schimbat în timp.
pentru a face acest lucru, va trebui să importați directorul dvs. ca un nou CVSproject. Puteți face acest lucru folosind comandaimport
:
$ cvs -d ~/sandbox import -m "" colors colors initialN colors/favorites.txtNo conflicts created by this import
aici specificăm locația depozitului nostru cu-d
flagagain. Argumentele rămase sunt transmise subcomandei import
. Trebuie să transmitem un mesaj, dar aici nu avem nevoie de unul, așa că l-am lăsat în urmă. Următorul argument,colors
, specifică numele noului nostru director din depozit; aici tocmai am folosit același nume ca directorul în care ne aflăm.Ultimele două argumente specifică eticheta furnizorului și, respectiv, eticheta de lansare.Vom vorbi mai multe despre etichete într-un minut.
tocmai ați tras proiectul „culori” în depozitul CVS. Există câteva modalități diferite de a aduce codul în CV-uri, dar aceasta este metoda recomandată de Pragmatic Version Control UsingCVS, cartea PragmaticProgrammer despre CV-uri. Ceea ce face ca această metodă să fie puțin ciudată este că tuapoi trebuie să vă verificați munca proaspătă, chiar dacă aveți deja un director existent colors
. În loc să utilizați acel director, veți mergeștergeți-l și apoi verificați versiunea despre care CVS știe deja:
$ cvs -d ~/sandbox co colorscvs checkout: Updating colorsU colors/favorites.txt
aceasta va crea un nou director, numit și colors
. În acest director veți găsi fișierul original favorites.txt
împreună cu un director numitCVS
. Directorul CVS
este practic echivalentul CVS al directorului.git
în fiecare depozit Git.
efectuarea de modificări
pregătiți-vă pentru o călătorie.
la fel ca Git, CVS are unstatus
Subcomandă:
aici lucrurile încep să pară străine. CVS nu are comite obiecte. În cele de mai sus, există ceva numit „identificator de comitere”, dar acesta ar putea fidoar o ediție relativ recentă—nu apare nicio mențiune despre un „identificator de comitere” controlul versiunii pragmatice folosind CVS, care a fost publicat în 2003. (The lastupdate to CVS a fost lansat în 2008.5)
în timp ce cu Git ați vorbi despre versiunea unui fișier asociat cu commit45de392
, în fișierele CVS sunt versionate separat. Prima versiune a yourfile este versiunea 1.1, următoarea versiune este 1.2 și așa mai departe. Când ramurile sunt implicate, se adaugă numere suplimentare, astfel încât s-ar putea să ajungeți la ceva de genul 1.1.1.1
de mai sus, care pare a fi implicit în cazul nostru, chiar dacă nu am creat nicio ramură.
dacă ar fi să rulațicvs log
(echivalent cugit log
) într-un proiect cu fișiere lotsof și comiteri, veți vedea un istoric individual pentru fiecare fișier. S-ar putea să aveți un fișier la versiunea 1.2 și un fișier la versiunea 1.14 în același proiect.
Să mergem mai departe și să facem o modificare la versiunea 1.1 a fișierului nostru favorites.txt
:
blue orange green+cyan definitely not yellow
odată ce am făcut schimbarea, putem rulacvs diff
pentru a vedea ce crede CVS că am văzut:
CVS recunoaște că am adăugat o nouă linie care conține culoarea „cyan” la fișier. (De fapt, se spune că am făcut modificări la fișierul „RCS”; puteți vedea astacvs nu a scăpat niciodată pe deplin de asocierea sa inițială cu RCS.) Diferența pe care o afișăm este diferența dintre copia favorites.txt
din workingdirectory și versiunea 1.1.1.1 stocată în depozit.
pentru a actualiza versiunea stocată în depozit, trebuie să comitemschimbare. În Git, acesta ar fi un proces în mai multe etape. Ar trebui să organizăm schimbarea astfel încât să apară în indexul nostru. Apoi am comite schimbarea. În cele din urmă, pentru a face schimbarea vizibilă pentru oricine altcineva, ar trebui să împingem angajamentul până la depozitul de origine.
în CVS, toate aceste lucruri se întâmplă atunci când executați cvs commit
. CVS acoperă toate modificările pe care le poate găsi și le pune în depozit:
sunt atât de obișnuit să Git că acest lucru mi se pare terifiant. Fără o oportunitatepentru a organiza schimbări, orice lucru vechi pe care l-ați atins în directorul dvs. de lucrupoate ajunge ca parte a depozitului public. Ai fost pasiv-agresivscrie funcția prost implementată a unui coleg din necesitate cathartică, fără a intenționa niciodată să știe? Păcat, acum crede că ești un nesimțit. De asemenea, nu vă puteți edita comiterile înainte de a le împinge, deoarece o comitere este o împingere. Te bucuri să petreci 40 de minute rulând în mod repetat git rebase -i
până când Istoricul localcommit curge ca derivarea unei dovezi matematice? Îmi pare rău, nu poți face asta aici, și toată lumea va afla că de fapt nu scrii testele mai întâi.
dar acum înțeleg și de ce atât de mulți oameni consideră că Git este inutil de complicat.Dacă cvs commit
este ceea ce ați fost obișnuiți, atunci sunt sigur că punerea în scenă și împingereaschimbări te-ar lovi ca o corvoadă inutilă.
când oamenii vorbesc despre Git ca fiind un sistem „distribuit”, aceasta este în primul rând diferența pe care o înseamnă. În CVS, nu puteți face comiteri la nivel local. O comitere este asubmiterea codului în depozitul central, deci nu este ceva ce puteți face fără o conexiune. Tot ce ai la nivel local este directorul de lucru. În Git, aveți un depozit local cu drepturi depline, astfel încât să puteți face comiteri toată ziachiar și în timp ce este deconectat. Și puteți edita aceste comiteri, reveni, ramură, andcherry alege la fel de mult, după cum doriți, fără ca nimeni altcineva să știe.
deoarece comiterile au fost o afacere mai mare, utilizatorii CVS le-au făcut adesea rar.Comiterile ar conține la fel de multe schimbări ca astăzi ne-am putea aștepta să vedem în aten-commit pull request. Acest lucru a fost valabil mai ales dacă comiterile au declanșat un cibuild și o suită de testare automată.
dacă acum rulăm cvs status
, putem vedea că avem o nouă versiune a fișierului nostru:
fuzionând
după cum sa menționat mai sus, în CVS puteți edita un fișier pe care altcineva îl are dejaeditarea. Aceasta a fost marea îmbunătățire a CVS pe RCS. Ce se întâmplă când trebuieaduceți schimbările înapoi împreună?
Să presupunem că ați invitat niște prieteni să adauge culorile lor preferatelista ta. În timp ce își adaugă culorile, decideți că nu mai existăca culoarea verde și scoateți-o din listă.
când te duci să comită modificările, s-ar putea descoperi că CVS notificări aproblem:
se pare ca prietenii tai comis modificările lor în primul rând. Deci, versiunea dvs. defavorites.txt
nu este actualizată cu versiunea din depozit. Dacă yourun cvs status
, veți vedea că copia locală a favorites.txt
este version1.2 cu unele modificări locale, dar versiunea repository este 1.3:
puteți rulacvs diff
pentru a vedea exact care sunt diferențele dintre 1.2 și1.3:
se pare că prietenilor noștri le place foarte mult rozul. În orice caz, au editat o parte diferită a fișierului decât avem noi, astfel încât modificările sunt ușor de îmbinat. CVScan face asta pentru noi atunci când vom rula cvs update
, care este similar cu git pull
:
$ cvs updatecvs update: Updating .RCS file: /Users/sinclairtarget/sandbox/colors/favorites.txt,vretrieving revision 1.2retrieving revision 1.3Merging differences between 1.2 and 1.3 into favorites.txtM favorites.txt
dacă luați acum o privire la favorites.txt
, veți găsi că a fostmodificat pentru a include modificările pe care prietenii dvs. le-au făcut în fișier. Schimbările tale sunt încă acolo. Acum sunteți liber să comiteți fișierul:
rezultatul final este ceea ce veți obține în Git rulând git pull --rebase
. Modificările tale au fost adăugate pe lângă modificările prietenilor tăi. Nu există nici o „mergecommit.”
uneori, modificările la același fișier pot fi incompatibile. Dacă prietenii tăi ar fi schimbat „verde „în” măslin”, de exemplu, asta ar fi intrat în conflict cu schimbarea ta eliminând cu totul” verde”. În primele zile ale CVS, acest lucru a fost exacttipul de caz care a determinat oamenii să se îngrijoreze că CVS nu era sigur; Blocarea pesimistă a RCS a asigurat că un astfel de caz nu ar putea apărea niciodată. Dar Cvsgarantează siguranța asigurându-se că modificările nimănui nu sunt suprascrise automat. Trebuie să spuneți CVS ce schimbare doriți să continuați înainte, așa că atunci când executați cvs update
, CVS marchează fișierul cu ambele modificăriîn același mod în care face Git atunci când git detectează un conflict de îmbinare. Apoi trebuie să editați manual fișierul și să alegeți modificarea pe care doriți să o păstrați.
lucrul interesant de remarcat aici este că conflictele de îmbinare trebuie remediateînainte de a putea comite. Aceasta este o altă consecință a centralizării CV-urilor nature.In Git, nu trebuie să vă faceți griji cu privire la rezolvarea fuziuni până când împinge comitetele le-ați luat la nivel local.
Tag-uri și ramuri
deoarece CVS nu are ușor adresabile comite obiecte, singura modalitate de a groupa colecție de modificări este de a marca un anumit stat director de lucru cu atag.
crearea unei etichete este ușoară:
$ cvs tag VERSION_1_0cvs tag: Tagging .T favorites.txt
mai târziu veți putea returna fișierele în această stare rulândcvs update
șitrecând eticheta la-r
steag:
$ cvs update -r VERSION_1_0cvs update: Updating .U favorites.txt
deoarece aveți nevoie de o etichetă pentru a derula înapoi la o stare de director de lucru mai devreme, CVSencourages o mulțime de tagging preemptive. Înainte de refactori majore,de exemplu, s-ar putea crea un BEFORE_REFACTOR_01
tag-ul pe care le-ar putea folosi mai târziu, dacă thefactor a mers prost. Oamenii au folosit, de asemenea, etichete dacă au vrut să generezedif-uri la nivel de proiect. Practic, toate lucrurile pe care le facem în mod obișnuit astăzi cu commithashes trebuie să fie anticipate și planificate cu CVS, deoarece trebuia să aveți etichetele disponibile deja.
ramurile pot fi create în CV-uri, un fel de. Ramurile sunt doar un tip special detag:
$ cvs rtag -b TRY_EXPERIMENTAL_THING colorscvs rtag: Tagging colors
care creează doar ramura (în viziunea tuturor, apropo), așa că tot trebuie să treceți la ea folosindcvs update
:
$ cvs update -r TRY_EXPERIMENTAL_THING
comenzile de mai sus trec pe noua ramură din directorul de lucru curent, dar controlul versiunii pragmatice folosind CVs recomandă de fapt să creați un nou director pentru a ține noua ramură. Probabil că autorii săi au găsitcomutarea directoarelor mai ușoară decât comutarea ramurilor în CVS.
controlul Pragmatic al versiunii folosind CVS recomandă, de asemenea, crearea de ramificațiioff-ul unei sucursale existente. Ei recomandă crearea de sucursale numai în afara ramurii principale, care în Git este cunoscută sub numele de master
. În general, ramificarea a fostconsiderată o abilitate CVS” avansată”. În Git, s-ar putea să începeți o nouă sucursalăaproape orice motiv banal, dar în CVS ramificarea a fost utilizată de obicei numai atunci când este cu adevărat necesar, cum ar fi pentru lansări.
o ramură ar putea fi ulterior fuzionată înapoi în linia principală folosind cvs update
și -j
steag:
$ cvs update -j TRY_EXPERIMENTAL_THING
Vă mulțumim pentru istoricul comiterii
În 2007, Linus Torvalds a dat atalk despre Git la Google. Git era foarte nou atunci, așa că discuția a fost practic o încercare de a convinge o cameră plină de programatori sceptici că ar trebui să folosească Git, chiar dacă Git era atât de diferit de orice era disponibil atunci. Dacă nu ați văzut deja discuția, vă încurajez foarte mult să o urmăriți. Linus este un vorbitor distractiv, chiar dacă elnu reușește niciodată să fie sinele său obraznic. El face o treabă excelentă de a explica de cemodelul distribuit de control al versiunii este mai bun decât cel centralizat. O mare parte din criticile sale sunt rezervate în special CV-urilor.
Git este un instrument complex. Învățarea poate fi o experiență afrustrantă. Dar sunt, de asemenea, uimit continuu de lucrurile pe care le face Gitcan. În comparație, CVS este simplu și direct, deși adesea incapabil să facă multe dintre operațiunile pe care le luăm acum de la sine. Întoarcerea și utilizarea CV-urilor pentru o vreme este o modalitate excelentă de a vă găsi cu o nouă apreciere pentruputerea și flexibilitatea lui. Acesta ilustrează bine de ce înțelegerea istoriei dezvoltării de software poate fi atât de benefică—ridicarea și reexaminarea instrumentelor învechite vă vor învăța volume despre motivul din spatele instrumentelor pe care le folosim astăzi.
dacă ți-a plăcut acest post, mai mult ca acesta să iasă la fiecare patru săptămâni! Urmați @ TwoBitHistory pe Twitter sau abonați-vă la feed RSS pentru a vă asigura că știți când apare o nouă postare.
corecție
mi s-a spus că există multe organizații, în special organizații cu risc opus, care fac lucruri cum ar fi crearea de software pentru dispozitive medicale, care încă folosesc vehicule. Programatorii din aceste organizații au dezvoltat mici trucuri pentrulucrând în jurul limitărilor CV – urilor, cum ar fi crearea unei noi sucursale pentru aproape fiecare schimbare pentru a evita angajarea directă la HEAD
. (Mulțumesc lui Michael Kohne pentrupointing acest lucru.)