martedì 28 ottobre 2025

Git: Creazione di un Nuovo Branch

Quando si crea un nuovo branch in Git, in realtà non vengono duplicati file o directory, né viene generata una nuova copia del progetto.

Git si limita semplicemente a creare un nuovo puntatore (reference) a un commit esistente — un’operazione estremamente leggera e immediata.


1. Creazione di un Nuovo Branch

Per creare un nuovo branch denominato test, è sufficiente eseguire:
git branch Test
Questo comando crea un nuovo puntatore al commit corrente, ma non cambia il branch attivo.

In altre parole, il branch test viene creato, ma Git rimane ancora posizionato su master (o qualunque branch fosse attivo).

Branch Test
FIG 1 - Branch Test

Entrambi i branch, master e testing, puntano inizialmente allo stesso commit (40fb977).

Solo in seguito, quando si inizierà a lavorare su testing (con git switch Test o git checkout Test), i due percorsi inizieranno a divergere.



2. Il Ruolo di HEAD in Git

Per determinare su quale branch si stia lavorando, Git utilizza un puntatore speciale chiamato HEAD.

In Git, HEAD è un riferimento simbolico che punta al branch corrente.

Non va confuso con il concetto di HEAD in altri VCS (come Subversion o CVS), dove rappresenta una revisione remota.

Nel nostro esempio, dopo il comando git branch test, il puntatore HEAD rimane collegato a master (FIG 1).



3. Verifica dei Branch e del Puntatore HEAD

Per visualizzare la posizione dei vari branch rispetto ai commit, è possibile utilizzare il comando:

git log --oneline --decorate

git log
FIG 2 - git log

In questo caso, sia master che Test puntano al commit 5e1955b.

Il simbolo HEAD -> master indica che il branch attualmente attivo è master.


4. Comprendere la Leggerezza del Branching in Git

Una delle caratteristiche più potenti di Git è la leggerezza dei branch:

  • Ogni branch è semplicemente un file di testo di pochi byte che contiene l’hash del commit di riferimento.
  • Creare, eliminare o spostare un branch è quindi un’operazione quasi istantanea.
  • Non viene copiato alcun file, e la struttura fisica del progetto rimane invariata.

Questo approccio consente di:

  • creare rapidamente branch tematici (feature branches),
  • sperimentare nuove soluzioni senza rischiare di compromettere la linea principale di sviluppo,
  • integrare e fondere modifiche tramite merge o rebase in modo efficiente.


5. Best Practice
  • Usare nomi descrittivi per i branch, come feature/login-page o bugfix/api-timeout.
  • Creare branch specifici per funzionalità o bug, per mantenere il codice principale stabile.
  • Evitare di lavorare direttamente su master/main, specialmente nei progetti collaborativi.
  • Verificare frequentemente la posizione di HEAD con git status o git branch --show-current.
  • Eliminare i branch non più necessari con git branch -d <nome> per mantenere pulito il repository.



lunedì 27 ottobre 2025

Git: Branching. Introduzione

Il concetto di branching (ramificazione) è presente in quasi tutti i sistemi di controllo di versione (Version Control Systems – VCS).

In termini generali, creare un branch significa divergere dalla linea principale di sviluppo per proseguire il lavoro in modo indipendente, senza interferire con il codice stabile o condiviso.

Nella maggior parte dei VCS tradizionali, questa operazione risulta computazionalmente onerosa, in quanto comporta spesso la creazione di una copia fisica dell’intero albero dei sorgenti. Nei progetti di grandi dimensioni, ciò può implicare tempi di attesa considerevoli e un uso intensivo delle risorse.


Il Modello di Branching in Git

Git si distingue radicalmente da questo approccio.

Il suo sistema di branching è considerato una delle caratteristiche più innovative e determinanti dell’intero strumento — spesso definita la sua "killer feature".

La ragione principale di questa superiorità risiede nel fatto che, in Git, i branch sono entità estremamente leggere: si tratta di semplici puntatori (reference) a specifici commit della cronologia del repository.

Questo design permette di:

  • creare nuovi branch in modo quasi istantaneo,
  • passare da un branch all’altro in maniera immediata,
  • gestire e fondere (merge) rami multipli con grande efficienza.

Tali caratteristiche rendono Git non solo più performante, ma anche più flessibile nella gestione dei flussi di lavoro complessi.

Grazie alla leggerezza del modello, Git favorisce un uso intensivo e naturale del branching, incoraggiando sviluppatori e team a creare, unire e rimuovere branch anche più volte nel corso della stessa giornata.

Questo approccio incentiva una metodologia di sviluppo più sperimentale e iterativa, in cui ogni funzionalità, correzione o prova può essere isolata in un branch dedicato, riducendo i rischi di regressione e migliorando la qualità del codice.


Comprendere la Struttura dei Branch in Git

Per comprendere appieno il funzionamento del branching in Git, è necessario analizzare in dettaglio come Git gestisce e archivia i dati internamente.

1. Il Modello di Memorizzazione in Git

A differenza di molti altri sistemi di controllo di versione, Git non archivia i dati come sequenze di differenze incrementali (changeset o delta).

Invece, ogni commit rappresenta uno snapshot completo dello stato dei file al momento della conferma (commit).

Quando si esegue un commit, Git crea un oggetto commit che contiene:

  • Un puntatore (reference) allo snapshot del contenuto “staged” (nell’area di preparazione),
  • Il nome e l’email dell’autore,
  • Il messaggio di commit,
  • Uno o più puntatori ai commit genitori (parent commit)

2. Esempio Pratico: Creazione di un Primo Commit

