Docsity
Docsity

Prepara i tuoi esami
Prepara i tuoi esami

Studia grazie alle numerose risorse presenti su Docsity


Ottieni i punti per scaricare
Ottieni i punti per scaricare

Guadagna punti aiutando altri studenti oppure acquistali con un piano Premium


Guide e consigli
Guide e consigli


Introduzione a GIT: perché è così utilizzato, Sbobinature di Ingegneria del Software

Introduzione a Git: funzionamento e comandi principali

Tipologia: Sbobinature

2021/2022

Caricato il 12/09/2022

Vittorio_92
Vittorio_92 🇮🇹

4.5

(8)

26 documenti

1 / 10

Toggle sidebar

Questa pagina non è visibile nell’anteprima

Non perderti parti importanti!

bg1
Capitolo 1
Git, sistema per il controllo delle versioni
1.1 Sistemi di controllo delle versioni
IVersion Control system ci permettono di monitorare i cambiamenti effettuati su in file nel tempo; in modo tale da
vedere il cambiamento rispetto alle vecchie versioni. Il controllo della versione è possibile effettuarlo con qualsiasi tipo
di file: testo, immagini, codice ma, è utilizzato principalmente da programmatori per tenere aggiornate le versione dei
programmi
Isistemi di controllo delle versioni, ci permettono di:
Riconvertire il file in una versione precedente o un intero progetto alla versione precedente
Rivedere i cambiamenti fatti nel tempo
Vedere le modifiche fatte su un file e, da parte di chi così da individuare chi ha portato al cambiamento e, magari
ha introdotto un problema o un bug
Effettuare un operazione di rinomina per ogni possibile file, non è la scelta più giusta e, soprattutto può portare ad
introdurre errori; perciò si è pensato di automatizzare queste operazioni introducendo un sistema che ci permette di
controllare le versioni dei file. Il tutto, fatto in modo molto semplice e, non costoso dal punto di vista computazione e
di memoria
Inizialmente, i sistemi che effettuavano il controllo delle versioni erano locali, detti local VCSs, utilizzavano un piccolo
database locale che teneva traccia dei cambiamenti delle versioni dei file. Questo però, limitava il controllo della versione
in locale. Si è passato perciò, col tempo, ad avere un sistema di controllo della versione basato su un server centrale
dove, le versioni sono condivise tra tutti gli utenti del server. Portando a delle conseguenze:
Pro:
Ognuno può vedere cosa gli altri stanno facendo
L’amministratore ha una visione ampia del progetto
Le uniche versioni che si andranno a caricare sono quelle presenti nel database
Contro:
È tutto centralizzato quindi, essendo centralizzato tutto in un singolo punto può portare a problematiche,
ad esempio in caso di problemi al server o problemi in generale, mancanza di rete
Si è passato per ciò a sviluppare dei sistemi di controllo delle versioni che sono distribuiti:distributed version
controll system. Ciò che li caratterizza è il fatto di andare a fare una copia completa dei file sulla nostra macchina
locale, di ciò che si trova all’interno del database.
Ogni volta che si accede al database, sulla propria macchina si andrà a copiare automaticamente l’ultima versione
presente in esso; in questo modo tutti possono lavorare insieme parallelamente sull’ultima versione e, essendo che
ognuno ha la sua copia locale, anche in caso di guasto del database, è quasi impossibile che qualcuno non abbia in
locale una delle ultime versioni, mantenendo comunque una ridondanza dei file
1
pf3
pf4
pf5
pf8
pf9
pfa

Anteprima parziale del testo

Scarica Introduzione a GIT: perché è così utilizzato e più Sbobinature in PDF di Ingegneria del Software solo su Docsity!

Capitolo 1

Git, sistema per il controllo delle versioni

1.1 Sistemi di controllo delle versioni

I Version Control system ci permettono di monitorare i cambiamenti effettuati su in file nel tempo; in modo tale da vedere il cambiamento rispetto alle vecchie versioni. Il controllo della versione è possibile effettuarlo con qualsiasi tipo di file: testo, immagini, codice ma, è utilizzato principalmente da programmatori per tenere aggiornate le versione dei programmi I sistemi di controllo delle versioni, ci permettono di:

  • Riconvertire il file in una versione precedente o un intero progetto alla versione precedente
  • Rivedere i cambiamenti fatti nel tempo
  • Vedere le modifiche fatte su un file e, da parte di chi così da individuare chi ha portato al cambiamento e, magari ha introdotto un problema o un bug

