0b10

Github è stato lanciato nel 2008. Se la tua carriera di ingegneria del software, come la mia, non è più vecchia di Github, allora Git potrebbe essere l’unico software di controllo della versione che tu abbia mai usato. Mentre le persone a volte si lamentano della sua ripida curva di apprendimento ointerfaccia non intuitiva, Git è diventato il go-to di tutti per il controllo della versione. Il sondaggio per sviluppatori 2015 di InStack Overflow, il 69,3% degli intervistati ha utilizzato Git,quasi due volte quanti hanno utilizzato il secondo sistema di controllo della versione più popolare, Subversion.1 Dopo 2015, Stack Overflow ha smesso di chiedere agli sviluppatori i sistemi di controllo della versione che usano, forse perché Git era diventato così popolare che la domanda non era interessante.

Git stesso non è molto più vecchio di Github. Linus Torvalds ha rilasciato il primoversione di Git nel 2005. Anche se oggi gli sviluppatori più giovani potrebbero avere un momento difficileconceiving di un mondo in cui il termine” software di controllo della versione ” non significava più o meno solo Git, un mondo del genere esisteva non molto tempo fa. C’erano molti ofalternatives da scegliere. Gli sviluppatori open source preferivano Subversion, le imprese e le società di videogiochi utilizzavano Perforce (alcuni lo fanno ancora), mentre il progetto del kernel di Lux si basava notoriamente su un sistema di controllo della versione chiamato Bitkeeper.

Alcuni di questi sistemi, in particolare BitKeeper, potrebbero sentirsi familiari a un utente youngGit trasportato indietro nel tempo. La maggior parte non lo farebbe. BitKeeper a parte, i sistemi versioncontrol precedenti a Git funzionavano secondo un paradigma fondamentalmentedifferent. In una tassonomia offerta da Eric Sink, autore di VersionControl per esempio, Git è un sistema di controllo di versione di terza generazione, mentre la maggior parte dei predecessori di Git, i sistemi popolari negli 1990 e nei primi 2000,sono sistemi di controllo di versione di seconda generazione.2 Dove sono distribuiti sistemi di controllo di terza generazioneversione, i sistemi di controllo di seconda generazione sono centralizzati. Hai quasi certamente sentito Git descritto come un sistema di controllo della versione “distribuito” prima. Non ho mai capito bene la distinzione distribuita/centralizzata, almeno non fino a quando non ho installato e sperimentato con un sistema di controllo della versione centralizzato di seconda generazione.

Il sistema che ho installato era CVS. CVS, abbreviazione di Concurrent Versions System, erail primissimo sistema di controllo della versione di seconda generazione. È stato anche il sistema di controllo della versione più popolare per circa un decennio fino a quando non è stato sostituito in 2000by Subversion. Anche allora, Subversion doveva essere “CVS ma migliore”, che sottolinea solo come i CV dominanti fossero diventati durante gli 1990.

CVS è stato sviluppato per la prima volta nel 1986 da uno scienziato informatico olandese di nome Dick Grune,che era alla ricerca di un modo per collaborare con i suoi studenti su un compilerproject.3 CVS era inizialmente poco più di una raccolta di scriptswrapping shell RCS (Revision Control System), un sistema di controllo della versione di prima generazione che Grune voleva migliorare. RCS funziona secondo un modello pessimisticlocking, il che significa che non ci sono due programmatori in grado di lavorare su un singolo file atonce. Per modificare un file, devi prima chiedere a RCS un blocco esclusivosul file, che mantieni fino a quando non hai finito di modificare. Se qualcun altro lo ègià modificando un file che devi modificare, devi aspettare. CVS migliorato su RC e ha inaugurato la seconda generazione di sistemi di controllo della versione scambiando il modello di bloccoessimistico per uno ottimista. I programmatori potrebbero ora modificare lo stesso file allo stesso tempo, fondendo le loro modifiche e risolvendo qualsiasi conflitto. (Brian Berliner, un ingegnere che in seguito ha assunto il progetto CVS, ha scritto un documento molto leggibile sulle innovazioni di CVS nel 1990.)