Supponiamo di avere una directory con due file (leggimi.txt, main.cs ), che vengono aggiunti e poi confermati:

git add leggimi.txt main.cs
git commit -m "Initial commit"

Durante l’operazione di git add, Git:

  1. Calcola un checksum (SHA-1 hash) per ciascun file.
  2. Archivia la versione del file nel repository come blob.
  3. Aggiunge il riferimento di ogni blob all’area di staging.

Al momento del commit, Git:

  • calcola un checksum anche per la directory (creando un oggetto tree),
  • genera un oggetto commit che punta a tale tree,
  • registra i metadati (autore, messaggio, timestamp).

Il repository conterrà ora quattro oggetti:

  • 2 blob -> rappresentano il contenuto dei singoli file,
  • 1 tree -> struttura della directory e mapping tra nomi file e blob,
  • 1 commit -> metadati e riferimento al tree radice.
Commit, tree e blob
FIG 1 - Commit, tree e blob

3. Evoluzione della Cronologia dei Commit

Ogni nuovo commit aggiunge un nuovo oggetto commit con un puntatore al commit precedente.

In questo modo si crea una catena di commit, dove ogni nodo conosce il suo predecessore.

Questo modello garantisce integrità e tracciabilità, poiché ogni commit è referenziato crittograficamente.

Commit, Child, Parent
FIG 2 - Commit, Child, Parent


4. Il Ruolo dei Branch

Un branch in Git non è altro che un puntatore mobile e leggero a un commit specifico.

Il branch predefinito si chiama master (o main).

Ogni volta che si effettua un nuovo commit, il puntatore del branch si sposta automaticamente in avanti, aggiornandosi per indicare l’ultimo commit nella sequenza.

Il branch master non ha alcun comportamento speciale.

È un branch come tutti gli altri, creato semplicemente come default dal comando git init.

Master
FIG 3 - Master






giovedì 23 ottobre 2025

Git: Alias

Una delle funzionalità più pratiche e spesso sottovalutate di Git è la possibilità di definire alias personalizzati, ovvero abbreviazioni di comandi frequenti.

Questa caratteristica consente di semplificare e velocizzare l’utilizzo quotidiano del sistema di versionamento, migliorando la produttività e riducendo la possibilità di errore nella digitazione di comandi complessi.


Introduzione agli Alias

Git non effettua alcuna inferenza automatica sui comandi parziali: se si digita un comando incompleto, Git non tenta di indovinare quello corretto.

Per ovviare a questo limite, è possibile definire scorciatoie per qualsiasi comando, tramite l’opzione alias di git config.

Un alias viene creato associando una parola chiave a un comando Git.

Ad esempio:

git config --global alias.cm commit
git config --global alias.st status

Grazie a queste definizioni, i comandi Git possono essere digitati in forma abbreviata:

git cm al posto di git commit

git st al posto di git status

Alias commit
FIG 1 - Alias commit

Gli alias possono essere configurati a livello globale (--global, valido per tutti i repository dell’utente) o locale (solo per il repository corrente, omettendo --global).


Creare Alias Personalizzati

Gli alias non si limitano a sostituire comandi esistenti: possono anche essere utilizzati per definire nuovi comandi Git personalizzati, ovvero combinazioni di opzioni o scorciatoie operative che migliorano la produttività.

Ad esempio, per semplificare l’operazione di unstage di un file (ovvero la rimozione di un file dall’area di staging), si può creare un alias dedicato:

git config --global alias.unstage 'reset HEAD --'

Da questo momento in poi, i seguenti comandi diventeranno equivalenti:

git unstage fileA
git reset HEAD -- fileA

Questo rende la sintassi più leggibile e intuitiva, in particolare per operazioni ripetitive.


Alias per Operazioni Comuni

Un altro esempio utile consiste nel definire un alias per visualizzare rapidamente l’ultimo commit effettuato:

git config --global alias.last 'log -1 HEAD'

In questo modo, il comando:

git last

produrrà un output come il seguente:

L’alias last diventa così una comoda abbreviazione per visualizzare rapidamente l’ultimo commit applicato sul branch corrente.

Alias per la visualizzazione dell'ultimo commit
FIG 2 - Alias per la visualizzazione dell'ultimo commit

Alias per Comandi Esterni

Git permette anche di associare comandi esterni o script personalizzati come alias.

In questo caso, è sufficiente anteporre un punto esclamativo ! al comando esterno.

Esempio:

git config --global alias.visual '!gitk'

In questo modo, eseguendo:

git visual

verrà lanciato Gitk, l’interfaccia grafica nativa di Git per la visualizzazione della cronologia dei commit.

Gitk
FIG 3 - Gitk


Best Practice

  • Utilizzare alias brevi ma significativi (es. ci, co, br, st).
  • Centralizzare gli alias globali nel file ~/.gitconfig per coerenza tra progetti.
  • Documentare gli alias personalizzati all’interno della documentazione del progetto o in un file README_DEV.md.
  • Usare l’opzione ! per collegare script di automazione, come strumenti di analisi o di build.



lunedì 13 ottobre 2025

Git: Gestione dei Tag (Tagging)

Come nella maggior parte dei sistemi di controllo versione (VCS), Git consente di associare un’etichetta (tag) a specifici punti della cronologia di un repository.

Questa funzionalità è comunemente utilizzata per identificare rilasci ufficiali del software (ad esempio v1.0, v2.0, ecc.), ma può anche servire a marcare revisioni significative per motivi organizzativi o di audit.

1. Elenco dei Tag Esistenti

Per visualizzare i tag presenti in un repository Git, il comando di riferimento è:
git tag

