Definição de "downstream" e "upstream"

902

Comecei a brincar com o Git e me deparei com os termos "upstream" e "downstream". Eu já os vi antes, mas nunca os entendi completamente. O que esses termos significam no contexto dos SCMs ( ferramentas de gerenciamento de configuração de software ) e no código-fonte?

brendan
fonte
13
Existem dois contextos diferentes para upstream / downstream no git: controles remotos e tempo / histórico. A montante / a jusante em relação aos controles remotos, o repositório a jusante será retirado do repositório a montante (as alterações fluirão a jusante naturalmente). A montante / a jusante em relação ao tempo / história pode ser confuso, porque a montante no tempo significa a jusante na história e vice-versa (a terminologia genealógica funciona muito melhor aqui - pai / ancestral / filho / descendente).
charlesreid1
6
Relacionado: O que significa 'upstream'? em OS
kenorb
5
Relacionado: Diferença entre origem e upstream no gitHub
RBT

Respostas:

703

Em termos de controle de origem, você fica "a jusante " quando copia (clone, checkout etc.) de um repositório. As informações fluíram "a jusante" para você.

Quando você faz alterações, geralmente deseja enviá-las de volta " upstream " para que elas entrem no repositório para que todos os que estão na mesma fonte trabalhem 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ê deseja incluir suas alterações no projeto principal para não acompanhar linhas de desenvolvimento divergentes.

Às vezes, você lerá sobre gerentes de pacote ou release (as pessoas, não a ferramenta) falando sobre o envio de alterações para "upstream". Isso geralmente significa que eles precisavam ajustar as fontes 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, não deverão ter que lidar com o mesmo problema no próximo lançamento.

brian d foy
fonte
116
"Download" e "upload" são verbos. "Upstream" e "downstream" descrevem uma posição relativa.
Brian d foy
2
Eu diria a montante ea jusante são adjetivos
Crt
8
São adjetivos quando usados ​​como modificadores, mas esses termos são frequentemente usados ​​como substantivos.
precisa
2
@MycrofD palavras pode ser usado como adjectivos e substantivos, dependendo do contexto
reggaeguitar
1
Isso é principalmente uma questão social, e não um requisito técnico . Então, por que existe uma opção -ucomo git push --set-upstream origin masterse não é um requisito técnico ? Podemos push -u originou não push origin, por isso é um requisito técnico. Mas qual a diferença?
Verde
249

Quando você lê na git tagpágina do manual :

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

, isso significa simplesmente que não há um repo absoluto a montante ou a jusante.
Essas noções são sempre relativas entre dois repositórios e dependem da maneira como os dados fluem:

Se "yourRepo" declarou "otherRepo" como remoto, então :

  • você está retirando do "otherRepo" a montante ("otherRepo" está "a montante de você" e está "a jusante do otherRepo").
  • você está empurrando para o upstream ("otherRepo" ainda está "upstream", para onde as informações agora retornam).

Observe o "de" e "para": você não é apenas "a jusante", você é "a jusante de / para ", daí o aspecto relativo.


A reviravolta do DVCS (Sistema de controle de versão distribuído) é: você não tem idéia do que é realmente o downstream, além de seu próprio repositório em relação aos repositórios remotos que você declarou.

  • você sabe o que é upstream (os repositórios dos quais você está puxando ou pressionando)
  • você não sabe do que é feito o downstream (os outros repositórios são retirados ou enviados para o repositório ).

Basicamente:

Em termos de " fluxo de dados ", seu repositório fica na parte inferior ("a jusante") de um fluxo proveniente de repositórios upstream ("pull from") e voltando para (o mesmo ou outro) repositório upstream ("push to" )


Você pode ver uma ilustração na git-rebasepágina do manual com o parágrafo "RECUPERANDO DO UPSTREAM REBASE":