Effettuare un operazione di rinomina per ogni possibile file, non è la scelta più giusta e, soprattutto può portare ad introdurre errori; perciò si è pensato di automatizzare queste operazioni introducendo un sistema che ci permette di controllare le versioni dei file. Il tutto, fatto in modo molto semplice e, non costoso dal punto di vista computazione e di memoria

Inizialmente, i sistemi che effettuavano il controllo delle versioni erano locali, detti local VCSs, utilizzavano un piccolo database locale che teneva traccia dei cambiamenti delle versioni dei file. Questo però, limitava il controllo della versione in locale. Si è passato perciò, col tempo, ad avere un sistema di controllo della versione basato su un server centrale dove, le versioni sono condivise tra tutti gli utenti del server. Portando a delle conseguenze:

  • Pro:
    • Ognuno può vedere cosa gli altri stanno facendo
    • L’amministratore ha una visione ampia del progetto
    • Le uniche versioni che si andranno a caricare sono quelle presenti nel database
  • Contro:
    • È tutto centralizzato quindi, essendo centralizzato tutto in un singolo punto può portare a problematiche, ad esempio in caso di problemi al server o problemi in generale, mancanza di rete

Si è passato per ciò a sviluppare dei sistemi di controllo delle versioni che sono distribuiti: distributed version controll system. Ciò che li caratterizza è il fatto di andare a fare una copia completa dei file sulla nostra macchina locale, di ciò che si trova all’interno del database. Ogni volta che si accede al database, sulla propria macchina si andrà a copiare automaticamente l’ultima versione presente in esso; in questo modo tutti possono lavorare insieme parallelamente sull’ultima versione e, essendo che ognuno ha la sua copia locale, anche in caso di guasto del database, è quasi impossibile che qualcuno non abbia in locale una delle ultime versioni, mantenendo comunque una ridondanza dei file

1.2 Git

Git, è uno dei principali sistemi di controllo distribuiti.

Git, ci offre la possibilità di lavorare in modo semplice ed efficace sul controllo delle versioni. Ciò lo contraddistingue è la possibilità di fare branching: " creazione di un ramo di sviluppo parallelo, da cui si può operare senza modificare il ramo d’origine. A questo punto, attraverso il merging è possibile riunire i rami i quello di origine"

1.2.1 Delta function

La delta function è una funzione che ci consente di calcolare per ogni file le differenze che ci sono tra una versione ed un altra, consentendoci così di aggiornare all’interno di una versione solo i file che sono stati aggiornati e, di mantenere il riferimento agli altri file che non sono stati aggiornati in quella versione. Si memorizza quindi, una lista delle differenze per ogni file

Questa soluzione, non usata da Git, è funzionale ma, presenta alcune problematiche infatti, nel caso in cui si vuole ritornare ad una versione precedente risulta problematico in quanto, avendo la lista delle differenze, per tornare alla versione precedente bisognerà fare dei calcoli computazionali.

Soluzione adottata da Git

Git, pensa ai dati in un modo differente e, si basa su quelli che sono chiamai snapshot. Ad ogni versione si crea un’istantanea dell’ultima versione. I file modificati vengono aggiornati mentre, per i file non modificati, non sono ricopiati in memoria locale nuovamente ma, vi è un link che ci porta a dove il file è già memorizzato localmente Nelle nuove versioni abbiamo la copia dei file modificati mentre, teniamo i riferimenti a ciò che non è stato modificato

Figura 1.1: Esempio Snapshot di Git

In pratica, ogni operazione avviene sulla copia che abbiamo localmente e, solo una volta che si è sicuri dei cambiamenti effettuati si carica la nuova versione sul server. Tutti gli altri utenti, avranno la versione aggiornata quando riapriranno il server. Il fatto che Git usi i file locali per effettuare le sue operazioni fa si che queste sembrino istantanee e, c’è solo una piccola porzione di operazioni che non puoi fare se si offline. Quindi l’avere tutto localmente ci permette anche di vedere i cambiamenti fatti tra una versione e l’altra, solo calcolando localmente le differenze

1.2.2 Check sum

Meccanismo che associa ad ogni file un codice alfanumerico composto da 40 caratteri esadecimali. L’utilizzo del meccanismo di check fa si che tutte le operazioni svolte sono in Git, siano operazioni sicure dunque, ogni volta prima di effettuare le operazioni viene svolto un controllo sul codice e, anche sulla somma dei caratteri del codice. Grazie a questo codice è inoltre possibile lavorare sui file direttamente attraverso quest’ultimo

  • Push and Pull: termini utilizzati per rappresentare il download e l’upload dalla git directory. Push li metto in git directory, pull prendo dalla git directory la versione che è presente. È consigliabile prima di fare una operazione di push, farne prima una di pull
  • Branching: utilizzato per dire che ci stiamo separando dalla linea principale di sviluppo ma, comunque, con- tinuano a lavorare su quel progetto, senza fare modifiche sulla linea principale. Si crea un ramo parallelo di sviluppo che ci permette comunque di lavorare sul progetta ma, che le sue modifiche non riflettano sulla versione principale finché non si effettua una operazione di merging
  • Merging: ci permette di riunirmi dopo un branching sulla linea principale di sviluppo

1.2.6 Branching e Merging

Git, favorisce e vuole incoraggiare ad avere multipli rami di sviluppo, interamente indipendenti fra di loro Permettendo di fare cose come:

  • Cambio di contesto senza attrito. Posso cambiare di ramo senza problemi
  • I rami s possono basare sui ruoli infatti, potremmo avere un ramo dove si ha il prodotto finito, un secondo ramo dove si sviluppa e un terzo ramo dove si effettua il testing
  • Creare nuovi rami per introdurre nuove funzionalità. Se queste hanno buon esito, è possibile effettuare il merge introducendo le nuove funzionalità nel ramo principale
  • Creazione di rami per la sperimentazione. I rami possono essere tranquillamente cancellati senza essere salvati sul database; se la sperimentazione non va buon fine, nessuno se ne accorge perché è tutto locale finché non viene fatta una commit

L’idea alla base del branchig e merging è quella di avere dei rami per avere diversi livelli di stabilità del progetto:

  • Ramo master: contiene il codice stabile, nonché la versione finale del prodotto sviluppata fino a quel momento
  • Ramo develop: contiene il codice in fase di sviluppo
  • Ramo topic: è ramo di sperimentazione per creare e testare particolari funzioni del progetto

1.3 Comandi di Git

1.3.1 git config

Il comando serve a configurare la propria identità all’interno di Git. Si specificano l’username e, l’email che ne specificano la nostra identità dunque, è un operazione che va fatta solo una volta al’inizio

$ git config –global user.name "name" $ git config –global user.email [email protected] Utilizzando la parola –global vogliamo specificare questa identità per qualsiasi cosa facciamo su git altrimenti, possiamo usare un identità diversa per uno specifico progetto, eseguendo i comandi senza la scritta –global all’interno del progetto

Controllare le impostazioni

Se vogliamo controllare la configurazione dei settaggi fatti e, visualizzarli, dobbiamo usare il comando: git config –list

Se, invece, vogliamo vedere solo uno specifico parametro bisogna dara il comando: git config < key >

1.3.2 git help

Il comando serve ad aiutarci per capire o, avere della documentazione aggiuntiva di determinati comandi di git. Serve ad aiutarci nell’uso di git; per fare ciò si possono eseguire diversi comandi:

  1. git help < verb >
  2. git < verb > –help

In base al comando specificato in < verb > si aprirà una pagina locale che conterrà le specifiche che riguardano il comando

1.3.3 Creazione di una repository

Una repositoy all’interno di Git si può creare in due diversi modi:

  1. Prendere una repository locale e trasformarla in una git repositoy ad esempio utilizzando Git Hub
  2. Clonare una git repository già esistente, presa da qualche altra parte

Trasformare una cartella in una git repository

Figura 1.2: Esempio inizializzazione di una repository

Per inizializzare la cartella, una volta messi nel percorso di quest’ultima, bisogna eseguire il comando git init. Per aggingere dei file uso il comando git add ., per poi fare la commit git commit Per trasformare la cartella in una git repository

Figura 1.3: Esempio trasformazione della cartella in una git repository da poter condividere

I comandi git push e git pull sono i comandi per effettuare il push ed il pull dei file nella git repository

Clonare una git repositoy già esistente

Si utilizza il comando: git clone < url > L’url corrisponde alla repository che vogliamo clonare

1.3.4 Comandi per i file

  • git add < file > Per aggiungere all’area di staging e renderlo tracked come: un file untracked rendendolo tracked oppure, per inserire i file modificati all’interno dell’area di staging
  • git diff Ci permette di vedere esattamente le differenze che ci sono tra i file modificati ma, che non sono ancora nell’area di staging. Ci permette di vedere esattamente cosa è cambiato all’interno del file e, non solo quali file sono cambiati

1.4 Branching

Il branching è stata la funzionalità che ha reso così funzionale e utilizzato git. Incoraggiando il flusso di lavoro a fare continuamente branching e merging