Visualizza tag presenti
FIG 1 - Visualizza tag presenti

L’output mostra i tag in ordine alfabetico. L’ordinamento non riflette la sequenza temporale dei rilasci o la loro importanza, ma è puramente lessicografico.

Nei progetti complessi, il numero di tag può essere molto elevato (il repository ufficiale di Git, ad esempio, contiene centinaia di etichette).

Per filtrare i risultati in base a un criterio, è possibile utilizzare le opzioni -l o --list insieme a una wildcard.

Esempio

Se si desidera visualizzare esclusivamente i tag relativi alla versione 4.7, si può eseguire:

$ git tag -l "v4.7*"

Filtrare i tag
FIG 2 - Filtrare i tag

Nota Importante

L’utilizzo di git tag senza argomenti restituisce implicitamente l’elenco completo dei tag.
Se invece si utilizza un pattern (ad esempio "v4.7*"), è obbligatorio specificare -l o --list.


2. Tipologie di Tag in Git

Git mette a disposizione due principali categorie di tag:
  • Leggeri (lightweight tag).
  • Annotati (annotated tag).
Entrambe le tipologie servono a collegare un commit a un’etichetta significativa, ma si differenziano profondamente in termini di struttura, metadati e finalità d’uso.

Tag Annotati (Annotated Tags)

I tag annotati sono oggetti completi, salvati nel database di Git con un proprio checksum.

Caratteristiche principali:
  • Contengono metadati come autore (tagger), email, data.
  • Includono un messaggio di tagging, utile per descrivere lo scopo o il contenuto della release.
  • Possono essere firmati digitalmente con GNU Privacy Guard (GPG) per garantire autenticità e integrità.
  • Sono generalmente considerati la scelta raccomandata per i rilasci ufficiali.
I tag annotati rappresentano la modalità più completa e raccomandata per contrassegnare uno specifico punto nella storia di un repository Git. Essi non solo puntano a un commit, ma contengono anche metadati aggiuntivi che ne arricchiscono l’informazione e ne garantiscono l’autenticità.

Per creare un tag annotato, si utilizza l’opzione -a del comando git tag, accompagnata da un messaggio descrittivo tramite l’opzione -m.

Esempio
git tag -a v1.0 -m "Release ufficiale versione 1.0"

Creazione di un Tag Annotato
FIG 3 - Creazione di un Tag Annotato


Per ottenere dettagli su un tag annotato, incluso il commit a cui si riferisce, si utilizza il comando git show.
git show v1.0
git show
FIG 4 - git show


Come si può notare, l’output mostra:
  • informazioni sul tag (nome, autore del tag, email, data, messaggio di annotazione),
  • dettagli sul commit associato (hash, autore, data, messaggio del commit).

Vantaggi dei Tag Annotati
  • Tracciabilità: contengono informazioni su chi ha creato il tag e quando.
  • Documentazione: permettono di associare un messaggio descrittivo che contestualizza la versione.
  • Sicurezza: possono essere firmati digitalmente con GPG, garantendo autenticità e integrità.
  • Professionalità: sono la scelta ideale per marcare rilasci ufficiali o milestone significative.

Tag Leggeri (Lightweight Tags)

Oltre ai tag annotati, Git consente la creazione di tag leggeri (lightweight tags), una modalità più semplice e meno strutturata per marcare uno specifico commit nella storia del repository.

A differenza dei tag annotati, i tag leggeri non includono metadati aggiuntivi: essi rappresentano semplicemente un puntatore diretto a un commit, equivalente a salvare l’hash di quel commit in un riferimento con un nome leggibile.

Un tag leggero rappresenta il tipo più semplice di tag in Git.
  • È sostanzialmente un puntatore immutabile a un commit specifico, molto simile a un branch che non evolve.
  • Non contiene metadati aggiuntivi: né autore, né data, né messaggio.
  • È utile per:
    - contrassegnare rapidamente una revisione
    - definire marcature temporanee
    - operazioni di test o debugging.
Per creare un tag leggero è sufficiente eseguire il comando git tag specificando il nome del tag, senza utilizzare le opzioni -a (annotato), -s (firmato) o -m (messaggio). 

Esempio
git tag v1.0.0

In questo caso, il tag v1.0.0 punta semplicemente al commit corrente, senza ulteriori informazioni.

A differenza dei tag annotati, l’uso di git show su un tag leggero non fornisce informazioni aggiuntive (autore del tag, data, messaggio). Mostra esclusivamente i dettagli del commit a cui il tag fa riferimento.


3. Aggiungere un Tag retroattivamente in Git

In alcuni casi può accadere di dimenticare di creare un tag al momento opportuno, ad esempio in corrispondenza di un rilascio o di una milestone importante. Fortunatamente, Git consente di aggiungere un tag retroattivo a un commit già presente nella cronologia, anche se non si tratta dell’ultimo.

Scenario di Partenza
Supponiamo che la cronologia dei ommit sia simile a quella mostrata in FIG 5 dal comando
git log --pretty=oneline
git log --pretty=oneline
FIG 5 - git log --pretty=oneline

Supponiamo di voler aggiungere un tag alla versione v1.0, corrispondente al commit con messaggio Modifica Projects1.cs  (hash abbreviato 925e858).

Per creare un tag annotato riferito a un commit precedente, è sufficiente specificarne l’hash (anche parziale, purché univoco) al termine del comando:

git tag -a v1.0 925e858 -m "version 1.0"

Creazione del Tag Retroattivo
FIG 6 - Creazione del Tag Retroattivo

Per ottenere informazioni dettagliate sul tag e sul commit associato, è possibile usare:
git show v1.0
git show
FIG 7 - git show

