Definizione di "downstream" e "upstream"


902

Ho iniziato a giocare con Git e ho trovato i termini "upstream" e "downstream". Li ho già visti ma non li ho mai capiti fino in fondo. Cosa significano questi termini nel contesto degli SCM ( strumenti di gestione della configurazione del software ) e del codice sorgente?


13
Esistono due contesti diversi per upstream / downstream in git: telecomandi e tempo / storia. A monte / a valle rispetto ai telecomandi è, il repository a valle verrà estratto dal repository a monte (le modifiche scenderanno a valle in modo naturale). A monte / a valle rispetto al tempo / alla storia può essere fonte di confusione, perché a monte nel tempo significa a valle nella storia e viceversa (la terminologia della genealogia qui funziona molto meglio - genitore / antenato / figlio / discendente).
charlesreid1,

6
Correlati: cosa significa "upstream"? presso OS
Kenorb,

5
Correlati: Differenza tra origine e upstream su gitHub
RBT

Risposte:


703

In termini di controllo del codice sorgente, sei " downstream " quando copi (clone, checkout, ecc.) Da un repository. Le informazioni scorrevano "a valle" verso di te.

Quando si apportano modifiche, di solito si desidera rinviarle "a monte ", in modo che entrino in quel repository in modo che tutti gli utenti che provengono dalla stessa fonte lavorino con tutte le stesse modifiche. Questo è principalmente un problema sociale di come tutti possono coordinare il proprio lavoro piuttosto che un requisito tecnico di controllo delle fonti. Vuoi inserire le tue modifiche nel progetto principale, quindi non stai monitorando linee di sviluppo divergenti.

A volte leggerai dei gestori di pacchetti o release (le persone, non lo strumento) parlando dell'invio di modifiche a "upstream". Questo di solito significa che hanno dovuto adattare le fonti originali in modo da poter creare un pacchetto per il loro sistema. Non vogliono continuare ad apportare tali modifiche, quindi se li inviano "a monte" alla fonte originale, non dovrebbero affrontare lo stesso problema nella prossima versione.


116
"Download" e "upload" sono verbi. "A monte" e "a valle" descrivono una posizione relativa.
brian d foy,

2
Direi che upstream e downstream sono aggettivi
Crt

8
Sono aggettivi quando sono usati come modificatori, ma quei termini sono spesso usati come sostantivi.
brian d foy,

2
Le parole di @MycrofD possono essere usate come aggettivi e nomi a seconda del contesto
reggaeguitar,

1
Questo è principalmente un problema sociale piuttosto che un requisito tecnico . Allora perché esiste un'opzione -ucome git push --set-upstream origin masterse non fosse un requisito tecnico ? Possiamo push -u origino meno push origin, quindi è un requisito tecnico. Ma qual è la differenza?
Verde

249

Quando leggi nella git tagpagina man :

Un aspetto importante di git è che è distribuito, e la sua distribuzione in gran parte significa che non vi è alcun "upstream" o "downstream" intrinseco nel sistema.

, ciò significa semplicemente che non esiste un repository upstream o repository downstream assoluto .
Tali nozioni sono sempre relative tra due repository e dipendono dal modo in cui i dati scorrono:

Se "yourRepo" ha dichiarato "otherRepo" come remoto, quindi :

  • stai estraendo da "otherRepo" a monte ("otherRepo" è "upstream da te", e sei "downstream per otherRepo").
  • stai spingendo verso monte ("otherRepo" è ancora "a monte", dove le informazioni ora tornano a).

Nota "da" e "per": non sei solo "a valle", sei "a valle da / a ", quindi l'aspetto relativo.


La svolta del DVCS (Distributed Version Control System) è: non hai idea di cosa sia effettivamente a valle, a parte il tuo repository relativo ai repository remoti che hai dichiarato.

  • sai cos'è a monte (i repository da cui stai estraendo o spingendo)
  • non sai di cosa sia fatto il downstream (gli altri repository che effettuano il pull o il push del repository ).

Fondamentalmente:

In termini di " flusso di dati ", il repository si trova nella parte inferiore ("downstream") di un flusso proveniente da repository a monte ("pull from") e che torna a (lo stesso o altro) repository a monte ("push to" ).


È possibile vedere un'illustrazione nella git-rebasepagina man con il paragrafo "RECUPERO DALLA REVISIONE DI UPSTREAM":

Significa che stai effettuando il pull da un repository "a monte" in cui ha avuto luogo un rebase , e tu (il repository "a valle") sei bloccato con la conseguenza (molti commit duplicati, perché il ramo riformato a monte ha ricreato i commit dello stesso ramo che hai avere localmente).