In questo senso, CVS non era poi così diverso da Git, che funziona anche secondo un modello ottimistico. Ma è lì che finiscono le somiglianze. Infatti, quando Linus Torvalds stava sviluppando Git, uno dei suoi principi guida era WWCVSND, o ” Cosa non farebbe CVS.”Ogni volta che era in dubbio su una decisione, si sforzava di scegliere l’opzione che non era stata scelta nella progettazione DICV.4 Quindi, anche se CVS precede Git di oltre un decennio, ha influenzato Git come una sorta di modello negativo.

Mi è piaciuto molto giocare con CVS. Penso che non ci sia modo migliore per capire perché la natura distribuita di Git è un tale miglioramento rispetto a ciò che è venuto prima. Quindi vi invito a venire con me in un viaggio emozionante andspend i prossimi dieci minuti della tua vita imparare a conoscere un pezzo di softwarenobody ha utilizzato negli ultimi dieci anni. (Vedi correzione.)

Per iniziare con CVS

Le istruzioni per l’installazione di CVS possono essere trovate nella pagina homepage del progetto. Su macOS, puoi installare CVS Usandohomebrew.

Poiché CVS è centralizzato, distingue tra l’universo lato client e l’universo lato server in un modo che qualcosa come Git non lo fa. La distinzione non è così pronunciata che ci sono diversi eseguibili. Ma inorder per iniziare a utilizzare CVS, anche sul proprio computer, dovrai configurare il backend di CVS.

Il backend CVS, l’archivio centrale per tutto il codice, è chiamato repository.Mentre in Git avresti in genere un repository per ogni progetto, in CVSIL repository contiene tutti i tuoi progetti. C’è un repository centrale foreverything, anche se ci sono modi per lavorare con solo un progetto alla volta.

Per creare un repository locale, si esegue il comando init. Lo faresti da qualche parte globale come la tua home directory.

$ cvs -d ~/sandbox init

CVS consente di passare le opzioni al comandocvs stesso o al sottocomando init. Le opzioni che appaiono dopo il comandocvs sono di natura globale, mentre le opzioni che appaiono dopo il sottocomando sono specifiche per thesubcommand. In questo caso, il flag -d è globale. Qui capita di dire a CVSwhere che vogliamo creare il nostro repository, ma in generale il flag -d punta alla posizione del repository che vogliamo usare per ogni data azione. Si può betedious per fornire il-d bandiera per tutto il tempo, in modo che ilCVSROOT environmentvariable può essere impostato invece.

Dato che stiamo lavorando localmente, abbiamo appena passato un percorso per il nostro argomento-d, ma avremmo anche potuto includere un nome host.

Il comando crea una directory chiamata sandbox nella directory home. Se si elencano i contenuti di sandbox, troverete che contiene un altro directorycalled CVSROOT. Questa directory, da non confondere con environmentvariable, contiene file amministrativi per il repository.

Congratulazioni! Hai appena creato il tuo primo repository CVS.

Controllo del codice

Diciamo che hai deciso di mantenere una lista dei tuoi colori preferiti. Sei una persona artisticamente incline ma estremamente smemorata. Digita la tua lista di colori e salvala come un file chiamatofavorites.txt:

blueorangegreendefinitely not yellow

Supponiamo anche che tu abbia salvato il tuo file in una nuova directory chiamata colors. Ora ti piacerebbe mettere la tua lista di colori preferiti sotto il controllo della versione, perché tra cinquant’anni sarà interessante guardare indietro e vedere comei tuoi gusti sono cambiati nel tempo.

Per farlo, dovrai importare la tua directory come nuovo CVSproject. Puoi farlo usando il comandoimport :

$ cvs -d ~/sandbox import -m "" colors colors initialN colors/favorites.txtNo conflicts created by this import

Qui stiamo specificando la posizione del nostro repository con il -d flagagain. Gli argomenti rimanenti vengono passati al sottocomandoimport. Dobbiamo fornire un messaggio, ma qui non ne abbiamo davvero bisogno, quindi l’abbiamo lasciato in bianco. L’argomento successivo,colors, specifica il nome della nostra nuova directory nel repository; qui abbiamo appena usato lo stesso nome della directory in cui ci troviamo.Gli ultimi due argomenti specificano rispettivamente il tag fornitore e il tag rilascio.Parleremo più di tag in un minuto.