L’output mostra sia i metadati del tag (autore, data, messaggio) sia i dettagli del commit referenziato.


4. Condivisione dei Tag in Git

Per impostazione predefinita, il comando git push non trasferisce automaticamente i tag al repository remoto. Pertanto, una volta creati, è necessario eseguire un’operazione esplicita di push per renderli disponibili ad altri collaboratori. Questo comportamento differisce dai branch, i quali vengono aggiornati automaticamente in seguito a un push.

Pubblicazione di un Singolo Tag
Per condividere un tag specifico con il server remoto, si utilizza la seguente sintassi:
git push origin <tagname>


Ad esempio:
git push origin v1.0

Push di un singolo tag
FIG 8 - Push di un singolo tag

In questo esempio, il tag v1.0 viene trasferito correttamente sul repository remoto origin.

Pubblicazione di Tutti i Tag
Qualora sia necessario trasferire più tag contemporaneamente, Git fornisce l’opzione --tags, che invia tutti i tag locali non ancora presenti sul server remoto:
git push origin --tags

Push di tutti i tag
FIG 9 - Push di tutti i tag


Dopo questa operazione, chiunque effettui un git clone o un git pull riceverà anche tutti i tag pubblicati.

Differenze tra Tipologie di Tag
È importante ricordare che:
  • Il comando git push invia sia i tag lightweight che quelli annotati.
  • Per trasferire solo i tag annotati, è possibile utilizzare l’opzione --follow-tags:
    git push origin --follow-tags
    In questo modo, vengono pubblicati soltanto i tag associati a commit presenti nella cronologia del push e che siano stati creati come tag annotati.

Verificare tag disponibili sul repository remoto
Per verificare i tag disponibili sul repository remoto dopo un push, è possibile utilizzare il comando
git ls-remote --tags origin
 
Tag presenti sul repository remoto
FIG 10 - Tag presenti sul repository remoto


5. Eliminazione dei Tag in Git

In Git, i tag possono essere eliminati sia localmente che sul repository remoto. È importante distinguere le due operazioni, poiché la rimozione in locale non influisce automaticamente sul server remoto, e viceversa.

Eliminazione di un Tag Locale
Per eliminare un tag nel repository locale, si utilizza il comando:
git tag -d <tagname>

Ad esempio:
git tag -d v1.0-lw
Eliminazione di un tag locale
FIG 11 - Eliminazione di un tag locale

In questo caso, il tag v1.0-lw viene eliminato solo dal repository locale.
Tuttavia, se il tag era già stato pubblicato su un remoto (es. origin), esso continuerà ad esistere sul server finché non verrà rimosso manualmente.

Eliminazione di un Tag Remoto
Per rimuovere un tag da un repository remoto, Git mette a disposizione due approcci.
  1. Utilizzo della sintassi con refs/tags
    git push <remote> :refs/tags/<tagname>

    Esempio
    git push origin :refs/tags/v1.0-lw

    In questa sintassi, il valore nullo (:) viene "spinto" verso il riferimento remoto del tag, ottenendo come effetto la sua cancellazione.

    Eliminazione di un Tag Remoto refs-tags
    FIG 12 - Eliminazione di un Tag Remoto refs-tags

  2. Utilizzo dell’opzione --delete (più intuitivo)
    git push <remote> --delete <tagname>

    Esempio:
    git push origin --delete v1.0.1

    Questa modalità è generalmente preferita, poiché risulta più leggibile e intuitiva rispetto alla precedente.

    Eliminazione di un Tag Remoto --delete
    FIG 13 - Eliminazione di un Tag Remoto --delete

6. Visualizzazione del Contenuto di un Tag con git checkout

In Git, i tag rappresentano riferimenti immutabili a specifici commit. Per visualizzare lo stato del progetto associato a un determinato tag, è possibile utilizzare il comando:
git checkout <tagname>

Ad esempio:
git checkout v1.0

git checkout
FIG 14 - git checkout


Lo stato Detached HEAD

Effettuando un checkout diretto su un tag, Git posiziona il repository in modalità detached HEAD.

In questo stato:
  1. È possibile esplorare i file e compilare il progetto esattamente come era al momento del commit taggato.
  2. È consentito creare commit, ma questi non saranno collegati ad alcun branch, risultando raggiungibili solo tramite il loro hash SHA.
  3. Se si esegue un nuovo git checkout senza aver salvato i commit, le modifiche saranno difficilmente recuperabili.
Esempio:
git checkout v1.0.1
git checkout
FIG 15 - git checkout



Creazione di un Branch a partire da un Tag

Per lavorare su una versione storica (ad esempio correggere un bug in una release precedente), è consigliato creare un branch derivato dal tag:
git checkout -b <branchname> <tagname>

Esempio:
git checkout -b version2 v2.0
Creazione di un Branch a partire da un Tag
FIG 16 - Creazione di un Branch a partire da un Tag


In questo caso, il nuovo branch version2 viene creato a partire dal commit identificato dal tag v2.0. Eventuali nuovi commit saranno tracciati da questo branch e non andranno persi.

È importante ricordare che il branch si evolverà in maniera indipendente rispetto al tag:
  • Il tag rimarrà un riferimento statico al commit originale.
  • Il branch potrà avanzare con nuovi commit.











martedì 7 ottobre 2025

Git: Gestione dei repository remoti

Per collaborare efficacemente in un progetto Git, è fondamentale comprendere come gestire i repository remoti. I repository remoti sono versioni dei progetti ospitati su un server (Internet, rete locale o persino la stessa macchina, purché in un percorso distinto).