Ciò è negativo perché per un repository "upstream" possono esserci molti repository downstream (ovvero repository che estraggono da quello upstream, con il ramo rinnovato), tutti potenzialmente in grado di gestire i commit duplicati.

Ancora una volta, con l'analogia del "flusso di dati", in un DVCS, un comando errato "a monte" può avere un " effetto a catena " a valle.


Nota: questo non è limitato ai dati.
Si applica anche ai parametri , poiché i comandi git (come quelli "porcellana") spesso chiamano internamente altri comandi git (quelli "idraulici"). Vedi la rev-parsepagina man :

Molti comandi di git porcellanato prendono una combinazione di flag (cioè parametri che iniziano con un trattino ' -') e parametri pensati per il git rev-listcomando sottostante che usano internamente e flag e parametri per gli altri comandi che usano a vallegit rev-list . Questo comando viene utilizzato per distinguerli.


15
si tira da monte, e si spinge a monte. spingere verso valle mi sembra molto sbagliato
Knittl,

1
@knittl: hai ragione. Ho riformulato la mia risposta per illustrare meglio il ruolo del repository "upstream" rispetto al repository locale (e "downstream").
VonC

85

Monitoraggio a monte (in relazione a)

Il termine upstream ha anche un significato inequivocabile per quanto riguarda la suite di strumenti GIT, in particolare per quanto riguarda il tracciamento

Per esempio :

   $git rev-list --count --left-right "@{upstream}"...HEAD
   >4   12

