Definizione di “downstream” e “upstream”

Ho iniziato a giocare con Git e ho trovato i termini “upstream” e “downstream”. Li ho già visti prima, ma non li capisco mai completamente. Cosa significano questi termini nel contesto degli SCM (strumenti di gestione della configurazione del software ) e del codice sorgente?

    In termini di controllo del codice sorgente, si è “a valle ” quando si copia (clonazione, checkout, ecc.) Da un repository. Le informazioni scorrevano “a valle”.

    Quando apporti delle modifiche, di solito vuoi rispedirle “a monte ” in modo che possano essere inserite in quel repository in modo che tutti quelli che utilizzano la 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 del controllo del codice sorgente. Vuoi ottenere le tue modifiche nel progetto principale in modo da non tracciare linee di sviluppo divergenti.

    A volte leggi i gestori di pacchetti o release (le persone, non lo strumento) che parlano di invio di modifiche a “upstream”. Questo di solito significa che dovevano aggiustare le fonti originali in modo che potessero creare un pacchetto per il loro sistema. Non vogliono continuare a fare quei cambiamenti, quindi se li inviano “upstream” alla fonte originale, non dovrebbero avere a che fare con lo stesso problema nella prossima versione.

    Quando leggi la pagina man di git tag :

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

    , questo significa semplicemente che non esiste un repository assoluto upstream o un repository downstream.
    Queste nozioni sono sempre relative tra due repository e dipendono dal modo in cui i flussi di dati:

    Se “yourRepo” ha dichiarato “otherRepo” come remoto, quindi :

    • stai tirando da upstream “otherRepo” (“otherRepo” è “upstream da te”, e tu sei “downstream for otherRepo”).
    • stai spingendo verso monte (“otherRepo” è ancora “a monte”, dove ora torna l’informazione).

    Nota “da” e “per”: non sei solo “a valle”, sei “a valle di / per “, quindi l’aspetto relativo.


    Il twist del DVCS (Distributed Version Control System) è: non hai idea di cosa sia realmente downstream, oltre al tuo repository rispetto ai repository remoti che hai dichiarato.

    • sai cosa è upstream (i repository da cui stai tirando o spingi)
    • non sai di cosa è fatto downstream (gli altri repository che tirano o spingono al tuo repository ).

    Fondamentalmente:

    In termini di ” stream di dati “, il repository è in fondo (“downstream”) di un stream proveniente da repository upstream (“pull from”) e torna a (lo stesso o altro) repository upstream (“push to” ).


    Puoi vedere un’illustrazione nella pagina man di git-rebase con il paragrafo “RECOVERING FROM REPROGRUPPO DI UPSTREAM”:

    Significa che stai tirando da un repo “upstream” in cui è avvenuto un rebase , e tu (il repository “downstream”) è bloccato con le conseguenze (un sacco di commit duplicati, perché il ramo rebased upstream ha ricreato i commit dello stesso ramo tu avere localmente).

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

    Di nuovo, con l’analogia del “stream 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 , dato che i comandi git (come quelli “di porcellana”) spesso chiamano internamente altri comandi git (quelli “idraulici”). Vedi la pagina man rev-parse :

    Molti comandi git di porcellana prendono una combinazione di flag (cioè parametri che iniziano con un trattino ‘ - ‘) e parametri intesi per il comando git rev-list sottostante che usano internamente e flag e parametri per gli altri comandi che usano a valle di git rev-list . Questo comando è usato per distinguere tra loro.

    Monitoraggio a monte (correlato a)

    Il termine upstream ha anche un significato non ambiguo in termini 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 avanti (a destra) del ramo di lavoro corrente, relativo al ( se presente ) ramo remoto di monitoraggio corrente per questo ramo locale. Stamperà altrimenti 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 forzi un repository da github, quindi emetti una “richiesta pull”, ne hai sicuramente almeno due: origin (il tuo repository biforcuto su github) e upstream (il repository su github da cui si è biforcati). Questi sono solo nomi intercambiabili, solo l’url ‘git @ …’ li identifica.

    Il tuo .git/config legge:

      [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 esiste) su ‘said remote’ , che sta rintracciando il ‘current branch’ sul tuo ‘repository locale’ .

    È il ramo che si recupera / tira da ogni volta che si rilascia un semplice git fetch / git pull , senza argomenti.

    Supponiamo di voler impostare l’origine / master del ramo remoto come ramo di tracciamento per il ramo master locale che hai estratto. Solo problema:

      $ 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 (il telecomando ‘upstream’ è fornito di un ramo ‘dev’)

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

    .git/config ora dice:

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

    git-push(1) Pagina manuale :

      -u --set-upstream 

    Per ogni ramo aggiornato o inserito correttamente, aggiungi il riferimento di upstream (tracciamento) , usato da git-pull (1) senza argomenti e altri comandi. Per ulteriori informazioni, consultare branch..merge in git-config (1).

    git-config(1) Pagina manuale :

      branch..merge 

    Definisce, insieme al branch..remote , il ramo upstream per il ramo specificato. Indica a git fetch / git pull / git rebase quale ramo da unire e può anche influenzare git push (vedi push.default). \ (…)

      branch..remote 

    Quando si trova nel ramo , dice a git fetch e git push quale telecomando recuperare da / push a. L’origine è predefinita se non è configurato alcun telecomando. l’origine viene utilizzata anche se non ci si trova in nessun ramo.

    Upstream e Push (Gotcha)

    dare un’occhiata alla pagina di manuale di git-config(1)

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

    Questo serve a prevenire spinte accidentali ai rami che non sei ancora pronto a spingere.

    È un po ‘di terminologia informale.

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

    In generale, a monte è dove hai clonato (l’origine). Downstream è un progetto che integra il tuo lavoro con altre opere.

    I termini non sono limitati ai repository Git.

    Ad esempio, Ubuntu è una derivata di Debian, quindi Debian è a monte per Ubuntu.

    Upstream Called Harmful

    C’è, ahimè, un altro uso di “upstream” che le altre risposte qui non stanno ottenendo, vale a dire fare riferimento alla relazione genitore-figlio di commit all’interno di un repository. Scott Chacon nel libro Pro Git è particolarmente incline a questo, ed 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 fuso era direttamente a monte del commit su cui ti trovi

    Vuole dire che commit B è l’unico figlio dell’unico figlio di … dell’unico figlio di commit A, quindi per unire B in A è sufficiente spostare il riferimento A per puntare su commit B. Perché questa direzione dovrebbe essere chiamato “a monte” piuttosto che “a valle”, o perché la geometria di un tale lineare puro dovrebbe essere descritta “direttamente a monte”, è completamente poco chiara e probabilmente arbitraria. (La pagina man di git-merge fa un lavoro molto migliore di spiegare questa relazione quando dice che “l’attuale capo della branca è un antenato del commit specificato.” Questo è il genere di cose che Chacon avrebbe dovuto dire.)

    Infatti, Chacon stesso sembra usare “downstream” più tardi per dire esattamente la stessa cosa, quando parla di riscrivere tutti i commit di un commit cancellato da parte di un bambino:

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

    Fondamentalmente sembra non avere una chiara idea di cosa intenda per “upstream” e “downstream” quando si riferisce alla storia dei commit nel tempo. Questo uso è informale, quindi, e non deve essere incoraggiato, in quanto è solo fonte di confusione.

    È perfettamente chiaro che ogni impegno (tranne uno) ha almeno un genitore e che i genitori dei genitori sono quindi antenati; e nell’altra direzione, i commetti hanno figli e discendenti. Questa è una terminologia accettata e descrive in modo inequivocabile la direzionalità del grafico, quindi questo è il modo di parlare quando si desidera descrivere come i commit si relazionano tra loro all’interno della geometria del grafico di un repository. Non utilizzare “upstream” o “downstream” in questa situazione.

    [Nota aggiuntiva: ho pensato alla relazione tra la prima frase di Chacon che cito sopra e la pagina man di git-merge , e mi viene in mente che la prima potrebbe essere basata su un fraintendimento di quest’ultima. La pagina man continua descrivendo una situazione in cui l’uso di “upstream” è legittimo: l’avanzamento veloce si verifica spesso quando “si sta monitorando un repository upstream, non si sono commesse modifiche locali e ora si desidera aggiornare a un nuovo revisione a monte. ” Quindi forse Chacon usava “upstream” perché lo vedeva qui nella pagina man. Ma nella pagina man c’è un repository remoto; non esiste un repository remoto nell’esempio citato di avvio rapido di Chacon, solo un paio di rami creati localmente.]