La gestione dei remoti comprende operazioni quali:

  • Aggiungere o rimuovere repository remoti.
  • Consultare la loro configurazione.
  • Sincronizzare i dati tramite fetch, pull e push.
  • Ispezionare e mantenere aggiornate le referenze remote.


Visualizzare i repository remoti 

Per verificare quali repository remoti sono attualmente associati a un progetto Git, è possibile utilizzare il comando:

git remote

Tale comando restituisce l’elenco degli alias (shortname) configurati per i repository remoti. Qualora il repository sia stato clonato da un server remoto, sarà presente almeno l’alias origin, che costituisce la denominazione predefinita attribuita da Git al repository di origine del clone.

Git remote
FIG 1 - Git remote

Per ottenere, oltre ai nomi, anche gli indirizzi URL associati ai repository remoti (distinti per operazioni di fetch e push), è possibile utilizzare l’opzione -v:

git remote -v

git remote -v
FIG 2 - git remote -v

Un progetto con più collaboratori può avere vari remoti, ciascuno con il proprio URL e protocollo di accesso (HTTPS, SSH, Git).


Aggiungere un nuovo repository remoto

Per aggiungere un nuovo repository remoto e assegnargli un shortname (alias):

git remote add <shortname> <url>

Esempio:

git remote add pd24 https://github.com/Pedestrian24/Hello.git

Da questo momento, sarà possibile richiamare il repository remoto con pd24 invece di digitare l’intero URL.

git remote add
FIG 3 - git remote add

Sincronizzazione con Repository Remoti: Fetch e Pull

Nell’ambito della collaborazione su progetti Git, una delle operazioni fondamentali consiste nel mantenere il proprio repository locale aggiornato rispetto al repository remoto. A tal fine, Git mette a disposizione due comandi principali: git fetch e git pull.


1. git fetch: Recupero dei dati senza integrazione automatica

Scarica i nuovi dati dal remoto senza modificarne l’integrazione nel branch attuale. Il comando:

git fetch <remote>

provvede a contattare il repository remoto specificato (ad esempio origin) e a scaricare tutte le nuove informazioni (commit, branch, tag) che non sono ancora presenti localmente.

Dopo l’esecuzione di git fetch, il repository locale contiene riferimenti aggiornati a tutti i branch remoti (ad esempio origin/main, origin/dev, ecc.), senza tuttavia modificare il contenuto della working directory o del branch corrente.

Pertanto:

  • I dati vengono aggiornati nella copia locale del database Git.
  • Non viene modificato il codice attualmente in lavorazione.
  • L’integrazione delle modifiche (mediante merge o rebase) deve essere eseguita manualmente dall’utente.


Esempio pratico:

git fetch origin

Scarica dal server remoto origin tutte le modifiche effettuate da altri collaboratori dall’ultimo fetch, lasciando intatto lo stato della propria area di lavoro.

git fetch origin
FIG 4 - git fetch origin


2. git pull: Recupero e fusione automatica

Il comando:

git pull <remote> <branch>

rappresenta una scorciatoia che combina due operazioni:

  • git fetch
    recupera i dati aggiornati dal repository remoto.
  • git merge (o git rebase se configurato)
    integra automaticamente i dati recuperati nel branch locale attualmente attivo.

In caso di repository clonato con il comando git clone, Git configura automaticamente il branch locale predefinito (main o master, a seconda della nomenclatura del server) per tracciare il branch remoto corrispondente (origin/main o origin/master).

Pertanto, il semplice comando:

git pull

provvede a scaricare e integrare nel branch locale eventuali modifiche presenti sul server remoto di origine.

git pull
FIG 5 - git pull

A partire da Git 2.27, se la variabile di configurazione pull.rebase non è impostata, l’esecuzione di git pull genera un avviso, invitando l’utente a scegliere un comportamento predefinito

Configurazioni consigliate:

  • Comportamento standard (merge)
    git config --global pull.rebase "false"
       
    In questo caso, git pull tenta un fast-forward quando possibile, altrimenti effettua un merge commit.
  • Comportamento alternativo (rebase)
    git config --global pull.rebase "true"
       
    In questo scenario, le modifiche locali vengono riallineate sopra la cronologia del branch remoto, mantenendo una storia più lineare e priva di commit di merge superflui.


Pubblicazione delle Modifiche su Repository Remoti (Push)

Una volta raggiunto uno stato stabile del proprio progetto locale, è necessario condividere le modifiche con gli altri collaboratori pubblicandole su un repository remoto.

Questa operazione viene eseguita tramite il comando:

git push <remote> <branch>


Concetto di Push

Il comando git push invia i commit presenti nel branch locale specificato verso il corrispondente branch remoto.

Ad esempio, per pubblicare il contenuto del branch main(o master, a seconda della nomenclatura utilizzata) sul repository remoto di default origin, è sufficiente eseguire:

git push origin main

In questo modo, lo stato corrente del branch locale master viene replicato nel corrispondente branch remoto origin/main.


Requisiti e condizioni per il push

L’operazione di push ha successo solo se:

  • L’utente dispone di permessi di scrittura sul repository remoto.
  • La cronologia del branch remoto è compatibile con quella del branch locale.

Nel caso in cui un altro collaboratore abbia già eseguito un push al branch remoto dopo il vostro ultimo aggiornamento locale, Git rifiuterà l’operazione per evitare la perdita o la sovrascrittura dei commit altrui.


Sincronizzazione prima del push

