Definição de “downstream” e “upstream”

Eu comecei a jogar com o Git e encontrei os termos “upstream” e “downstream”. Eu já vi isso antes, mas nunca os entendi completamente. O que esses termos significam no contexto de SCMs (ferramentas de gerenciamento de configuração de software ) e código-fonte?

Em termos de controle de origem, você é ” downstream ” quando copia (clone, checkout, etc) de um repository. A informação fluiu “a jusante” para você.

Quando você faz mudanças, você normalmente quer enviá-las de volta ” upstream ” para que elas façam parte do repository, de modo que todos os usuários da mesma fonte estejam trabalhando com as mesmas alterações. Isso é principalmente uma questão social de como todos podem coordenar seu trabalho, em vez de um requisito técnico de controle de origem. Você quer colocar suas alterações no projeto principal para não rastrear linhas de desenvolvimento divergentes.

Às vezes você vai ler sobre pacotes ou gerentes de lançamento (as pessoas, não a ferramenta) falando sobre o envio de alterações para “upstream”. Isso geralmente significa que eles precisavam ajustar as fonts originais para criar um pacote para o sistema. Eles não querem continuar fazendo essas alterações, portanto, se os enviarem “upstream” para a fonte original, eles não precisarão lidar com o mesmo problema na próxima versão.

Quando você lê na página man do git tag :

Um aspecto importante do git é que ele é distribuído e, sendo distribuído em grande parte, significa que não há “upstream” ou “downstream” inerente no sistema.

, isso significa simplesmente que não há um repository upstream absoluto ou um repo downstream.
Essas noções são sempre relativas entre dois repos e dependem da maneira como os dados fluem:

Se “yourRepo” tiver declarado “otherRepo” como remoto, então :

  • você está puxando de upstream “otherRepo” (“otherRepo” é “upstream from you”, e você está “downstream for otherRepo”).
  • você está empurrando para upstream (“otherRepo” ainda é “upstream”, onde as informações agora retornam).

Observe o “de” e “para”: você não é apenas “downstream”, você é “downstream de / para “, daí o aspecto relativo.


O diferencial do DVCS (Distributed Version Control System) é: você não tem idéia do que é o downstream, além do seu próprio repo em relação aos repositorys remotos que você declarou.

  • você sabe o que é upstream (os repositorys dos quais você está puxando ou empurrando)
  • você não sabe do que é feito o downstream (os outros repos puxando ou empurrando para o seu repo ).

Basicamente:

Em termos de ” stream de dados “, o repo está na parte inferior (“downstream”) de um stream proveniente de repos upstream (“pull from”) e voltando para (o mesmo ou outro) repos upstream (“push to”) ).


Você pode ver uma ilustração na página man do git-rebase com o parágrafo “RECUPERANDO DO REINTERS DA UPSTREAM”:

Isso significa que você está puxando de um repository “upstream” onde ocorreu um rebase , e você (o repository “downstream”) está preso à conseqüência (muitos commits duplicados, porque o branch rebaseed upstream recriava os commits do mesmo branch que você tem localmente).

Isso é ruim porque para um repository “upstream”, pode haver muitos repositorys downstream (isto é, repos extraídos do upstream, com o branch rebased), todos eles tendo potencialmente para lidar com os commits duplicados.

Novamente, com a analogia do “stream de dados”, em um DVCS, um comando incorreto “upstream” pode ter um ” efeito cascata ” downstream.


Nota: isto não está limitado aos dados.
Também se aplica a parâmetros , como os comandos git (como os de porcelana) freqüentemente chamam internamente outros comandos git (os “encanadores”). Veja a página man rev-parse :

Muitos comandos de porcelana tomam mistura de flags (ie parâmetros que começam com um traço ‘ - ‘) e parâmetros significados para o comando git rev-list eles usam internamente e flags e parâmetros para os outros comandos que usam downstream do git rev-list . Este comando é usado para distinguir entre eles.

Upstream (como relacionado a) Tracking

O termo upstream também tem algum significado não ambíguo como vem ao conjunto de ferramentas GIT, especialmente em relação ao rastreamento

Por exemplo :

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

imprimirá (o último valor em cache de) o número de confirmações atrás (à esquerda) e à frente (à direita) de sua ramificação de trabalho atual, em relação à ramificação remota de rastreamento atual ( se houver ) dessa ramificação local. Ele imprimirá uma mensagem de erro do contrário:

  >error: No upstream branch found for '' 
  • Como já foi dito, você pode ter qualquer número de controles remotos para um repository local, por exemplo, se você distribuir um repository do github e emitir um ‘pull request’, você certamente tem pelo menos dois: origin (seu repository bifurcado no github) e upstream (o repo no github que você bifurcou). Esses são apenas nomes intercambiáveis, apenas o URL ‘git @ …’ os identifica.

