Quando impari a programmare, prima o poi imparerai anche a conoscere i sistemi di controllo della versione. E mentre ci sono molti strumenti concorrenti in questo spazio, uno di questi è lo standard de facto utilizzato da quasi tutti nel settore. È così popolare che ci sono aziende che usano il suo nome nel loro marchio. Stiamo parlando di Git, ovviamente.
Sebbene Git sia uno strumento potente, il suo potere è ben nascosto. Ci sono alcuni concetti essenziali che devi capire per diventare veramente esperto con Git. La buona notizia è che una volta che li impari, difficilmente ti imbatterai in guai da cui non puoi sfuggire.
Il tipico flusso di lavoro
In un tipico flusso di lavoro Git utilizzerai un repository locale, un repository remoto e uno o più rami. I repository memorizzano tutte le informazioni sul progetto, inclusa l'intera cronologia e tutti i rami. Un ramo è fondamentalmente una raccolta di modifiche che portano da un progetto vuoto allo stato corrente.
Dopo aver clonato un repository, lavori sulla tua copia locale e introduci nuove modifiche. Fino a quando non invii le modifiche locali al repository remoto, tutto il tuo lavoro è disponibile solo sulla tua macchina.
Quando finisci un'attività, è il momento di sincronizzarti con il repository remoto. Si desidera eseguire il pull delle modifiche remote per tenere il passo con l'avanzamento del progetto e si desidera eseguire il push delle modifiche locali per condividere il proprio lavoro con gli altri.
Modifiche locali
Tutto va bene quando tu e il resto del tuo team lavorate su file completamente separati. Qualunque cosa accada, non vi calpesterete a vicenda.
Tuttavia, ci sono momenti in cui tu ei tuoi compagni di squadra introducete simultaneamente modifiche nello stesso punto. E di solito è lì che iniziano i problemi.
Hai mai giustiziato git pull
solo per vedere i temuti error: Your local changes to the following files would be overwritten by merge:
? Prima o poi, tutti si imbattono in quel problema.
Ciò che è più confuso qui è che non vuoi unire nulla, basta tirare, giusto? In realtà, tirare è un po 'più complicato di quanto potresti aver pensato.
Come funziona esattamente Git Pull?
Il pull non è una singola operazione. Consiste nel recuperare i dati dal server remoto e quindi unire le modifiche con il repository locale. Queste due operazioni possono essere eseguite manualmente se lo desideri:
git fetch git merge origin/$CURRENT_BRANCH
La origin/$CURRENT_BRANCH
parte significa che:
- Git unirà le modifiche dal repository remoto denominato
origin
(quello da cui hai clonato) - che sono stati aggiunti a
$CURRENT_BRANCH
- che non sono già presenti nella tua filiale locale controllata
Poiché Git esegue unioni solo quando non ci sono modifiche non salvate, ogni volta che esegui git pull
con modifiche non salvate potresti metterti nei guai. Fortunatamente, ci sono modi per uscire dai guai tutto d'un pezzo!

Approcci diversi
Quando sono presenti modifiche locali non salvate e si desidera comunque estrarre una nuova versione dal server remoto, il caso d'uso rientra in genere in uno dei seguenti scenari. O:
- non ti interessano le modifiche locali e vuoi sovrascriverle,
- ti interessano molto le modifiche e vorresti applicarle dopo le modifiche remote,
- si desidera scaricare le modifiche remote ma non applicarle ancora
Ciascuno degli approcci richiede una soluzione diversa.
Non ti interessano i cambiamenti locali
In questo caso, vuoi solo eliminare tutte le modifiche locali non salvate. Forse hai modificato un file per sperimentare, ma non hai più bisogno della modifica. Tutto ciò che ti interessa è essere aggiornato con l'upstream.
Ciò significa che aggiungi un ulteriore passaggio tra il recupero delle modifiche remote e l'unione di esse. Questo passaggio ripristinerà il ramo allo stato non modificato, consentendo così git merge
di funzionare.
git fetch git reset --hard HEAD git merge origin/$CURRENT_BRANCH
Se non si desidera digitare il nome del ramo ogni volta che si esegue questo comando, Git ha una bella scorciatoia che punta al ramo di monte: @{u}
. Un ramo a monte è il ramo nel repository remoto da cui esegui il push e il recupero.
Ecco come apparirebbero i comandi precedenti con il collegamento:
git fetch git reset --hard HEAD git merge '@{u}'
Stiamo citando la scorciatoia nell'esempio per impedire alla shell di interpretarla.
Ti preoccupi molto dei cambiamenti locali
Quando le modifiche non salvate sono significative per te, ci sono due opzioni. Puoi impegnarli e poi esibirli git pull
, oppure puoi nasconderli.
Nascondere significa mettere da parte le modifiche per un momento per ripristinarle più tardi. Per essere più precisi, git stash
crea un commit che non è visibile sul tuo ramo corrente, ma è comunque accessibile da Git.
Per ripristinare le modifiche salvate nell'ultima scorta, utilizzare il git stash pop
comando. Dopo aver applicato con successo le modifiche nascoste, questo comando rimuove anche il commit stash in quanto non è più necessario.
Il flusso di lavoro potrebbe quindi assomigliare a questo:
git fetch git stash git merge '@{u}' git stash pop
Per impostazione predefinita, le modifiche dalla scorta verranno messe in scena. Se vuoi rimuoverli dallo stage, usa il comando git restore --staged
(se usi Git più recente di 2.25.0).
Vuoi solo scaricare le modifiche remote
L'ultimo scenario è leggermente diverso dai precedenti. Diciamo che sei nel mezzo di un refactoring molto disordinato. Né perdere le modifiche né metterle da parte è un'opzione. Tuttavia, vuoi ancora avere le modifiche remote disponibili per eseguirle git diff
.
Come probabilmente avrai capito, il download delle modifiche remote non richiede git pull
affatto! git fetch
è appena sufficiente.
One thing to note is that by default, git fetch
will only bring you changes from the current branch. To get all the changes from all the branches, use git fetch --all
. And if you'd like to clean up some of the branches that no longer exist in the remote repository, git fetch --all --prune
will do the cleaning up!

Some Automation
Have you heard of Git Config? It's a file where Git stores all of the user-configured settings. It resides in your home directory: either as ~/.gitconfig
or ~/.config/git/config
. You can edit it to add some custom aliases that will be understood as Git commands.
For example, to have a shortcut equivalent to git diff --cached
(that shows the difference between the current branch and the staged files), you'd add the following section:
[alias] dc = diff --cached
After that, you can run git dc
whenever you wish to review the changes. Going this way, we can set up a few aliases related to the previous use cases.
[alias] pull_force = !"git fetch --all; git reset --hard HEAD; git merge @{u}" pf = pull_force pull_stash = !"git fetch --all; git stash; git merge @{u}; git stash pop"
This way, running git pull_force
will overwrite the local changes, while git pull_stash
will preserve them.
The Other Git Pull Force
Curious minds may have already discovered that there is such a thing as git pull --force
. However, this is a very different beast to what's presented in this article.
It may sound like something that would help us overwrite local changes. Instead, it lets us fetch the changes from one remote branch to a different local branch. git pull --force
only modifies the behavior of the fetching part. It is therefore equivalent to git fetch --force
.
Like git push
, git fetch
allows us to specify which local and remote branch do we want to operate on. git fetch origin/feature-1:my-feature
will mean that the changes in the feature-1
branch from the remote repository will end up visible on the local branch my-feature
. When such an operation modifies the existing history, it is not permitted by Git without an explicit --force
parameter.
Just like git push --force
allows overwriting remote branches, git fetch --force
(or git pull --force
) allows overwriting local branches. It is always used with source and destination branches mentioned as parameters. An alternative approach to overwriting local changes using git --pull force
could be git pull --force "@{u}:HEAD"
.
Conclusion
Il mondo di Git è vasto. Questo articolo ha trattato solo uno degli aspetti della manutenzione del repository: incorporare modifiche remote in un repository locale. Anche questo scenario quotidiano ci ha richiesto di guardare leggermente più in profondità nei meccanismi interni di questo strumento di controllo delle versioni.
Imparare casi d'uso reali ti aiuta a capire meglio come funziona Git sotto il cofano. Questo, a sua volta, ti farà sentire potenziato ogni volta che ti metti nei guai. Lo facciamo tutti di tanto in tanto.