Quando il push viene rifiutato a causa di divergenze, è necessario:

  1. Eseguire un fetch per recuperare i commit remoti:
    git fetch origin 
  2. Integrare tali modifiche nel branch locale, utilizzando:
    git merge origin/main
    fusione classica, mantiene entrambe le linee di sviluppo.
    git rebase origin/main
    riallineamento lineare, utile per cronologie pulite.
  3. Eseguire nuovamente il push:
    git push origin main

Solo dopo questa integrazione sarà possibile completare la pubblicazione delle modifiche.


Scenari avanzati

  1. Push di tutti i branch locali:
    git push --all origin
  2. Pubblicazione dei tag (per versionamento o release):
    git push origin --tags
  3. Forzare il push (operazione rischiosa): 
    git push --force origin master
    Questo comando sovrascrive la cronologia remota con quella locale, potenzialmente cancellando il lavoro di altri. Deve essere utilizzato solo in scenari controllati (es. riscrittura della cronologia prima della pubblicazione ufficiale).

git push origin main
FIG 6 - git push origin main


Ispezione di un Repository Remoto (show)

Per gestire in maniera efficace le interazioni con repository remoti, Git mette a disposizione il comando:

git remote show <nome-remoto>

Questo strumento consente di ottenere una panoramica dettagliata sulle configurazioni associate a un determinato remote, come ad esempio l’URL di fetch e push, i branch tracciati e le impostazioni di sincronizzazione.


Utilizzo di base

Ad esempio, per ispezionare il remote predefinito origin:

git remote show origin

git remote show origin
FIG 7 - git remote show origin

L’output restituisce informazioni essenziali, tra cui:

  • Fetch/Push URL. Gli indirizzi utilizzati per scaricare (fetch) o pubblicare (push) dati.
  • HEAD branch. Il branch predefinito del remote (spesso master o main).
  • Remote branches. I branch remoti tracciati dal repository locale.
  • Branch locali configurati per pull/push. Le associazioni automatiche di sincronizzazione.


Output avanzato in scenari complessi

In progetti di grandi dimensioni o con più branch remoti, l’output può essere molto più articolato.

git remote show origin
FIG 8 - git remote show origin

In questo caso, emergono ulteriori informazioni:

  • Branch nuovi (new)
    individuati sul server, ma non ancora scaricati localmente. Verranno sincronizzati al prossimo fetch.
  • Branch obsoleti (stale)
    presenti localmente ma rimossi dal server. Git suggerisce di eliminarli con:
    git remote prune origin
  • Associazioni multiple
    un branch locale può essere configurato per sincronizzarsi automaticamente con un branch remoto specifico.


Casi d’uso pratici

  • Verifica rapida della configurazione remota prima di eseguire git pull o git push.
  • Identificazione di branch obsoleti per mantenere un repository locale pulito.
  • Controllo dei permessi e degli URL (utile quando si lavora con remoti accessibili sia via HTTPS che SSH).
  • Diagnosi di problemi di sincronizzazione, ad esempio quando un branch non è correttamente tracciato.


Rinomina ed Eliminazione dei Repository Remoti (rename, remove)

La gestione dei repository remoti in Git non si limita alla loro configurazione iniziale: in determinati scenari può essere necessario rinominare un remote per una migliore leggibilità, oppure rimuoverlo se non più utilizzato. Git mette a disposizione comandi specifici per entrambe le operazioni.


1. Rinomina di un Remote

Per modificare il nome abbreviato (shortname) di un remote si utilizza:

git remote rename <vecchio-nome> <nuovo-nome>


Esempio

Se si desidera rinominare un remote chiamato pd24 in pippo:

git remote rename pd24 pippo
git remote
git remote rename
FIG 9 - git remote rename

L’operazione non si limita a rinominare il remote, ma aggiorna automaticamente anche tutti i riferimenti ai branch di tracking.

Ad esempio:

  • Prima: pd24/main
  • Dopo: pippo/main

Questo garantisce coerenza e riduce il rischio di errori manuali.


2. Rimozione di un Remote

Se un remote non è più necessario (ad esempio perché il server è stato spostato, un mirror è stato dismesso o un collaboratore non contribuisce più), è possibile eliminarlo con:

git remote remove <nome>

oppure, in alternativa:

git remote rm <nome>


Esempio

Per rimuovere il remote pippo:

git remote remove pippo
git remote
git remote remove
FIG 10 - git remote remove


Dopo l’eliminazione:

  • Tutti i remote-tracking branch associati a quel remote vengono rimossi.
  • Le configurazioni locali legate al remote (ad esempio impostazioni di fetch e push) vengono eliminate.



Tabella di Sintesi: Principali Operazioni sui Repository Remoti

ComandoDescrizioneEsempio
git remote -vElenca i remoti configurati con i rispettivi URLgit remote -v
git remote add <nome> <url>Aggiunge un nuovo remotogit remote add pd24
 https://github.com/Pedestrian24/Hello.git
git fetch <remote>Scarica i dati dal remoto senza integrarligit fetch origin
git pullScarica e integra i dati dal remotogit pull origin master
git push <remote> <branch>Invia i commit locali al remotogit push origin main
git remote show <remote>Mostra dettagli di configurazione di un remotogit remote show origin
git remote rename <old> <new>Rinomina un remotogit remote rename pd24 pippo
git remote remove <nome>Rimuove un remoto e le relative configurazionigit remote remove pippo


Best Practice

  • Usare nomi coerenti: origin per il repository principale, upstream per il fork originale.
  • Controllare sempre con git fetch prima di un git pull: riduce i conflitti e rende più prevedibile il flusso.
  • Evitare git push --force salvo nei branch personali: può riscrivere la cronologia e creare problemi ai collaboratori.
  • Pulire i branch remoti obsoleti con:
    git remote prune origin
  • Preferire SSH a HTTPS per ambienti professionali: maggiore sicurezza e praticità nell’autenticazione.