stamperà (l'ultimo valore memorizzato nella cache di) il numero di commit dietro (a sinistra) e in avanti (a destra) del ramo di lavoro corrente, relativamente al ( se presente ) ramo remoto che sta attualmente monitorando per questo ramo locale. In caso contrario verrà stampato un messaggio di errore:

    >error: No upstream branch found for ''
  • Come è già stato detto, potresti avere un numero qualsiasi di telecomandi per un repository locale, ad esempio, se esegui il fork di un repository da github, quindi emetti una "richiesta pull", avrai sicuramente almeno due: origin(il tuo repository biforcato su github) e upstream(il repository su github da cui hai effettuato il fork). Questi sono solo nomi intercambiabili, solo l'URL 'git @ ...' li identifica.

Le tue .git/configletture:

   [remote "origin"]
       fetch = +refs/heads/*:refs/remotes/origin/*
       url = git@github.com:myusername/reponame.git
   [remote "upstream"]
       fetch = +refs/heads/*:refs/remotes/upstream/*
       url = git@github.com:authorname/reponame.git
  • D'altra parte, il significato di @ {upstream} per GIT è unico:

è "il ramo" (se presente) su "detto telecomando" , che sta monitorando il "ramo corrente" sul "repository locale" .

È il ramo da cui prendi / tira ogni volta che emetti un semplice git fetch/ git pull, senza argomenti.

Supponiamo di voler impostare l'origine / il master del ramo remoto in modo che sia il ramo di tracciamento per il ramo principale locale che hai estratto. Emetti solo:

   $ git branch --set-upstream  master origin/master
   > Branch master set up to track remote branch master from origin.

Questo aggiunge 2 parametri in .git/config:

   [branch "master"]
       remote = origin
       merge = refs/heads/master

ora prova (a condizione che il telecomando "upstream" abbia un ramo "dev")

   $ git branch --set-upstream  master upstream/dev
   > Branch master set up to track remote branch dev from upstream.

.git/config ora legge:

   [branch "master"]
       remote = upstream
       merge = refs/heads/dev

git-push(1)Pagina del manuale :

   -u
   --set-upstream

Per ogni ramo aggiornato o inviato correttamente, aggiungi il riferimento upstream (tracking) , usato da git-pull (1) senza argomenti e altri comandi. Per ulteriori informazioni, vedere branch.<name>.mergein git-config (1).

git-config(1)Pagina del manuale :

   branch.<name>.merge

Definisce, insieme a branch.<name>.remote, il ramo a monte per il ramo dato. Indica a git fetch / git pull / git rebase quale ramo unire e può anche influenzare git push (vedi push.default). \ (...)

   branch.<name>.remote

Quando si trova nel ramo <nome>, indica a git fetch e git push da quale telecomando prelevare / push. L'impostazione predefinita è origine se non è configurato alcun telecomando. l'origine viene utilizzata anche se non ci si trova su alcun ramo.

A monte e Push (Gotcha)

dai un'occhiata alla git-config(1)pagina del manuale

   git config --global push.default upstream
   git config --global push.default tracking  (deprecated)

Questo per evitare spinte accidentali verso rami che non sei ancora pronto a spingere.


4
Estratto dal git branch --help2018:As this option had confusing syntax, it is no longer supported. Please use --track or --set-upstream-to instead.
zezollo,

59

È un po 'di terminologia informale.

Per quanto riguarda Git, ogni altro repository è solo un telecomando.

In generale, a monte è da dove hai clonato (l'origine). Downstream è qualsiasi progetto che integri il tuo lavoro con altri lavori.

I termini non sono limitati ai repository Git.

Ad esempio, Ubuntu è un derivato Debian, quindi Debian è a monte per Ubuntu.


51

A monte chiamato dannoso

C'è, purtroppo, un altro uso di "upstream" a cui le altre risposte qui non riescono, vale a dire fare riferimento alla relazione genitore-figlio dei commit all'interno di un repository. Scott Chacon nel libro Pro Git è particolarmente incline a questo, e i risultati sono sfortunati. Non imitare questo modo di parlare.

Ad esempio, dice di una fusione risultante in un avanzamento rapido che ciò accade perché

il commit indicato dal ramo in cui ti sei unito era direttamente a monte del commit in cui ti trovi

Vuole dire che il commit B è l'unico figlio dell'unico figlio di ... dell'unico figlio del commit A, quindi per unire B in A è sufficiente spostare il riferimento A per indicare il commit B. Perché questa direzione dovrebbe essere chiamato "a monte" piuttosto che "a valle", o perché la geometria di un tale grafico a linea retta pura debba essere descritta "direttamente a monte", è completamente poco chiara e probabilmente arbitraria. (La pagina man per git-mergefa un lavoro di gran lunga migliore nel spiegare questa relazione quando dice che "l'attuale diramazione è un antenato del commit chiamato." Questo è il genere di cose che Chacon avrebbe dovuto dire.)

In effetti, lo stesso Chacon sembra usare "downstream" in seguito per indicare esattamente la stessa cosa, quando parla di riscrivere tutti i commit figlio di un commit eliminato:

È necessario riscrivere tutti i commit a valle da 6df76 per rimuovere completamente questo file dalla cronologia di Git

Fondamentalmente sembra non avere alcuna idea chiara di cosa significhi "a monte" e "a valle" quando si riferisce alla storia delle commesse nel tempo. Questo uso è informale, quindi, e non deve essere incoraggiato, poiché è solo confuso.

È perfettamente chiaro che ogni impegno (tranne uno) ha almeno un genitore e che i genitori dei genitori sono quindi antenati; e nella direzione opposta, i commessi hanno figli e discendenti. Questa è una terminologia accettata e descrive la direzionalità del grafico in modo inequivocabile, quindi è il modo di parlare quando si desidera descrivere come i commit si relazionano tra loro all'interno della geometria del grafico di un repository. In questa situazione non utilizzare "a monte" o "a valle" liberamente.

[Nota aggiuntiva: ho pensato al rapporto tra la prima frase di Chacon che cito sopra e la git-mergepagina man, e mi viene in mente che il primo potrebbe essere basato su un malinteso del secondo. La pagina man continua descrivendo una situazione in cui l'uso di "upstream" è legittimo: l'avanzamento rapido spesso si verifica quando "stai monitorando un repository upstream, non hai commesso modifiche locali e ora vuoi passare a una versione più recente revisione a monte. " Quindi forse Chacon ha usato "upstream" perché l'ha visto qui nella pagina man. Ma nella pagina man c'è un repository remoto; non esiste un repository remoto nell'esempio citato di avanzamento rapido di Chacon, solo un paio di filiali create localmente.]


14
Anche la pagina man git-rebase soffre di questo sovraccarico: il commit che viene verificato prima del rebasing viene definito "upstream". Anche questo potrebbe aver influito sull'uso di Chacon.
uscita

@outis strange - nella documentazione git html, il ramo è stato estratto prima che il rebasing sia indicato come <branch>.
Jesper Matthiesen,

Buon punto. Sarebbe di grande aiuto raccogliere qualche "terminologia git" comune da qualche parte. Soprattutto per i neofiti (o ppl che contribuiscono a git). Mi avrebbe fatto risparmiare tempo per abituarmi alla formulazione delle pagine man di git.
SebNag,


1
Sono venuto qui dai git-rebasedocumenti perché ero totalmente confuso perché un ref di commit sarebbe stato chiamato "a monte" lì (in realtà, dubitavo di me stesso perché non avevo mai visto questa terminologia prima). Grazie @outis & @matt per aver chiarito le cose!
Borek Bernard,

-1

In generale;

  • a monte è verso la fonte
  • a valle è verso il lavandino o la destinazione

Questo vale per tutti i sistemi ad albero, compresi i sistemi di controllo del codice sorgente.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.