Hai appena tirato il tuo progetto “colors” nel repository CVS. Ci sono diversi modi per portare il codice in CVS, ma questo è il metodo raccomandato da Pragmatic Version Control UsingCVS, il libro PragmaticProgrammer su CVS. Ciò che rende questo metodo un po ‘ imbarazzante è che devi controllare il tuo lavoro fresco, anche se hai già una directory colors. Invece di usare quella directory, andrai adeliminarlo e quindi controllare la versione di cui CVS è già a conoscenza:

$ cvs -d ~/sandbox co colorscvs checkout: Updating colorsU colors/favorites.txt

Questo creerà una nuova directory, chiamata anche colors. In questa directory troverai il tuo file originalefavorites.txt insieme a una directory chiamataCVS. La directoryCVS è fondamentalmente l’equivalente di CVS della directory.git in ogni repository Git.

Apportare modifiche

Preparatevi per un viaggio.

Proprio come Git, CVS ha unstatus sottocomando:

Questo è dove le cose iniziano a sembrare estranee. CVS non ha oggetti di commit. Inthe sopra, c’è qualcosa chiamato “Identificatore di commit”, ma questo potrebbe essere solo un’edizione relativamente recente—nessuna menzione di un “Identificatore di commit” appare inPragmatic Version Control Usando CVS, che è stato pubblicato nel 2003. (The lastupdate to CVS was released in 2008.5)

Mentre con Git si parla della versione di un file associato a commit45de392, in CVS i file vengono versionati separatamente. La prima versione del tuofile è la versione 1.1, la prossima versione è 1.2 e così via. Quando i rami sono coinvolti, vengono aggiunti numeri extra, quindi potresti finire con qualcosa come 1.1.1.1 sopra, che sembra essere l’impostazione predefinita nel nostro caso anche se non abbiamo creato alcun ramo.

Se si dovesse eseguire cvs log (equivalente a git log) in un progetto con lotsof file e commit, si vedrebbe una cronologia individuale per ogni file. Puoi avere un file alla versione 1.2 e un file alla versione 1.14 nello stesso progetto.

Andiamo avanti e apportare una modifica alla versione 1.1 del nostrofavorites.txt file:

 blue orange green+cyan definitely not yellow

Una volta effettuata la modifica, possiamo eseguirecvs diffper vedere cosa CVS pensa di aver fatto:

CVS riconosce che abbiamo aggiunto una nuova riga contenente il colore “ciano” al file. (In realtà, dice che abbiamo apportato modifiche al file “RCS”; puoi vedere che thatCVS non è mai sfuggito completamente alla sua associazione originale con RCS.) Il diff che stiamo mostrando è il diff tra la copia di favorites.txt nella nostra directory di lavoro e la versione 1.1.1.1 memorizzata nel repository.

Per aggiornare la versione memorizzata nel repository, dobbiamo commit thechange. In Git, questo sarebbe un processo a più fasi. Dovremmo mettere in scena il cambiamento in modo che appaia nel nostro indice. Poi avremmo commesso il cambiamento. Infine, per rendere la modifica visibile a chiunque altro, dovremmo spingere il commit fino al repository di origine.

In CVS, tutte queste cose accadono quando si eseguecvs commit. CVS raggruppa tutte le modifiche che può trovare e le mette nel repository:

Sono così abituato a Git che questo mi sembra terrificante. Senza un’opportunityto stage changes, qualsiasi vecchia cosa che hai toccato nel tuo working directorymight finisce come parte del repository pubblico. Hai passivo-aggressivamenterescrivere la funzione mal implementata di un collega per necessità catartica, senza mai intenderlo sapere? Peccato, ora pensa che tu sia un coglione. Non puoi anche modificare i tuoi commit prima di spingerli, poiché un commit è una spinta. Ti piace spendere 40 minuti ripetutamente eseguendo git rebase -i fino a quando la tua cronologia localcommit scorre come la derivazione di una prova matematica? Scusa, non puoi farlo qui, e tutti scopriranno che in realtà non scrivi prima i tuoi test.

Ma ora capisco anche perché così tante persone trovano Git inutilmente complicato.Secvs commit è quello a cui eri abituato, allora sono sicuro che la messa in scena e i pushingchanges ti sembrerebbero un lavoro inutile.