venerdì 3 ottobre 2025

MS Outlook: Aggiungere automaticamente i contatti da un'email quando si risponde

Nell’attività quotidiana di un professionista IT o di un knowledge worker, la gestione dei contatti è un aspetto cruciale. Ogni giorno vengono scambiate centinaia di email, spesso con interlocutori che non sono ancora presenti nella rubrica di Outlook. In questi casi, il rischio è quello di perdere tempo nel reinserire manualmente i dati o, peggio, non riuscire a recuperare in futuro un indirizzo di posta elettronica utile.

Microsoft Outlook, pur essendo una delle piattaforme di posta elettronica più diffuse in ambito aziendale, non offre di default una funzionalità che consenta di aggiungere automaticamente i contatti quando si risponde a un’email. Per sopperire a questa mancanza è possibile implementare una macro VBA (Visual Basic for Applications), che permette di automatizzare l’inserimento dei contatti direttamente all’interno di Outlook.

Attraverso una semplice macro VBA è possibile configurare Outlook in modo che, ogni volta che si risponde a un messaggio, il mittente e tutti i destinatari vengano automaticamente salvati nella cartella contatti predefinita.

Procedura operativa:

  • Aprire l’editor VBA: premere Alt+F11 per accedere a Microsoft Visual Basic for Applications.
  • Accedere al progetto di Outlook: nel riquadro laterale espandere Project1 e fare doppio clic su ThisOutlookSession.
  • Copiare il seguente codice VBA e incollarlo nella finestra di codice. Numerosi commenti rendono il codice ben documentato e facilmente leggibile

Option Explicit
' Istruzione fondamentale: richiede che TUTTE le variabili siano dichiarate prima di essere usate.
' Questo aiuta a prevenire errori di battitura (bug) nel codice.

' --- DICHIARAZIONI GLOBALI (a livello di modulo) ---

Public WithEvents xExplorer As Outlook.Explorer
' Dichiara una variabile 'xExplorer' che rappresenta la finestra principale di Outlook
' (dove vedi la lista delle email). 'WithEvents' permette di "ascoltare" cosa succede in quella finestra.

Public WithEvents xMailItem As Outlook.MailItem
' Dichiara una variabile 'xMailItem' che rappresenta l'email che è attualmente selezionata.
' 'WithEvents' ci permette di "ascoltare" l'azione "Rispondi" su quell'email specifica.

' --- GESTIONE AVVIO APPLICAZIONE ---

Sub Application_Startup()
    ' Questa funzione viene eseguita automaticamente non appena apri Outlook.
    Set xExplorer = Outlook.Application.ActiveExplorer
    ' Assegna alla variabile 'xExplorer' la finestra di Outlook attualmente attiva.
End Sub

' --- GESTIONE SELEZIONE (Monitora il cambio di email) ---

Private Sub xExplorer_SelectionChange()
    ' Questa funzione viene eseguita ogni volta che cambi la selezione nella lista delle email.
    
    ' Nota: il codice originale conteneva una riga "Call ReplySelectedMail(xExplorer)" che è stata rimossa
    ' o sostituita dal blocco seguente, che è la versione pulita per assegnare l'oggetto.
    
    On Error Resume Next
    ' Istruzione temporanea: se si verifica un errore (es. selezioni qualcosa che non è un'email),
    ' ignora l'errore e passa alla riga successiva. Necessario qui perché la selezione può essere complessa.
    
    If xExplorer.Selection.Count = 1 Then
        ' Controlla: se hai selezionato un SOLO elemento...
        If TypeOf xExplorer.Selection.Item(1) Is Outlook.MailItem Then
            ' E se quell'elemento è un'Email (MailItem)...
            Set xMailItem = xExplorer.Selection.Item(1)
            ' ...allora assegna quell'email alla variabile 'xMailItem' per poter intercettare il 'Reply'.
        Else
            Set xMailItem = Nothing
            ' Altrimenti, se hai selezionato un calendario o una cartella, rilascia la variabile.
        End If
    Else
        Set xMailItem = Nothing
        ' Se hai selezionato più di un elemento o nessuno, rilascia la variabile.
    End If
    
    On Error GoTo 0
    ' Disattiva l'istruzione temporanea di gestione degli errori per le righe successive.
End Sub

' --- AZIONE PRINCIPALE: L'EVENTO "RISPONDI" ---