Isso significa que você está retirando de um repo "upstream" onde ocorreu uma nova recuperação e você (o repo "downstream") fica com a conseqüência (muitas confirmações duplicadas, porque a ramificação reestruturada a montante recriou as confirmações da mesma ramificação que você localmente).

Isso é ruim porque, para um repo "upstream", pode haver muitos repositórios downstream (ou seja, repos retirados do upstream, com a ramificação rebased), todos tendo potencialmente para lidar com os commits duplicados.

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


Nota: isso não se limita aos dados.
Também se aplica a parâmetros , pois os comandos git (como os de "porcelana") costumam chamar internamente outros comandos de git (os de "encanamento"). Veja a rev-parsepágina de manual :

Muitos comandos git porcelainish usam mistura de sinalizadores (ou seja, parâmetros que começam com um traço ' -') e parâmetros destinados ao git rev-listcomando subjacente que eles usam internamente e sinalizadores e parâmetros para os outros comandos que eles usam a jusantegit rev-list . Este comando é usado para distinguir entre eles.

VonC
fonte
15
você puxa do montante e empurra para o montante. empurrando a sons jusante muito errado para mim
knittl
1
@knittl: você está certo. Eu reformulei minha resposta para ilustrar melhor o papel do repositório "upstream" em relação ao seu próprio repositório local (e "downstream").
VonC
85

Rastreamento a montante (como relacionado a)

O termo upstream também tem algum significado inequívoco no que diz respeito 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) do seu ramo de trabalho atual, em relação ao ( se houver ) que atualmente rastreia o ramo remoto para esse ramo local. Caso contrário, imprimirá uma mensagem de erro:

    >error: No upstream branch found for ''
  • Como já foi dito, você pode ter vários controles remotos para um repositório local; por exemplo, se você bifurcar um repositório no github e emitir uma 'solicitação pull', certamente terá pelo menos dois: origin(seu repositório bifurcado em github) e upstream(o repositório no github do qual você bifurcou). Esses são apenas nomes intercambiáveis, apenas o URL 'git @ ...' os identifica.