Quando le persone parlano di Git come sistema “distribuito”, questa è principalmente la differenza che intendono. In CVS, non è possibile effettuare commit localmente. Un commit è un invio di codice al repository centrale, quindi non è qualcosa che puoi fare senza una connessione. Tutto quello che hai localmente è la tua directory di lavoro. In Git, hai un repository locale a tutti gli effetti, quindi puoi fare commit tutto il giorno anche se disconnesso. E puoi modificare quei commit, revert, branch, andcherry pick quanto vuoi, senza che nessun altro debba saperlo.

Poiché i commit erano un affare più grande, gli utenti CVS spesso li rendevano raramente.I commit conterrebbero tutte le modifiche che oggi potremmo aspettarci di vedere nella richiesta di pull aten-commit. Ciò era particolarmente vero se i commit attivavano un CIbuild e una suite di test automatizzata.

Se ora eseguiamo cvs status, possiamo vedere che abbiamo una nuova versione del nostro file:

Fusione

Come menzionato sopra, in CVS puoi modificare un file che qualcun altro sta già modificando. Questo è stato il grande miglioramento di CVS su RCS. Cosa succede quando hai bisogno di rimettere insieme le tue modifiche?

Diciamo che hai invitato alcuni amici ad aggiungere i loro colori preferiti ala tua lista. Mentre stanno aggiungendo i loro colori, si decide che non longerlike il colore verde e rimuoverlo dalla lista.

Quando vai a commettere le tue modifiche, potresti scoprire che CVS nota aproblem:

Sembra che i tuoi amici abbiano prima commesso le loro modifiche. Quindi la tua versione difavorites.txt non è aggiornata con la versione nel repository. Se esegui cvs status, vedrai che la tua copia locale di favorites.txt è version1.2 con alcune modifiche locali, ma la versione del repository è 1.3:

Puoi eseguirecvs diffper vedere esattamente quali sono le differenze tra 1.2 e1.3:

Sembra che ai nostri amici piaccia davvero il rosa. In ogni caso, hanno modificato una parte diversa del file di quella che abbiamo, quindi le modifiche sono facili da unire. CVScan farlo per noi quando si esegue cvs update, che è simile a 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

Se ora di dare un’occhiata a favorites.txt troverete che ha beenmodified per includere le modifiche che i tuoi amici apportate al file. Anche i tuoi cambiamenti sono ancora lì. Ora sei libero di impegnare il file:

Il risultato finale è quello che otterrai in Git eseguendo git pull --rebase. Yourchanges sono stati aggiunti in cima alle modifiche dei tuoi amici. Non c’è ” mergecommit.”

A volte, le modifiche allo stesso file potrebbero essere incompatibili. Se i tuoi amici avessero cambiato ” verde “in” oliva”, ad esempio, ciò sarebbe in conflitto con yourchange rimuovendo del tutto” verde”. Nei primi giorni di CVS, questo era exactlythe tipo di caso che ha causato la gente a preoccuparsi che CVS non era sicuro; Il blocco messimistico di RCS assicurava che un caso del genere non potesse mai sorgere. Ma CVSgarantisce la sicurezza assicurandosi che i cambiamenti di nessuno vengano sovrascritti automaticamente. Devi dire a CVS quale cambiamento vuoi continuare ad andare avanti, quindi quando eseguicvs update, CVS contrassegna il file con entrambe le modifiche nello stesso modo in cui Git rileva un conflitto di unione. È quindi necessario modificare manualmente il file e scegliere la modifica che si desidera mantenere.

La cosa interessante da notare qui è che i conflitti di unione devono essere risolti prima di poter eseguire il commit. Questa è un’altra conseguenza della centralizzazione di CVS nature.In Git, non devi preoccuparti di risolvere le fusioni finché non spingi i commit che hai localmente.

Tag e rami

Poiché CVS non ha oggetti di commit facilmente indirizzabili, l’unico modo per raggruppareuna raccolta di modifiche è contrassegnare un particolare stato della directory di lavoro con atag.

Creare un tag è semplice:

$ cvs tag VERSION_1_0cvs tag: Tagging .T favorites.txt