Ciò è reso possibile grazie all’uso dei puntatori che utilizza git infatti, i dati sono memorizzati come una seria di snapshot e, quando si esegue una commit, git memorizza gli oggetti della commit in modo tale che essi abbiamo il puntatore allo snapshot. Gli oggetti di una commit sono memorizzati come un albero nella git repository. La struttura ad albero punta agli oggetti della commit che sono chiamati blobs ognuno con il suo puntatore. Quindi, la commit punta allo snapshot, alla commit precedente e, punta allo stesso modo all’albero del progetto che punta ai blobs degli oggetti dove, ogni pezzo ha il suo checksum per verificare la correttezza

Ciò che si fa con la creazione di un nuovo ramo è creare un nuovo puntatore dinamico che, punta ad una commit Il ramo principale è chiamato master e, punta all’ultima commit effettuata; ogni volta che si effettua una nuova commit il puntatore del ramo master si muove automaticamente. Comunque, il ramo master non è un ramo speciale ma, è un ramo come tutti gli altri tuttavia, esso è creato quando si inizializza la repository e, nessuno solitamente lo modifica

Per aggiungere un ramo si utilizza il comando: git branch < nomeRamo >. Esso, inizialmente punterà alla commit corrente Ma, esiste un altro puntatore speciale, chiamato HAED, che punterà al ramo locale corrente. Ci dice su che ramo l’utente si trova a lavorare. Bisogna stare attenti, perché quando si crea un nuovo ramo il puntatore HAED non verrà spostato ma, rimane sul ramo che puntava in precedenza. Per verificare su quale ramo punta HAED si utlizza il comando git log –decorate

Cambiare il puntatore HAED

Per modificare il ramo a cui punta HAED, si utilizza il comando: git chechout < nomeRamo >. Il puntatore cambierà e, i file nella working direcoty verranno cambiati. Da ora le commit effettuate verranno fatte dal ramo puntato da HAED

Figura 1.5: Esempio branching

1.5 Merging

Il merging serve per unire due rami in uno solo creando una nuova versione. Per fare il merging tra due rami bisogna eseguire i comandi: git checkout < ramoSuCuiFareLunione > "Il checkout viene fatto sul ramo su cui si vuole far unire l’altro" git merge < ramoDaUnire >

Esistono due tipi di merging

  1. Fast forward. Il puntatore del ramo su cui vogliamo a far riconvergere, si sposta semplicemente in avanti; questo perché il ramo che vogliamo unire è antenato diretto del ramo su cui effettuiamo la merge

Figura 1.6: Esempio merging fast forward

A questo punto potremo andare ad eliminare il ramo che non ci servirà più

1.5.1 Eliminazione di un ramo

Dopo aver effettuato un operazione di merging è possibile eliminare un ramo senza andare in contro a nessuna conseguenza. Per eliminare un ramo, utilizziamo il comando: git branch -d < nomeRamoDaEliminare >

Capitolo 2

Debbugging e Profiling

2.1 Debbugging

Il debbugging è un processo che utilizziamo per trovare gli errori all’interno del codice del nostro software. Consiste nell’esplorare il codice del nostro programma durante la sua esecuzione per capirne il corretto funzionamento; si visualizza come vengono eseguite e, se vengono eseguite singole istruzioni o gruppi di istruzioni. Perciò fare debugging è molto utile ai fini di identificare le parti problematiche del nostro codice così da correggerle

2.1.1 Debbugger

Per fare il debbugging, si utilizza il debugger, ormai presente in ogni IDE, è un software che ci permette a tempo di esecuzione di interagire dinamicamente con il software in esecuzione, così che lo sviluppatore possa osservare il codice e le variabili durante l’esecuzione.

Il controllo dinamico è effettuato grazie ai breakpoints, si comunicare al debugger di congelarsi all’esecuzione di in una certa linea di codice; quella segnalata dal breackpoint. Una volta che il programma è stato stoppato, lo sviluppatore può osservare lo sviluppo del codice e delle variabili e, osservarne il funzionamento fino a quel punto. Da lì, grazie a dei comandi può decidere se continuare con l’esecuzione e, in che modo; ad esempio, può scegliere se far riprendere l’esecuzione fine al prossimo breackpoint oppure, avanzare linea per linea

2.2 Profiling

L’attività di profiling è un’attività che ci permette di monitorare le attività del nostro programma, con lo scopo di analizzare le performance del nostro programma. Grazie all’aiuto di un software che effettua profiling, possiamo vedere durante l’esecuzione quanta CPU usa il programma o quanta memoria utilizza e, molte altre cose.

L’utilizzo del profiling è molto utile per risolvere le problematiche di performance di un programma, grazie al quale possiamo andare a fondo del problema e, ottimizzare il programma sia dal punto di vista temporale, sia dal punto di vista di occupazione della memoria grazie ai risultati che escono fuori dal profiling