Suas .git/configleituras:

   [remote "origin"]
       fetch = +refs/heads/*:refs/remotes/origin/*
       url = [email protected]:myusername/reponame.git
   [remote "upstream"]
       fetch = +refs/heads/*:refs/remotes/upstream/*
       url = [email protected]:authorname/reponame.git
  • Por outro lado, o significado de @ {upstream} para GIT é único:

é 'o ramo' (se houver) no 'referido controle remoto' , que está rastreando o 'ramo atual' no seu 'repositório local' .

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

Digamos que você queira definir a origem / mestre da filial remota como a filial de rastreamento da filial principal local que você efetuou check-out. Basta emitir:

   $ 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 que o controle remoto 'upstream' tenha uma ramificação '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 atualizada ou enviada com êxito, adicione uma referência upstream (rastreamento) , usada pelo git-pull (1) sem argumentos e outros comandos. Para mais informações, consulte branch.<name>.mergegit-config (1).

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

   branch.<name>.merge

Define, juntamente com branch.<name>.remote, a ramificação upstream para a ramificação especificada. Ele informa ao git fetch / git pull / git rebase qual ramificação será mesclada e também pode afetar o git push (consulte push.default). \ (...)

   branch.<name>.remote

Quando no ramo <nome>, ele informa ao git fetch e git push qual controle remoto buscar de / push para. O padrão é origem 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 na git-config(1)página Manual

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

Isso evita empurrões acidentais para galhos que você ainda não está pronto para empurrar.

Peter Host
fonte
4
Trecho de a git branch --helppartir de 2018:As this option had confusing syntax, it is no longer supported. Please use --track or --set-upstream-to instead.
zezollo 13/10
59

Isso é um pouco de terminologia informal.

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

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

Os termos não estão restritos aos repositórios Git.

Por exemplo, o Ubuntu é um derivado do Debian, portanto, o Debian é upstream para o Ubuntu.

hasen
fonte
51

Chamado a montante prejudicial

Há, infelizmente, outro uso de "upstream" que as outras respostas aqui não estão alcançando, ou seja, referir-se à relação pai-filho de commits em um repo. Scott Chacon no livro Pro Git é particularmente propenso a isso, e os resultados são infelizes. Não imite esse modo de falar.

Por exemplo, ele diz de uma mesclagem que resulta em um avanço rápido que isso acontece porque

o commit apontado pelo ramo em que você mesclou estava diretamente a montante do commit em que você está

Ele quer dizer que o commit B é o filho único do filho único de ... do filho único do commit A, portanto, para mesclar B em A é suficiente mover o árbitro A para apontar para o commit B. Por que essa direção deve ser chamado de "upstream" em vez de "downstream", ou por que a geometria de um gráfico linear tão puro deve ser descrita "diretamente upstream", é completamente obscura e provavelmente arbitrária. (A página de manual git-mergefaz um trabalho muito melhor de explicar esse relacionamento quando diz que "o chefe do ramo atual é um ancestral do commit nomeado". Esse é o tipo de coisa que Chacon deveria ter dito.)

De fato, o próprio Chacon parece usar "downstream" posteriormente para significar exatamente a mesma coisa, quando ele fala em reescrever todos os child commit de um commit excluído:

Você deve reescrever todas as confirmações a jusante do 6df76 para remover totalmente esse arquivo do seu histórico do Git

Basicamente, ele parece não ter uma idéia clara do que ele quer dizer com "upstream" e "downstream" quando se refere à história dos commits ao longo do tempo. Esse uso é informal, portanto, e não deve ser incentivado, pois é apenas confuso.

É perfeitamente claro que todo comprometimento (exceto um) tem pelo menos um dos pais e que os pais dos pais são, portanto, ancestrais; e na outra direção, compromete-se a ter filhos e descendentes. Essa terminologia é aceita e descreve a direcionalidade do gráfico de forma inequívoca; portanto, é assim que você deve falar quando quiser descrever como as confirmações se relacionam entre si na geometria do gráfico de um repositório. Não use "upstream" ou "downstream" nessa situação.

[Nota adicional: estive pensando sobre a relação entre a primeira frase de Chacon que cito acima e a git-mergepágina de manual, e me ocorre que a primeira pode se basear em um mal-entendido da segunda. A página de manual 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 repositório upstream, não cometeu alterações locais e agora deseja atualizar para um novo revisão a montante ". Então, talvez Chacon tenha usado "upstream" porque ele viu aqui na página de manual. Mas na página de manual há um repositório remoto; não há repositório remoto no exemplo citado de Chacon de avanço rápido, apenas algumas ramificações criadas localmente.]

mate
fonte
14
A página de manual do git-rebase também sofre com essa sobrecarga: o commit que é feito check-out antes do rebasing é denominado "upstream". Isso também pode ter afetado o uso do Chacon.
Outis
@outis estranho - na documentação do git html, a ramificação efetuada check-out antes do rebase é chamada de <branch>.
Jesper Matthiesen
Bom ponto. Seria útil reunir "terminologia git" comum em algum lugar. Especialmente para iniciantes (ou pessoas que contribuem para o git). Teria me poupado um bom tempo me acostumando à redação das páginas de manual do git.
SebNag 26/02
@SebNag algo assim? linuxacademy.com/blog/linux/git-terms-explained
reggaeguitar
1
Vim aqui da git-rebasedocumentação porque eu estava totalmente confuso por que um árbitro de confirmação seria chamado de "upstream" lá (na verdade, eu estava me duvidando de não ter visto essa terminologia antes). Obrigado @outis & @matt por esclarecer as coisas!
Borek Bernard
0

Em geral;

  • a montante é em direção à fonte
  • a jusante é em direção à pia ou destino

Isso se aplica a todos os sistemas semelhantes a árvores, incluindo sistemas de controle de origem.

Stefan
fonte