Private Sub xMailItem_Reply(ByVal Response As Object, Cancel As Boolean)
    ' Questa funzione viene eseguita solo quando premi il pulsante "Rispondi"
    ' sull'email che è stata selezionata.

    ' --- DICHIARAZIONE VARIABILI LOCALI ---
    Dim xNameSpace As Outlook.NameSpace         ' Per accedere alle cartelle di Outlook (es. Contatti).
    Dim xContactItems As Outlook.Items          ' L'intera collezione di elementi nella cartella Contatti.
    Dim xContact As Outlook.ContactItem         ' Un contatto esistente trovato.
    Dim xNewContact As Outlook.ContactItem      ' Un nuovo contatto da creare.
    Dim xRecipients As Outlook.Recipients       ' La lista di destinatari (A:, Cc:, Ccn:).
    Dim xRecipient As Outlook.Recipient         ' Un singolo destinatario della lista.
    Dim xDictAddresses As Object                ' Strumento avanzato (Dizionario) per tenere traccia
                                                ' degli indirizzi già visti ed evitare duplicati.
    Dim xAddress As Variant                     ' Usato per scorrere gli indirizzi nel Dizionario.
    Dim sName As String                         ' Nome della persona (Mittente o Destinatario).
    Dim sAddress As String                      ' Indirizzo email.
    Dim sFilterAddress As String                ' La stringa di ricerca per trovare i contatti esistenti.
    Dim lIdx As Long                            ' Un contatore per i cicli.

    ' --- 1. PREPARAZIONE E RACCOLTA INDIRIZZI ---

    Set xDictAddresses = CreateObject("Scripting.Dictionary")
    ' Crea il Dizionario (uno strumento per archiviare indirizzi unici: "Indirizzo" -> "Nome").
    
    ' A. Aggiungi il Mittente (Sender)
    sAddress = xMailItem.SenderEmailAddress
    sName = xMailItem.SenderName
    If Not xDictAddresses.Exists(sAddress) And sAddress <> "" Then
        ' Se l'indirizzo del Mittente NON è già nel Dizionario e non è vuoto...
        xDictAddresses.Add sAddress, sName
        ' ...allora aggiungilo (chiave: indirizzo, valore: nome).
    End If

    ' B. Aggiungi tutti i Destinatari (Recipients)
    Set xRecipients = xMailItem.Recipients
    For Each xRecipient In xRecipients
        ' Scorre tutti i destinatari (A:, Cc:, Ccn:)
        xRecipient.Resolve ' Assicura che l'indirizzo sia risolto (se non lo è già)
        sAddress = xRecipient.Address
        sName = xRecipient.Name
        If Not xDictAddresses.Exists(sAddress) And sAddress <> "" Then
            ' Se l'indirizzo del Destinatario NON è già nel Dizionario e non è vuoto...
            xDictAddresses.Add sAddress, sName
            ' ...allora aggiungilo.
        End If
    Next xRecipient

    ' --- 2. ACCESSO ALLA RUBRICA ---

    Set xNameSpace = Outlook.Application.GetNamespace("MAPI")
    ' Si connette al sistema di archiviazione di Outlook (MAPI).
    Set xContactItems = xNameSpace.GetDefaultFolder(olFolderContacts).Items
    ' Ottiene la collezione di tutti gli elementi (Contatti) nella cartella "Contatti" predefinita.

    ' --- 3. CONTROLLO ESISTENZA E CREAZIONE CONTATTI ---

    For Each xAddress In xDictAddresses.Keys
        ' Scorre tutti gli indirizzi UNICI raccolti (Mittente + Destinatari).
        sAddress = CStr(xAddress)
        sName = CStr(xDictAddresses.Item(xAddress))
        
        Set xContact = Nothing
        ' Resetta la variabile per la ricerca del contatto prima di ogni tentativo.
        
        ' Cerca se l'indirizzo esiste nei campi EmailAddress (Outlook ne gestisce fino a 3: Email1, Email2, Email3)
        For lIdx = 1 To 3
            ' Il ciclo controlla i 3 possibili campi email del contatto.
            
            sFilterAddress = "[Email" & lIdx & "Address] = '" & Replace(sAddress, "'", "''") & "'"
            ' Costruisce la stringa di ricerca. Ad esempio: "[Email1Address] = 'pippo@example.com'".
            ' Il 'Replace' serve a gestire indirizzi che contengono apici (molto raro, ma sicuro).
            
            Set xContact = xContactItems.Find(sFilterAddress)
            ' Esegue la ricerca vera e propria nella rubrica.
            
            If Not (xContact Is Nothing) Then
                Exit For
                ' Se ha trovato il contatto (non è 'Nothing'), esce dal ciclo 1-3.
            End If
        Next lIdx
        
        ' Se il contatto NON è stato trovato dopo tutti i controlli (xContact è ancora Nothing)...
        If xContact Is Nothing Then
            Set xNewContact = Outlook.Application.CreateItem(olContactItem)
            ' Crea un NUOVO oggetto Contatto.
            With xNewContact
                ' Imposta le proprietà del nuovo contatto.
                .FullName = sName           ' Imposta il nome completo.
                .Email1Address = sAddress   ' Imposta l'indirizzo email principale.
                .Categories = "From Email"  ' Aggiunge la categoria 'From Email' per identificarlo facilmente.
                .Save                       ' Salva il nuovo contatto nella rubrica.
            End With
        End If
    Next xAddress
    
    ' --- 4. PULIZIA FINALE ---
    
    Set xDictAddresses = Nothing
    Set xRecipients = Nothing
    Set xContactItems = Nothing
    Set xNameSpace = Nothing
    ' Rilascia tutti gli oggetti utilizzati per liberare la memoria.
    
End Sub

  • Salvare e riavviare Outlook. Al riavvio, la macro sarà attiva e funzionante.

Outlook, Microsoft Visual Basic
FIG 1 - Outlook, Microsoft Visual Basic

Da questo momento, ogni volta che si risponde a un’email, il sistema salverà automaticamente il mittente e tutti i destinatari come nuovi contatti all’interno della cartella predefinita associata all’account di posta.


Considerazioni di sicurezza e governance

È bene sottolineare che l’utilizzo di macro VBA in Outlook può essere soggetto a policy di sicurezza aziendali. In molte organizzazioni, infatti, l’esecuzione di codice personalizzato è limitata per ridurre i rischi di attacchi tramite macro. Prima di implementare questa soluzione in un contesto enterprise, è quindi opportuno:

  • Verificare le impostazioni di sicurezza di Outlook e le eventuali restrizioni IT.
  • Valutare l’impatto sulla gestione centralizzata dei contatti, soprattutto se si utilizzano sistemi integrati come Microsoft Exchange o Microsoft 365.