Risoluzione dei Problemi di Configurazione di Git: Correzioni Comuni e Buone Pratiche

Risolvi i problemi di configurazione di Git tracciando le origini delle impostazioni, risolvendo problemi di identità, alias, hook, terminazioni di riga, pull e credenziali.

Risoluzione dei Problemi di Configurazione di Git: Correzioni Comuni e Buone Pratiche

La maggior parte dei problemi di configurazione di Git sembrano più strani di quanto siano in realtà. Git di solito fa esattamente ciò che uno dei suoi file di configurazione gli ha detto di fare. La parte difficile è trovare quale file, perché l'impostazione può risiedere nel repository, nella configurazione utente, in una configurazione di sistema, in un file incluso o in un'inclusione condizionale che si applica solo in una directory.

Il comando che uso per primo è questo:

git config --list --show-origin --show-scope

Se la tua versione di Git non supporta --show-scope, usa:

git config --list --show-origin

L'origine ti dice quale file ha fornito ogni valore. Questo è più importante del valore da solo. Vedere [email protected] non è sufficiente; devi sapere se proviene da .git/config, ~/.gitconfig, /etc/gitconfig o da un profilo di lavoro incluso.

La configurazione di Git ha un ordine di priorità. La configurazione locale del repository di solito batte la configurazione globale dell'utente, e la configurazione globale batte quella di sistema. Le opzioni della riga di comando e le variabili d'ambiente possono sovrascriverle tutte per un singolo comando. Le inclusioni condizionali aggiungono un altro livello: un file globale può dire, "Quando sono all'interno di questa directory, carica anche quest'altra configurazione."

Puoi ispezionare una singola impostazione con la sua origine:

git config --show-origin --get user.email
git config --show-origin --get core.autocrlf
git config --show-origin --get-regexp '^alias\.'

Questa abitudine previene molti sprechi di modifiche. Se un repository ha user.email impostato localmente, cambiare git config --global user.email non influenzerà i commit in quel repository.

Nome o Email Errati sui Commit

Il sintomo è semplice: i commit mostrano l'autore sbagliato. Questo accade spesso quando usi lo stesso laptop per progetti lavorativi e personali, o quando cloni un repository aziendale prima di impostare la tua email lavorativa.

Controlla cosa Git userà nel repository corrente:

git config user.name
git config user.email
git config --show-origin --get user.email

Imposta la tua identità predefinita a livello globale:

git config --global user.name "Il Tuo Nome"
git config --global user.email "[email protected]"

Per un singolo repository, impostala localmente:

git config --local user.name "Il Tuo Nome"
git config --local user.email "[email protected]"

Se vuoi che Git rifiuti i commit quando l'identità non è configurata esplicitamente, usa:

git config --global user.useConfigOnly true

Questa impostazione è utile per chi cambia identità. Può infastidire i principianti perché Git smetterà di indovinare dal nome utente e hostname di sistema. Usala quando preferisci fallire un commit piuttosto che crearne uno con l'indirizzo sbagliato.

Per una separazione più pulita tra lavoro e personale, usa inclusioni condizionali:

# ~/.gitconfig
[user]
    name = Il Tuo Nome
    email = [email protected]

[includeIf "gitdir:~/lavoro/"]
    path = ~/.gitconfig-lavoro

Poi metti questo in ~/.gitconfig-lavoro:

[user]
    email = [email protected]

La barra finale in gitdir:~/lavoro/ è importante perché significa repository sotto quella directory. Se non si attiva, esegui git config --list --show-origin da dentro un repository di lavoro e controlla se il file incluso appare.

Se hai già fatto commit con l'email sbagliata, cambiare la configurazione risolve solo i commit futuri. Per commit non pubblicati, puoi modificare o fare rebase. Per commit già inviati a un branch condiviso, chiedi prima di riscrivere la storia.

Alias che Non Funzionano

Gli alias di Git sono memorizzati sotto alias.*. Elencali così:

git config --get-regexp '^alias\.'

Un alias normale si espande in un sottocomando Git:

git config --global alias.st 'status -sb'
git st

Se l'alias ha bisogno di una pipeline shell, espansione di variabili, cd, o un altro comando non Git, deve iniziare con !:

git config --global alias.recent '!git for-each-ref --sort=-committerdate --count=10 --format="%(refname:short)" refs/heads/'

Senza !, Git cerca di trattare la prima parola come un comando Git. ls -la diventa "esegui il comando Git chiamato ls," che non è quello che intendevi.

Le virgolette sono l'altro fallimento comune. Se definisci alias dalla shell, usa virgolette singole attorno all'intero alias quando possibile, poi virgolette doppie al suo interno se necessario. Shell diverse gestiscono le virgolette in modo diverso, specialmente PowerShell e cmd.exe. Se un alias complesso continua a rompersi, modifica direttamente il file di configurazione:

git config --global --edit

Un trucco pratico per il debug è iniziare con il comando al di fuori di Git. Una volta che funziona, incollalo nell'alias. Se è un alias di shell, prefissalo con ! e testa di nuovo.

Fai anche attenzione agli alias che oscurano i modelli mentali. Un alias chiamato pull o merge può rendere il comportamento di Git sorprendente. Git non permette agli alias di sovrascrivere direttamente i comandi incorporati, ma gli alias di shell e gli script wrapper possono farlo. Se git pull si comporta in modo strano, controlla anche la configurazione della tua shell:

type git
alias | grep git

Hook che Non Vengono Mai Eseguiti

Gli hook falliscono per tre ragioni noiose: Git sta cercando in una directory di hook diversa, il file non è eseguibile, o lo script assume un ambiente che non ha.

Controlla il percorso degli hook configurato:

git config --show-origin --get core.hooksPath

Se questo stampa .githooks, Git userà .githooks/pre-commit, non .git/hooks/pre-commit. Se non stampa nulla, Git usa .git/hooks.

Su macOS e Linux, controlla i permessi:

ls -l .git/hooks/pre-commit .githooks/pre-commit 2>/dev/null
chmod +x .githooks/pre-commit

Un hook che esce con uno stato diverso da zero blocca l'operazione Git. Aggiungi tracciamento temporaneo vicino all'inizio:

#!/usr/bin/env bash
set -x
pwd
env | sort

Non lasciare tracciamento rumoroso in un hook condiviso. Diventa illeggibile rapidamente.

I problemi di percorso sono comuni con i client GUI. Un hook che funziona nel tuo terminale potrebbe fallire in un IDE perché l'IDE non ha caricato il tuo profilo shell. Preferisci comandi locali al progetto dove possibile:

./node_modules/.bin/eslint .

o controlla il comando e stampa un messaggio utile:

if ! command -v npm >/dev/null 2>&1; then
  echo "npm è richiesto per questo hook ma non è stato trovato nel PATH."
  exit 1
fi

Le Terminazioni di Riga Continuano a Cambiare

I problemi di terminazione di riga si manifestano come file che appaiono modificati subito dopo il checkout, diff enormi dove ogni riga è cambiata, o script che falliscono su Linux dopo essere stati modificati su Windows.

Controlla la tua impostazione:

git config --show-origin --get core.autocrlf
git config --show-origin --get core.eol

Le scelte comuni sono:

# Checkout adatto a Windows, LF nel repository
git config --global core.autocrlf true

# Adatto a macOS/Linux: converti CRLF in LF solo al commit
git config --global core.autocrlf input

# Nessuna conversione automatica
git config --global core.autocrlf false

Per un team, .gitattributes è più affidabile che dire a ogni sviluppatore di impostare correttamente le variabili globali. Metti le regole del progetto nel repository:

* text=auto
*.sh text eol=lf
*.bat text eol=crlf
*.png binary
*.jpg binary
*.pdf binary

Dopo aver aggiunto o modificato .gitattributes, normalizza i file deliberatamente:

git add --renormalize .
git status

Rivedi attentamente quel diff. Può toccare molti file, e non vuoi mescolare la normalizzazione delle terminazioni di riga con il lavoro sulle funzionalità.

Pull, Push o Merge Usa il Default Sbagliato

A volte il problema di configurazione non è l'identità o le terminazioni di riga. È Git che sceglie una strategia di pull che non ti aspettavi.

Controlla le impostazioni relative al pull:

git config --show-origin --get pull.rebase
git config --show-origin --get pull.ff
git config --show-origin --get branch.main.rebase

Se git pull continua a fare rebase quando ti aspettavi un merge, pull.rebase o un'impostazione specifica del branch potrebbe essere abilitata. Se rifiuta pull non fast-forward, pull.ff=only potrebbe essere impostato. Queste impostazioni non sono sbagliate di per sé; devono solo corrispondere al flusso di lavoro del team.

Imposta un default esplicito invece di vivere con avvisi e sorprese:

# Merge su pull
git config --global pull.rebase false

# Rebase su pull
git config --global pull.rebase true

# Permetti solo pull fast-forward
git config --global pull.ff only

Per un singolo branch:

git config branch.main.rebase true

Confusione con il Credential Helper

I problemi di autenticazione spesso sembrano problemi remoti ma provengono dalla configurazione locale. Git potrebbe usare un credential helper che ha un vecchio token memorizzato nella cache.

Controlla gli helper:

git config --show-origin --get-all credential.helper

Potresti vedere osxkeychain, manager, manager-core, store o cache. Possono esistere più helper. Se Git continua a inviare la credenziale sbagliata, rimuovila dal portachiavi del sistema operativo o dal gestore delle credenziali piuttosto che cambiare URL remoti a caso.