In seguito sarai in grado di restituire i file a questo stato eseguendo cvs updatee inserendo il tag nel-r bandiera:

$ cvs update -r VERSION_1_0cvs update: Updating .U favorites.txt

Poiché è necessario un tag per riavvolgere a uno stato di directory di lavoro precedente, CVS incoraggia un sacco di tag preventivi. Prima dei refactors principali, ad esempio, è possibile creare un tag BEFORE_REFACTOR_01 che è possibile utilizzare in seguito se il fattore è andato storto. Le persone hanno anche usato i tag se volevano generare differenze a livello di progetto. Fondamentalmente, tutte le cose che facciamo abitualmente oggi con commithashes devono essere anticipate e pianificate con CVS, dal momento che avevi bisogno di avere già i tag disponibili.

I rami possono essere creati in CVS, una sorta di. I rami sono solo un particolare tipo oftag:

$ cvs rtag -b TRY_EXPERIMENTAL_THING colorscvs rtag: Tagging colors

Che crea solo il ramo (in piena vista di tutti, tra l’altro), in modo youstill bisogno di passare a utilizzando cvs update:

$ cvs update -r TRY_EXPERIMENTAL_THING

I comandi di cui sopra di interruttore sulla nuova filiale in corrente workingdirectory, ma Pragmatico di Controllo di Versione con CVS in realtà consiglia di youcreate una nuova directory che conterrà il nuovo ramo. Presumibilmente i suoi autori hanno trovatopassare le directory più facilmente che cambiare rami in CVS.

Il controllo di versione pragmatico che utilizza CVS consiglia inoltre di non creare branchesoff di un ramo esistente. Raccomandano solo di creare rami dal ramo principale, che in Git è noto come master. In generale, la ramificazione eraconsiderato un’abilità CVS “avanzata”. In Git, è possibile avviare un nuovo ramo perquasi qualsiasi motivo banale, ma in CVS la ramificazione è stata in genere utilizzata solo quando è veramente necessario, ad esempio per i rilasci.

Un ramo potrebbe in seguito essere unito di nuovo nella linea principale usando cvs update e il flag -j :

$ cvs update -j TRY_EXPERIMENTAL_THING

Grazie per le storie di commit

Nel 2007, Linus Torvalds ha parlato di Git su Google. Git era molto nuovo allora, quindi il discorso era fondamentalmente un tentativo di persuadere una stanza piena di programmatori skeptical che dovrebbero usare Git, anche se Git era così diverso da qualsiasi cosa allora disponibile. Se non avete già visto il discorso, Ihighly vi incoraggio a guardarlo. Linus è un oratore divertente, anche se henever non riesce ad essere il suo sé sfacciato. Fa un ottimo lavoro nello spiegare perchéil modello distribuito di controllo della versione è migliore di quello centralizzato. Molte delle sue critiche sono riservate in particolare ai CV.

Git è uno strumento complesso. Imparare può essere un’esperienza brillante. Ma sono anche continuamente stupito dalle cose che Gitcan fa. In confronto, CVS è semplice e diretto, anche se spesso unableto fare molte delle operazioni che ora diamo per scontato. Tornare indietro e utilizzare CVSfor un po ‘ è un ottimo modo per trovare se stessi con un nuovo apprezzamento per la potenza e la flessibilità di forGit. Illustra bene perché capire lo sviluppo di software di historyof può essere così vantaggioso-raccogliendo e riesaminando gli attrezzi di obsolete Gli insegnerà volumi sul perché dietro gli attrezzi che usetoday.

Se ti è piaciuto questo post, più simile esce ogni quattro settimane! Seguire @ TwoBitHistory su Twitter o iscriversi al feed RSS per assicurarsi di sapere quando un nuovo post è fuori.

Correzione

Mi è stato detto che ci sono molte organizzazioni, in particolare le organizzazioni avversarie al rischio che fanno cose come make medical device software, che usano ancora i Vs. I programmatori di queste organizzazioni hanno sviluppato piccoli trucchi per aggirare le limitazioni di CVS, come creare un nuovo ramo per quasi everychange per evitare di impegnarsi direttamente su HEAD. (Grazie a Michael Kohne forpointing questo fuori.)

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *