Skip to content
Snippets Groups Projects
Verified Commit 0982c21f authored by Marco Aceti's avatar Marco Aceti
Browse files

Add 'Lezione 05'

parent 82edd428
No related branches found
No related tags found
No related merge requests found
---
layout: post
title: "[05] Software Configuration Management"
date: 2022-10-17 14:40:00 +0200
toc: true
---
# SCM
Le soluzioni di Software Configuration Management nascono da problemi complessi purtroppo molto comuni nel mondo dello sviluppo software, come:
- pubblicare un _hotfix_ su una versione precedente a quella in cui si sta sviluppando. Può essere difficile localizzare le versioni vecchie, modificarle e rimappare le modifiche sulle versioni nuove;
- condividere lavori con altri gestendo accessi contemporanei e conflitti;
- stabilire la responsabilità di ciascuna linea di codice.
Il Software Configuration Management è l'insieme di pratiche che hanno l'obiettivo di rendere sistematico il processo di sviluppo, tenendo traccia dei cambiamenti in modo che il prodotto sia in ogni instante in uno stato (_configurazione_) ben definito.
## Storia
Il Configuration Management negli anni '50 nell'ambito dell'industria aerospaziale.
Alla fine degli anni '70 inizia ad essere applicato all'ingegneria del software.
Gli oggetti di cui si controlla l'evoluzione sono detti _configuration item_ o _artifact_ (manufatti, solitamente file).
Dunque l'SMC ci permette di controllare le revisioni degli _artifact_ e il risultato di tali revisioni,questo processo è molto utile per la generazione di un prodotto a partire da una configurazione ben determinata.
### Manufatti
Gli _"oggetti"_ di cui si controlla l'evoluzione sono detti _configuration item_ o manufatti; generalmente sono file.
Se si cambia nome a un file è come eliminarne uno e partire da zero con uno nuovo.
Originariamente i tool tracciavano i file indipendentemente, senza un senso logico (una _configurazione_) comune.
{% responsive_image path: 'assets/05_configuration-management.png' %}
- anni '80: strumenti locali (SCCS, ...)
- anni '90: strumenti client-server centralizzati (CVS, subversion, ...)
- anni '00: strumenti distribuiti peer-to-peer (git, mercurial, bazaar, ...)
Git nasce da un'esigenza di Linus Torvalds con il kernel Linux.
## Centralizzato vs decentralizzato
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/4XpnKHJAok8" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
Il mondo open source preferisce un approccio decentralizzato al version control. Perché?
- è possibile lavorare offline;
- è molto più veloce, perché la rete non fa più da _bottleneck_;
- supporta diversi modi di lavorare:
- simil centralizzato: un repository viene considerato "di riferimento";
- due peer che collaborano direttamente;
- gerarchico a più livelli (kernel Linux).
Non c'è sincronizzazione automatica, ma ci sono comandi espliciti per fare _merge_ tra repository remote.
In Git, per via della sua struttura modulare, è possibile utilizzare il proprio algoritmo _merge_ rispetto a quelli già inclusi.
### Cosa tracciare?
Qualunque sistema si usi, occorre prendere decisioni importanti che influenzano la replicabilità della produzione.
- Si traccia l'evoluzione anche di componenti fuori dal nostro controllo (librerie, compilatori)?
- Si archiviano i file che sostitusicono il prodotto (eseguibile, ecc...)?
La risposta ad entrambe queste domande è __no__, perché è scomodo, anti economico, costoso...
Questo porta però problemi, perché non c'è perfetta replicabilità.
## Meccanismo di base
Ogni cambiamento è regolato da:
- __check-out__: dichiara la volontà di lavorare partendo da una particolare revisione di un manufatto (o di una configurazione di diversi manufatti);
- __check-in__ (o __commit__): dichiara la volonta di registrarne una nuova (spesso chiamata change-set).
Queste operazioni vengono attivate rispetto a un _repository_.
Scambio di dati tra il repository (che contiene tutte le configurazioni) e il workspace (l'ambiente in cui si trova nel filesystem).
Solitamente ho un repository e $$n$$ workspace, uno per ogni ambiente dove sto lavorando.
### Repository
La repository mantiene:
- date
- etichette
- versioni
- diramazioni (branches)
- ecc...
Per risparmiare spazio, le repository salvano solo le differenze tra una versione e l'altra.
In realtà, Git non fa così, perché usa link simbolici: fare il _checkout_ di una specifica versione è instantaneo.
Le repository possono essere centralizzate o distribuite.
Nei sistemi di versioning distribuiti c'è il concetto di __hashing__, in modo da identificare file uguali anche se in posizioni diverse.
Per confrontare storie diverse si utilizzano gli hash dei file e delle directory.
### Accesso concorrente
Quando il repository è condiviso da un gruppo di lavoro, nasce il problema di gestirne l'accesso concorrente.
Esistono due modelli:
- __modello _'pessimistico'___ (RCS): prevedo il possibile conflitto assicurandomi che chi lavora sia l'unico con l'accesso in scrittura. Funziona solo in ambienti centralizzati, nell'open source non può funzionare.
- __modello _'ottimistico'___ (CVS): il sistema si disinteressa del problema e fornisce supporto per le attività di _merge_ di change-set paralleli potenzialmente conflittuali.
Il modello ottimistico può essere regolato con i branch: l'attività di _merge_ è quindi fondamentale.
CVS/Subversion scoraggiava i branch, Git li rende facili e li incoraggia.
In Git, l'uso dei branch è talmente comune che a volte è necessario introdurre delle politiche (come GitFlow) sul loro utilizzo.
# Git
{% responsive_image path: 'assets/05_git-schema.png' %}
In figura, possiamo osservare 4 _livelli_ ordinati:
- __working directory__ (WD): rappresenta la _configurazione_ della directory di lavoro sul filesystem - esiste indipendentemente da Git.
Può essere vista come l'unione dei _tracked_ and _untracked_ files;
- __index__ (o __area di staging__): insieme dei _tracked_ files da Git.
- ($$n$$?) __local repository__: insieme delle modifiche committate e relativo storico.
- ($$n$$) __remote repository__: branch remoto; è possibile avere sia più branch per progetto remoto che più progetti remoti configurati.
Il termine ___repository___ è abbastanza _misleading_, perché è comunemente associato ad un progetto mentre in questa astrazione a livelli corrisponde di fatto a un __branch__.
Il passaggio tra un livello e l'altro non è mai automatico, ma è sempre esplicitato da un'operazione.
## Operazioni di base
È consigliata la lettura di [Git Cheatsheet](http://ndpsoftware.com/git-cheatsheet.html).
{% responsive_image path: 'assets/05_git-commits.png' %}
Per ogni branch c'è un puntatore all'ultimo commit di tale branch.
L'HEAD punta all'ultimo commit in cui siamo: normalmente corrisponde al puntatore del branch corrente; quando non è così siamo in una situazione di _HEAD scollegato_.
È utile potersi spostare tra i commit per controllare revisioni precedenti, ma in caso di nuovi commit è importante creare un nuovo branch per poterci riferire ad esse.
### git commit - record changes to the repository
Il comando git commit ci permette di _salvare_ del contenuto dall'index al branch locale.
Dopo aver creato il commit, l'`HEAD` e il puntatore al branch corrente puntano al nuovo commit.
Anche il contenuto dell'index equivale al contenuto del commit.
{% responsive_image path: 'assets/05_git-commit.png' %}
#### -\-amend
Con l'opzione -\-amend è possibile rimpiazziare facilmente l'ultimo commit con uno nuovo.
{% responsive_image path: 'assets/05_git-commit-amend.png' %}
### git switch - switch branches
Il comando git switch ha un sottoinsieme delle funzionalità del comando git checkout ed è più semplice da utilizzare.
Permette di passare a un nuovo branch semplicemente modificando l'HEAD (e di conseguenza il contenuto dell'index e dei file).
{% responsive_image path: 'assets/05_git-checkout.png' %}
### git merge - join two or more development histories together
Il comando git merge è utile per unire branch (o più in generale alberi) insieme.
Se i due branch non sono divergenti, il merge avviene in modo banale con un _fast-forward_: nessun ulteriore commit verrà cambiato, verrà solo modificato il puntatore del branch e l'HEAD.
Per forzare la creazione di un merge di commit (in GitFlow è apprezzato) occorre utilizzare l'opzione `--no-ff`.
In tutti gli altri casi, il merge può concludersi con successo oppure possono avvenire conflitti.
Per risolverli, Git ci proporrà un'interfaccia simile alla seguente.
<<<<<<< yours:sample.txt
Conflict resolution is hard;
let's go shopping.
=======
Git makes conflict resolution easy.
>>>>>>> theirs:sample.txt
Una volta risolti tutti i conflitti è sufficiente commitare le modifiche concludendo quindi il merge.
{% responsive_image path: 'assets/05_git-merge.png' %}
### git reset - reset current HEAD to the specified state
Il comando git reset reimposta il contenuto dei file nell'_index_ (e, opzionalmente con l'opzione `--hard` nella WD) all'ultimo commit puntato da HEAD o ad un altro commit.
{% responsive_image path: 'assets/05_git-reset.png' %}
# Sofware Configuration Management
Le soluzioni di Software Configuration Management nascono da problemi complessi purtroppo molto comuni nel mondo dello sviluppo software, come:
- pubblicare un _hotfix_ su una versione precedente a quella in cui si sta sviluppando. Può essere difficile localizzare le versioni vecchie, modificarle e rimappare le modifiche sulle versioni nuove;
- condividere lavori con altri gestendo accessi contemporanei e conflitti;
- stabilire la responsabilità di ciascuna linea di codice.
Il Software Configuration Management è l'insieme di pratiche che hanno l'obiettivo di rendere sistematico il processo di sviluppo, tenendo traccia dei cambiamenti in modo che il prodotto sia in ogni instante in uno stato (_configurazione_) ben definito.
- [**Storia**](./01_storia.md)
- [**Meccanismo di base**](./02_meccanismo.md)
- [**git**](./03_git.md)
# Storia
Il Configuration Management negli anni '50 nell'ambito dell'industria aerospaziale.
Alla fine degli anni '70 inizia ad essere applicato all'ingegneria del software.
Gli oggetti di cui si controlla l'evoluzione sono detti _configuration item_ o _artifact_ (manufatti, solitamente file).
Dunque l'SMC ci permette di controllare le revisioni degli _artifact_ e il risultato di tali revisioni,questo processo è molto utile per la generazione di un prodotto a partire da una configurazione ben determinata.
## Manufatti
Gli _"oggetti"_ di cui si controlla l'evoluzione sono detti _configuration item_ o manufatti; generalmente sono file.
Se si cambia nome a un file è come eliminarne uno e partire da zero con uno nuovo.
Originariamente i tool tracciavano i file indipendentemente, senza un senso logico (una _configurazione_) comune.
![Definizione di configurazione](/assets/05_configuration-management.png)
- anni '80: strumenti locali (SCCS, ...)
- anni '90: strumenti client-server centralizzati (CVS, subversion, ...)
- anni '00: strumenti distribuiti peer-to-peer (git, mercurial, bazaar, ...)
git nasce da un'esigenza di Linus Torvalds con il kernel Linux.
## Centralizzato vs decentralizzato
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/4XpnKHJAok8" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
Il mondo open source preferisce un approccio decentralizzato al version control. Perché?
- è possibile lavorare offline;
- è molto più veloce, perché la rete non fa più da _bottleneck_;
- supporta diversi modi di lavorare:
- simil centralizzato: un repository viene considerato "di riferimento";
- due peer che collaborano direttamente;
- gerarchico a più livelli (kernel Linux).
Non c'è sincronizzazione automatica, ma ci sono comandi espliciti per fare _merge_ tra repository remote.
In git, per via della sua struttura modulare, è possibile utilizzare il proprio algoritmo _merge_ rispetto a quelli già inclusi.
# Meccanismo di base
Ogni _cambiamento_ è regolato da:
- __check-out__: dichiara la volontà di lavorare partendo da una particolare revisione di un manufatto (o di una configurazione di diversi manufatti);
- __check-in__ (o __commit__): dichiara la volonta di registrarne una nuova (spesso chiamata change-set).
Queste operazioni vengono attivate rispetto a un _repository_.
Scambio di dati tra il repository (che contiene tutte le configurazioni) e il workspace (l'ambiente in cui si trova nel filesystem).
Solitamente ho un repository e \\( n \\) workspace, uno per ogni ambiente dove sto lavorando.
## Repository
La repository mantiene:
- date
- etichette
- versioni
- diramazioni (branches)
- ecc...
Per risparmiare spazio, le repository salvano solo le differenze tra una versione e l'altra.
In realtà, Git non fa così, perché usa link simbolici: fare il _checkout_ di una specifica versione è instantaneo.
Le repository possono essere centralizzate o distribuite.
Nei sistemi di versioning distribuiti c'è il concetto di __hashing__, in modo da identificare file uguali anche se in posizioni diverse.
Per confrontare storie diverse si utilizzano gli hash dei file e delle directory.
### Cosa tracciare?
Qualunque sistema si usi, occorre prendere decisioni importanti che influenzano la replicabilità della produzione.
- Si traccia l'evoluzione anche di componenti fuori dal nostro controllo (librerie, compilatori)?
- Si archiviano i file che sostitusicono il prodotto (eseguibile, ecc...)?
La risposta ad entrambe queste domande è __no__, perché è scomodo, anti economico, costoso...
Questo porta però problemi, perché non c'è perfetta replicabilità.
## Accesso concorrente
Quando il repository è condiviso da un gruppo di lavoro, nasce il problema di gestirne l'accesso concorrente.
Esistono due modelli:
- __modello _'pessimistico'___ (RCS): prevedo il possibile conflitto assicurandomi che chi lavora sia l'unico con l'accesso in scrittura. Funziona solo in ambienti centralizzati, nell'open source non può funzionare.
- __modello _'ottimistico'___ (CVS): il sistema si disinteressa del problema e fornisce supporto per le attività di _merge_ di change-set paralleli potenzialmente conflittuali.
Il modello ottimistico può essere regolato con i branch: l'attività di _merge_ è quindi fondamentale.
CVS/Subversion scoraggiava i branch, Git li rende facili e li incoraggia.
In Git, l'uso dei branch è talmente comune che a volte è necessario introdurre delle politiche (come GitFlow) sul loro utilizzo.
\ No newline at end of file
# git
![Schema git](/assets/05_git-schema.png)
In figura, possiamo osservare 4 _livelli_ ordinati:
- __working directory__ (WD): rappresenta la _configurazione_ della directory di lavoro sul filesystem - esiste indipendentemente da git.
Può essere vista come l'unione dei _tracked_ and _untracked_ files;
- __index__ (o __area di staging__): insieme dei _tracked_ files da git.
- (\\(n\\)?) __local repository__: insieme delle modifiche committate e relativo storico.
- (\\(n\\)) __remote repository__: branch remoto; è possibile avere sia più branch per progetto remoto che più progetti remoti configurati.
Il termine ___repository___ è abbastanza _misleading_, perché è comunemente associato ad un progetto mentre in questa astrazione a livelli corrisponde di fatto a un __branch__.
Il passaggio tra un livello e l'altro non è mai automatico, ma è sempre esplicitato da un'operazione.
## Operazioni di base
È consigliata la lettura di [git Cheatsheet](http://ndpsoftware.com/git-cheatsheet.html).
![Puntatori commit git](/assets/05_git-commits.png)
Per ogni branch c'è un puntatore all'ultimo commit di tale branch.
L'HEAD punta all'ultimo commit in cui siamo: normalmente corrisponde al puntatore del branch corrente; quando non è così siamo in una situazione di _HEAD scollegato_.
È utile potersi spostare tra i commit per controllare revisioni precedenti, ma in caso di nuovi commit è importante creare un nuovo branch per poterci riferire ad esse.
### `git commit` &mdash; _record changes to the repository_
Il comando git commit ci permette di _salvare_ del contenuto dall'index al branch locale.
Dopo aver creato il commit, l'`HEAD` e il puntatore al branch corrente puntano al nuovo commit.
Anche il contenuto dell'index equivale al contenuto del commit.
![Puntatori commit git 2](/assets/05_git-commit.png)
#### `--amend`
Con l'opzione -\-amend è possibile rimpiazziare facilmente l'ultimo commit con uno nuovo.
![git commit --amend](/assets/05_git-commit-amend.png)
### `git switch` &mdash; _switch branches_
Il comando git switch ha un sottoinsieme delle funzionalità del comando git checkout ed è più semplice da utilizzare.
Permette di passare a un nuovo branch semplicemente modificando l'HEAD (e di conseguenza il contenuto dell'index e dei file).
![git checkout](/assets/05_git-checkout.png)
### `git merge` &mdash; _join two or more development histories together_
Il comando git merge è utile per unire branch (o più in generale alberi) insieme.
Se i due branch non sono divergenti, il merge avviene in modo banale con un _fast-forward_: nessun ulteriore commit verrà cambiato, verrà solo modificato il puntatore del branch e l'HEAD.
Per forzare la creazione di un merge di commit (in gitFlow è apprezzato) occorre utilizzare l'opzione `--no-ff`.
In tutti gli altri casi, il merge può concludersi con successo oppure possono avvenire conflitti.
Per risolverli, git ci proporrà un'interfaccia simile alla seguente.
<<<<<<< yours:sample.txt
Conflict resolution is hard;
let's go shopping.
=======
git makes conflict resolution easy.
>>>>>>> theirs:sample.txt
Una volta risolti tutti i conflitti è sufficiente commitare le modifiche concludendo quindi il merge.
![git merge](/assets/05_git-merge.png)
### `git reset` &mdash; _reset current HEAD to the specified state_
Il comando git reset reimposta il contenuto dei file nell'_index_ (e, opzionalmente con l'opzione `--hard` nella WD) all'ultimo commit puntato da HEAD o ad un altro commit.
![git reset](/assets/05_git-reset.png)
......@@ -43,6 +43,11 @@
- [An empirical study of open-source and closed-source software products](./04_open-source/01_letteratura/04_empirical-study.md)
- [Sfide](./04_open-source/02_sfide.md)
- [Software Configuration Management](./05_scm/00_index.md)
- [Storia](./05_scm/01_storia.md)
- [Meccanismo di base](./05_scm/02_meccanismo.md)
- [git](./05_scm/03_git.md)
# 2. Progettazione e implementazione
# 3. Verifica e convalida
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment