Fork e upstream di Git: istruzioni e un suggerimento interessante
Nicola Paolucci
Developer Advocate
Il fork dei progetti per apportare le tue modifiche ti consentono di integrare facilmente i tuoi contributi. Tuttavia, se non stai inviando di nuovo quelle modifiche a monte, il che significa rispedirle al repository principale, rischi di perderne traccia, il che può causare righe divergenti nel tuo repository. Per assicurarti che tutti i collaboratori attingano alla stessa posizione, devi conoscere alcuni principi su come il forking git interagisce con git upstream. In questo blog, ti presenterò le nozioni di base, alcuni trucchi e ti lascerò anche un suggerimento interessante per portarti un passo avanti a tutti.
Git upstream: tieniti aggiornato e contribuisci
Vorrei iniziare descrivendo in dettaglio una configurazione comune e il flusso di lavoro più semplice per interagire con i repository upstream
.
In una configurazione standard, generalmente hai un remoto di origine
e un remoto
upstream, quest'ultimo è il guardiano del progetto o l'origine di riferimento a cui desideri contribuire.
Innanzitutto, verifica di aver già configurato un remoto per il repository upstream
e, si spera, anche un'origine
:
git remote -v
origin git@bitbucket.org:my-user/some-project.git (fetch)
origin git@bitbucket.org:my-user/some-project.git (push)
Se non hai un upstream
, puoi aggiungerlo facilmente con il comando remote
:
git remote add upstream git@bitbucket.org:some-gatekeeper-maintainer/some-project.git
materiale correlato
Come spostare un repository Git completo
Scopri la soluzione
Impara a utilizzare Git con Bitbucket Cloud
Verifica che il remoto sia aggiunto correttamente:
git remote -v
origin git@bitbucket.org:my-user/some-project.git (fetch)
origin git@bitbucket.org:my-user/some-project.git (push)
upstream git@bitbucket.org:some-gatekeeper-maintainer/some-project.git (fetch)
upstream git@bitbucket.org:some-gatekeeper-maintainer/some-project.git (push)
Ora puoi raccogliere le ultime modifiche del repository upstream
con fetch
. Ripeti l'operazione ogni volta che vuoi ricevere aggiornamenti:
Se il progetto ha tag che non sono stati uniti a main, dovresti utilizzare anche: git fetch upstream --tags.
git fetch upstream
In genere, vorrai mantenere il tuo branch main
locale come equivalente prossimo di quello main
upstream
ed eseguire qualsiasi lavoro nei branch delle funzionalità, poiché potrebbero in seguito diventare pull request.
A questo punto, non importa se usi merge
o rebase
, poiché il risultato sarà in genere lo stesso. Usiamo merge
:
git checkout main
git merge upstream/main
Quando vuoi condividere un po' di lavoro con i manutentori upstream
del tuo branch main
, crea un branch di funzionalità. Quando sei soddisfatto, invialo al tuo repository remoto.
Puoi anche usare rebase
e quindi merge
per assicurarti che l'upstream
abbia un set pulito di commit (idealmente uno) da valutare:
git checkout -b feature-x
#some work and some commits happen
#some time passes
git fetch upstream
git rebase upstream/main
Pubblicare con git fork
Dopo i passaggi precedenti, pubblica il tuo lavoro nel fork remoto con un semplice push
:
git push origin feature-x
git push -f origin feature-x
Personalmente preferisco mantenere la cronologia il più pulita possibile e optare per l'opzione tre, ma team diversi hanno flussi di lavoro diversi. Nota: fallo solo quando lavori con il tuo fork. Riscrivere la cronologia dei repository e dei branch condivisi è qualcosa che non dovresti MAI fare.
Suggerimento del giorno: numeri di anticipi/ritardi nel prompt
Dopo un'operazione fetch
, git status
ti mostra quanti commit sono in anticipo o in ritardo rispetto al branch remoto
sincronizzato. Non sarebbe bello se potessi vedere queste informazioni nel tuo fedele prompt dei comandi? Lo pensavo anch'io, così ho iniziato a usare bash
per riuscirci.
Ecco come apparirà sul tuo prompt una volta configurato:
nick-macbook-air:~/dev/projects/stash[1|94]$
E questo è ciò che devi aggiungere al tuo .bashrc
o equivalente, solo una singola funzione:
function ahead_behind {
curr_branch=$(git rev-parse --abbrev-ref HEAD);
curr_remote=$(git config branch.$curr_branch.remote);
curr_merge_branch=$(git config branch.$curr_branch.merge | cut -d / -f 3);
git rev-list --left-right --count $curr_branch...$curr_remote/$curr_merge_branch | tr -s '\t' '|';
}
export PS1="\h:\w[\$(ahead_behind)]$"
Funzionamento interno
Per chi ama i dettagli e le spiegazioni ecco il funzionamento effettivo:
Otteniamo il nome simbolico dell'attuale HEAD, ovvero il branch attuale:
curr_branch=$(git rev-parse --abbrev-ref HEAD);
Otteniamo il remoto a cui punta il branch attuale:
curr_remote=$(git config branch.$curr_branch.remote);
Otteniamo il branch in cui questo remoto dovrebbe essere sottoposto a merge (con un trucco Unix comodo per scartare tutto fino all'ultima barra [/] inclusa):
curr_merge_branch=$(git config branch.$curr_branch.merge | cut -d / -f 3);
Ora abbiamo ciò di cui abbiamo bisogno per raccogliere il numero di conteggi per i commit in anticipo o in ritardo:
git rev-list --left-right --count $curr_branch...$curr_remote/$curr_merge_branch | tr -s '\t' '|';
Usiamo il vecchio comando Unix tr
per convertire il TAB
in un separatore |
.
Guida introduttiva a git upstream
Questa è una guida di base su git upstream
: come configurare un git upstream, creare un nuovo branch, raccogliere le modifiche, pubblicare con git fork e un buon consiglio su quanti commit in anticipo/ritardo sono presenti per il tuo branch remoto.
Bitbucket Data Center include la sincronizzazione dei fork, che sostanzialmente solleva gli sviluppatori dall'onere di tenersi aggiornati sui propri fork; Bitbucket Cloud ha invece una semplice sincronizzazione in 1 passaggio. Dai un'occhiata!
Condividi l'articolo
Argomento successivo
Letture consigliate
Aggiungi ai preferiti queste risorse per ricevere informazioni sui tipi di team DevOps e aggiornamenti continui su DevOps in Atlassian.