Controlla anche il remoto:

git remote -v

SSH e HTTPS usano percorsi di autenticazione diversi. Se un repository usa [email protected]:org/repo.git e un altro usa https://github.com/org/repo.git, non useranno necessariamente le stesse credenziali.

Una Routine di Debug Affidabile

Quando la configurazione di Git sembra incoerente, usa una routine invece di indovinare:

  1. Esegui il comando che fallisce dalla radice del repository.
  2. Ispeziona l'impostazione esatta con git config --show-origin --get <nome>.
  3. Elenca le impostazioni correlate con git config --list --show-origin --show-scope.
  4. Controlla la configurazione locale in .git/config prima di cambiare quella globale.
  5. Controlla le inclusioni condizionali se il problema si verifica solo in una directory.
  6. Fai la modifica di configurazione più piccola e riesegui il comando originale.

La configurazione di Git è potente perché può essere stratificata. Questo è anche il motivo per cui diventa confusa. La soluzione è rendere visibili gli strati, poi cambiare lo strato che sta effettivamente vincendo.

Quando la Configurazione è Diversa Dentro un IDE

Una classe confusa di problemi di Git appare solo all'interno di un editor o GUI. Il terminale usa un'identità, ma l'IDE fa commit con un'altra. Un hook passa nella tua shell, ma fallisce dal pannello di commit. Un prompt di credenziali appare nel terminale, mentre la GUI riprova silenziosamente con un vecchio token.

La ragione è di solito l'ambiente. La tua shell interattiva può caricare .bashrc, .zshrc, gestori SDK, gestori di versioni linguistiche e voci PATH personalizzate. Una GUI avviata dal desktop potrebbe non caricare nulla di tutto ciò. Git stesso legge gli stessi file di configurazione, ma gli hook e i credential helper potrebbero vedere un mondo diverso.

Per eseguire il debug, crea un hook temporaneo che stampi l'ambiente in un file locale:

#!/usr/bin/env bash
{
  date
  pwd
  git --version
  git config --list --show-origin
  env | sort
} > /tmp/git-hook-debug.log
exit 1

Esegui l'azione Git dall'IDE, poi ispeziona /tmp/git-hook-debug.log. Rimuovi l'hook dopo. Questo ti dice cosa Git e l'hook hanno effettivamente visto, invece di ciò che vede il tuo terminale.

Per problemi di identità nei client GUI, controlla se lo strumento ha le proprie impostazioni Git. Alcuni client usano Git di sistema; altri includono Git o memorizzano l'identità dell'utente nelle preferenze dell'applicazione. Se il client sta facendo commit tramite Git, git log --format=fuller -1 mostrerà l'autore e il committer risultanti. Questo aiuta a separare "la configurazione Git era sbagliata" da "la GUI ha usato la propria impostazione".

In caso di dubbio, rendi esplicite le impostazioni locali del repository per i progetti che contano:

git config --local user.email "[email protected]"
git config --local core.hooksPath .githooks

La configurazione locale riduce le sorprese perché viaggia con i metadati del repository su quella macchina. Non viene ancora committata, quindi le regole condivise dovrebbero risiedere in file tracciati come .gitattributes, .editorconfig, script hook e documentazione del progetto.

Mantieni una Baseline Conosciuta e Funzionante

Quando i problemi di configurazione continuano a ripresentarsi, salva una piccola baseline conosciuta e funzionante per le tue macchine. Non deve essere sofisticata. Un ~/.gitconfig commentato con la tua identità, editor, comportamento predefinito del branch, credential helper e inclusioni è sufficiente. Poi, quando un nuovo laptop si comporta diversamente, puoi confrontare invece di riscoprire ogni impostazione.

I controlli di baseline utili includono:

git config --global --list --show-origin
git config --global --get core.editor
git config --global --get init.defaultBranch
git config --global --get-all credential.helper

Fai attenzione a copiare la configurazione da internet o da un collega. Gli alias potrebbero presupporre strumenti che non hai. I credential helper sono specifici della piattaforma. Le impostazioni di terminazione di riga potrebbero essere giuste per il loro sistema operativo e sbagliate per il tuo. Tratta la configurazione di Git come quella della shell: prendi in prestito idee, ma comprendi ogni riga prima di mantenerla.

Per i manutentori del progetto, la soluzione migliore è spostare le aspettative condivise fuori dalla configurazione personale. Metti le terminazioni di riga in .gitattributes, la formattazione nella configurazione del formattatore, i file ignorati in .gitignore e i controlli richiesti in CI. Meno un progetto dipende da impostazioni globali invisibili, meno ticket di configurazione crea.

Quando cambi un'impostazione per risolvere un problema, annota se era locale o globale. Molti misteri futuri di Git iniziano con una buona correzione locale temporanea che nessuno ricorda sei mesi dopo.