Seu .git/config lê:

  [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 
  • Por outro lado, o significado do @ {upstream} para o GIT é único:

é ‘o ramo’ (se houver) no ‘dito remoto’ , que está rastreando o ‘ramo atual’ no seu ‘repository local’ .

É o ramo que você busca / extrai sempre que você emite um simples git fetch / git pull , sem argumentos.

Digamos que você queira definir a origem / mestre da filial remota como a ramificação de rastreamento para a ramificação mestre local que você fez check-out. Apenas questão:

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

Isso adiciona 2 parâmetros em .git/config :

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

Agora tente (desde ‘upstream’ remoto tem um ramo ‘dev’)

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

.git/config agora lê:

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

git-push(1) Página do manual :

  -u --set-upstream 

Para cada ramificação que esteja atualizada ou enviada com sucesso, inclua referência de upstream (rastreamento) , usada por git-pull (1) sem argumentos e outros comandos. Para mais informações, veja branch..merge em git-config (1).

git-config(1) Página do manual :

  branch..merge 

Define, junto com a branch..remote , a ramificação upstream da ramificação especificada. Ele diz git fetch / git pull / git rebase que ramifica para mesclar e também pode afetar o git push (consulte push.default). \ (…)

  branch..remote 

Quando na ramificação , ele informa git fetch e git push para o qual o controle remoto deve buscar / empurrar para. O padrão é originar se nenhum controle remoto estiver configurado. origem também é usada se você não estiver em nenhum ramo.

Upstream e Push (Gotcha)

dê uma olhada no git-config(1) Manual Page

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

Isso evita que sejam pressionadas as ramificações acidentais que você ainda não está pronto para empurrar.

Isso é um pouco de terminologia informal.

No que diz respeito ao Git, todos os outros repositorys são apenas remotos.

De um modo geral, upstream é onde você clonou (a origem). Downstream é qualquer projeto que integre seu trabalho com outros trabalhos.

Os termos não estão restritos a repositorys Git.

Por exemplo, o Ubuntu é um derivado do Debian, então o Debian é o upstream do Ubuntu.

Upstream Chamado Nocivo

Há, infelizmente, outro uso de “upstream” que as outras respostas aqui não estão chegando, ou seja, para se referir ao relacionamento pai-filho de commits dentro de um repo. Scott Chacon no livro Pro Git é particularmente propenso a isso, e os resultados são lamentáveis. Não imite este modo de falar.

Por exemplo, ele diz de uma fusão resultante de um avanço rápido que isso acontece porque

o commit apontado pelo branch em que você se fundiu era diretamente upstream do commit no qual você está

Ele quer dizer que commitar B é o único filho do único filho de … do único filho de commit A, então mesclar B em A é suficiente mover o árbitro A para apontar para commitar B. Por que essa direção deve ser chamado de “upstream” em vez de “downstream”, ou por que a geometry de um gráfico linear tão puro deve ser descrito “diretamente a montante”, é completamente incerto e provavelmente arbitrário. (A man page do git-merge faz um trabalho muito melhor de explicar esse relacionamento quando diz que “o atual branch chefe é um ancestral do commit nomeado.” Esse é o tipo de coisa que Chacon deveria ter dito.)

De fato, o próprio Chacon parece usar “downstream” mais tarde para significar exatamente a mesma coisa, quando ele fala de rewrite todos os commits filhos de um commit deletado:

Você deve rewrite todos os commits downstream do 6df76 para remover completamente este arquivo do seu histórico do Git

Basicamente ele parece não ter nenhuma ideia clara do que ele quer dizer com “upstream” e “downstream” quando se refere ao histórico de commits ao longo do tempo. Este uso é informal, então, e não deve ser encorajado, pois é apenas confuso.

É perfeitamente claro que todo cometimento (exceto um) tem pelo menos um dos pais, e que os pais dos pais são, portanto, ancestrais; e na outra direção, os commits têm filhos e descendentes. Isso é terminologia aceita, e descreve a direcionalidade do grafo inequivocamente, então é assim que você fala quando quer descrever como os commits se relacionam entre si dentro da geometry do grafo de um repo. Não use “upstream” ou “downstream” livremente nesta situação.

[Nota adicional: Estive pensando sobre a relação entre a primeira sentença de Chacon que citei acima e a página de manual do git-merge , e me ocorre que a primeira pode ser baseada em um mal-entendido da segunda. A página man continua descrevendo uma situação em que o uso de “upstream” é legítimo: o avanço rápido geralmente acontece quando “você está rastreando um repository upstream, não efetuou alterações locais e deseja atualizar para um novo revisão upstream. ” Então talvez Chacon tenha usado “upstream” porque ele viu aqui na man page. Mas na página man existe um repository remoto; não há repository remoto no exemplo citado de Chacon de avanço rápido, apenas alguns ramos criados localmente.]

    Intereting Posts