Ramificação do Git: mestre vs. origem / mestre vs. controles remotos / origem / mestre

201

Acho que estou no caminho certo para entender os conceitos básicos do git.

Eu já configurei e clonei um repositório remoto. Também criei um repositório vazio do lado do servidor e vinculei meu repositório local a ele.

Meu problema é que não entendo a diferença entre:

  • origem / mestre vs. controles remotos / origem / mestre

Tanto quanto eu entendi, o mestre é uma filial local e os controles remotos / origem / mestre são remotos.

Mas o que exatamente é origem / mestre ?

John Rumpel
fonte
1
@ChristopherWallace: Você provocou duas perguntas no meta com a sua edição: " Nós realmente precisamos de uma tag [origin]? " E " Qual é o verdadeiro [Master]? ".
Deduplicator
@Duplicador Isso é um problema?
Nbro 01/07
@ChristopherWallace: Bem, muitos parecem pensar que as duas tags (a que você criou e a que você acabou de adicionar) são ruins. Por acaso eu concordo, mas talvez você tenha algo a acrescentar à discussão vinculada que não foi considerada. Se não, parece que sim.
Deduplicator
Pergunta de acompanhamento: Por que .git/refs/origin/masteralguma vez se afastou .git/refs/remotes/origin/master? Isso está acontecendo comigo agora e estou sendo expulso.
Paul

Respostas:

219

Pegue um clone de um repositório remoto e execute git branch -a(para mostrar todos os ramos que o git conhece). Provavelmente será algo parecido com isto:

* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/master

Aqui masterestá uma ramificação no repositório local. remotes/origin/masteré uma ramificação nomeada masterno controle remoto nomeado origin. Você pode se referir a isso como origin/master:

git diff origin/master..master

Você também pode se referir a ele como remotes/origin/master:

git diff remotes/origin/master..master

Essas são apenas duas maneiras diferentes de se referir à mesma coisa (aliás, esses dois comandos significam "mostre-me as alterações entre a masterfilial remota e minha masterfilial).

remotes/origin/HEADé o default branchpara o controle remoto nomeado origin. Isso permite que você simplesmente diga em originvez de origin/master.

larsks
fonte
5
Boa resposta. Eu acho que git branch -amostrar o ramo remoto como remotes/origin/masteré parcialmente porque o ref subjacente é armazenado .git/refs/remotes/origin(se não tiver sido compactado). Na minha opinião, a saída de git branch -apoderia ser muito mais clara, talvez separando o nome do controle remoto do nome do ramo com algo diferente de uma barra.
Matt Hurne
14
Observe também que git branch -r, que deve mostrar apenas ramificações remotas, mostrará a ramificação apenas origin/masterporque o remotes/prefixo não é necessário.
Matt Hurne
3
@misterbiscuit: isso é verdade. A saída é mais confusa do que esclarecedora. Muito obrigado, uma grande resposta à minha quesion que me deu as dicas certas
John Rumpel
Se olhar para o git logque vejo commit fa9sd8jasdf98 (HEAD -> master), o que isso significa? O que é HEAD neste caso? Eu pensei que era atualmente "mestre" e estava me comprometendo origin/master. Acho que misturei algo, alguém poderia ajudar a se acalmar? EDIT UPDATE: Eu acho que entendi, é correto supor que HEAD atualmente esteja apontando para o ramo principal, o que significa que estou atualmente no processo de se comprometer com o master?
Sebastian Nielsen
@SebastianNielsen sim, você está certo, a parte principal HEAD -> significa que você está atualmente no ramo principal.
iRestMyCaseYourHonor 23/03
108

Resposta curta para bonecos como eu (roubados da Torek):

  • origem / mestre é "onde o mestre esteve lá da última vez que verifiquei"
  • mestre é "onde o mestre está aqui com base no que eu tenho feito"
ErichBSchulz
fonte
9
origem / mestre = backup da máquina remota, atualizado na última vez em que você verificou o mestre = sua cópia da origem / mestre
sakurashinken
40

Tecnicamente não há realmente nenhum "remota" coisas em tudo 1 em sua repo Git, existem apenas nomes locais que devem corresponder aos nomes na outra, repo diferente. Os nomeados origin/whateverinicialmente corresponderão aos do repositório que você clonou:

git clone ssh://some.where.out.there/some/path/to/repo # or git://some.where...

faz uma cópia local do outro repositório. Ao longo do caminho, ele anota todos os ramos que estavam lá, e os confirma, e os coloca no seu repositório local sob os nomes refs/remotes/origin/.

Dependendo de quanto tempo você preceder git fetchou equivalente para atualizar "minha cópia do que está em algum lugar.onde.está lá", eles podem mudar de ramo, criar novos e excluir alguns. Quando você faz o seu git fetch(ou o git pullque é realmente buscar mais mesclar), seu repositório fará cópias de seu novo trabalho e alterará todas as refs/remotes/origin/<name>entradas conforme necessário. É esse momento fetchque faz tudo coincidir (bem, isso e o clone inicial, e alguns casos pushtambém - basicamente sempre que o Git tem a chance de verificar), mas veja a advertência abaixo).

Normalmente, o Git faz com que você se refira ao seu refs/heads/<name>como justo <name>, e aos remotos como origin/<name>, e tudo funciona porque é óbvio qual é qual. Às vezes é possível criar seus próprios nomes de ramificações que não tornam óbvias, mas não se preocupe com isso até que isso aconteça. :-) Apenas dê ao Git o nome mais curto que o torne óbvio, e ele irá a partir daí: origin/masteré "onde o mestre esteve lá na última vez que verifiquei" e masteré "onde o mestre está aqui com base no que tenho feito" . Execute git fetchpara atualizar o Git em "onde o mestre está lá", conforme necessário.


Advertência: nas versões do Git anteriores à 1.8.4, git fetchexistem alguns modos que não atualizam "onde o mestre está lá" (mais precisamente, modos que não atualizam nenhuma ramificação de rastreamento remoto). Correr git fetch originougit fetch --all mesmo a atualização git fetch, é atualizada. Correr git fetch origin master não . Infelizmente, este modo "não atualiza" é acionado por comum git pull. (Isso é apenas um pequeno aborrecimento e é corrigido no Git 1.8.4 e posterior.)


1 Bem, há uma coisa que é chamada de "remoto". Mas isso também é local! O nome originé o que o Git chama de "um controle remoto". É basicamente apenas um nome abreviado para o URL usado quando você clonou. É também de onde vem o originin origin/master. O nomeorigin/master é chamado de ramificação de rastreamento remoto , que às vezes é reduzido para "ramificação remota", especialmente em documentação mais antiga ou mais informal.

torek
fonte
2
Excelente descrição para um novato como eu, obrigado! Esclareceu por que ela colocou o origin/masteradesivo no localgráfico do repositório, e não no remote(recomendo de todo o coração a apresentação "Git Happens" de Jessica Kerr para pessoas novas em git: vimeo.com/46010208 . Estava coçando a cabeça entre as 30:00 e as 30: 30: 19.)
ancião ancião
11

Eu tentaria simplificar a resposta de @ ErichBSchulz para iniciantes:

  • origem / mestre é o estado da ramificação principal no repositório remoto
  • master é o estado da ramificação principal no repositório local
MKJ
fonte
1
boa tentativa, mas IMHO sem last time I've checkedperde ponto importante #
Alexei Martianov
6
  1. origem - Esse é um nome personalizado e mais comum para apontar para remoto.

$ git remote add origin https://github.com/git/git.git--- Você executará este comando para vincular seu projeto do github à origem. Aqui a origem é definida pelo usuário. Você pode renomeá-lo$ git remote rename old-name new-name


  1. master - O nome padrão da ramificação no Git é master. Para computadores remoto e local.

  1. origem / mestre - Este é apenas um ponteiro para se referir à ramificação principal no repositório remoto. Lembre-se que eu disse que a origem aponta para remoto.

$ git fetch origin- Faz o download de objetos e referências do repositório remoto para o seu computador local [origem / mestre]. Isso significa que ele não afetará sua ramificação principal local, a menos que você as junte usando$ git merge origin/master . Lembre-se de fazer o checkout do ramo correto onde você precisa mesclar antes de executar este comando

Nota: O conteúdo buscado é representado como uma ramificação remota. Buscar permite que você revise as alterações antes de integrá-las à sua cópia do projeto. Para mostrar alterações entre a sua e a remota$git diff master..origin/master

Gnanasekar S
fonte
5

Um esclarecimento (e um ponto que me confundiu):

"controles remotos / origem / HEAD é o ramo padrão" não está realmente correto.

controles remotos / origem / mestre era a ramificação padrão no repositório remoto (última vez que você verificou). HEAD não é um ramo, apenas aponta para um ramo.

Pense em HEAD como sua área de trabalho. Quando você pensa dessa maneira, o 'git checkout branchname' faz sentido em relação à alteração dos arquivos da área de trabalho para que sejam de um ramo específico. Você "faz o checkout" dos arquivos da filial em sua área de trabalho. HEAD para todos os fins práticos é o que é visível para você na sua área de trabalho.

Rick
fonte
Mais precisamente, HEADé um "ponteiro para uma ramificação" (o arquivo real em seu repositório local geralmente contém a string ref: refs/heads/master, por exemplo ... a menos que seja "desanexada", o que é outra coisa totalmente diferente). No entanto, há um tipo de bug na maneira como cloneinterpreta o "HEAD remoto": os protocolos de transferência não podem enviar uma ramificação indireta, apenas um SHA-1 bruto, então o git tem um kludge que faz com que "principalmente funcione". De vez em quando alguém se depara com um caso estranho. I tipo de git desejo não criar remotes/origin/HEADem tudo, especialmente quando ele sai errado ...
Torek
2

Acho que essa notação de barra do Git provavelmente é melhor entendida olhando dentro da sua .gitpasta.


Por exemplo, aqui está uma árvore um pouco abreviada do meu .git para a base de origem do LibreOffice.

No linux sudo apt-get install tree é útil ver isso.
No Windows , acho que otree comando ainda pode funcionar.

Role para baixo e dê uma olhada em refs (aka 'referências') na parte inferior:

$ tree  
.  
├── branches  
├── config  
├── description  
├── FETCH_HEAD  
├── gitk.cache  
├── HEAD  
├── hooks  
│   ├── applypatch-msg.sample  
    ...
├── index  
├── info  
│   └── exclude  
├── logs  
│   ├── HEAD  
│   └── refs  
│       ├── heads  
│       │   ├── master  
│       │   └── remotes  
│       │       └── origin  
│       └── remotes  
│           └── origin  
│               ├── distro  
│               │   ├── cib  
│               │   │   └── libreoffice-6-0  
│               │   ├── collabora  
│               │   │   └── cp-6.0  
│               │   └── lhm  
│               │       └── libreoffice-5-2+backports  
│               ├── HEAD  
│               ├── libreoffice-6-2  
│               ├── master  
│               └── private  
│                   └── mst  
│                       └── sw_redlinehide_4a  
├── objects  
│   ├── info  
│   └── pack  
│       ├── pack-b80087dc57e2b3315f449ca0f1aaa91987bf0c5e.idx  
│       ├── pack-b80087dc57e2b3315f449ca0f1aaa91987bf0c5e.pack  
│       ├── pack-eb4e6808029e712d8d9c2671accbbd98aaeb9a04.idx  
│       └── pack-eb4e6808029e712d8d9c2671accbbd98aaeb9a04.pack  
├── ORIG_HEAD  
├── packed-refs  
└── refs  
    ├── heads  
    │   ├── master  
    │   └── remotes  
    │       └── origin  
    ├── remotes  
    │   └── origin  
    │       ├── distro  
    │       │   ├── cib  
    │       │   │   └── libreoffice-6-0  
    │       │   ├── collabora  
    │       │   │   └── cp-6.0  
    │       │   └── lhm  
    │       │       └── libreoffice-5-2+backports  
    │       ├── HEAD  
    │       ├── libreoffice-6-2  
    │       ├── master  
    │       └── private  
    │           └── mst  
    │               └── sw_redlinehide_4a  
    └── tags  
        └── libreoffice-6-2-branch-point  

32 directories, 45 files

Poderia ter sido menos confuso se fosse definido dessa maneira, mas não era:

repositories (i.e. independent trees)
├──local
│  └──master
│
└──origin1
│  └──master
└──origin2
   └──master

Temos três tipos básicos de referências: cabeças , controles remotos e tags .

  • .git / refs / heads detém nosso mestre local .

  • .git / refs / remotes pode conter vários controles remotos, embora no momento só tenhamos origem nele.

  • .git / refs / tags (discutido em outro lugar).

origem , portanto, é o nosso único e remoto. Possui origem / mestre .


Descobrimos que temos 2 HEADS (ponteiros para ramificações atuais), um local e um remoto:

$ cat .git/HEAD                        #         local:  HEAD -> master
ref: refs/heads/master

$ cat .git/refs/remotes/origin/HEAD    # remote origin:  HEAD -> master
ref: refs/remotes/origin/master

Se você listar suas filiais :

$ git branch -a
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/aoo/aw080
  remotes/origin/aoo/trunk
  remotes/origin/distro/capgemini/cg-4.1
  remotes/origin/distro/cib/libreoffice-5-0
  remotes/origin/distro/cib/libreoffice-5-1
  remotes/origin/distro/cib/libreoffice-5-2
  ...
  • O primeiro ramo listado ( mestre ) é o único que não é remoto. Portanto, neste caso, temos uma filial local. É aqui que começaremos nosso próprio trabalho, para nossas próprias novas filiais e confirmações subsequentes.

Em seguida, você pode ter muitas ramificações de rastreamento remoto, e fazemos aqui. Você sabe que essas são ramificações de rastreamento remoto porque são prefixadas com ' remotes / '. Os mostrados aqui são para a origem nomeada remota.

  • Portanto, a segunda linha é o ponteiro de ramificação atual da origem . Remotos / origem: HEAD - aponta para -> mestre. Isso mostra que no repositório remoto, a ramificação atual é a ramificação denominada master (não deve ser confundida com a ramificação local denominada master ).

  • Os ramos restantes não foram encontrados no seu .git / refs / tree, mas você os encontrará no .git/packed-refs.

Quando git fetch alterações do repositório remoto para o repositório de rastreamento remoto.

Quando nos unimos , mesclamos as alterações nesse repositório de rastreamento remoto local em nossas filiais ou filiais locais de trabalho, nesse caso em nossa filial principal.

(Quando fazemos o git pull , fazemos as duas etapas em uma operação.)


Também é interessante observar que esses UUIDs locais e remotos para mestre atualmente apontam para o mesmo nó (também conhecido como 'commit'):

$ cat refs/heads/master                   # local         master
1ca409292272632f443733450313de5a82c54a9c

$ cat refs/remotes/origin/master          # remote origin master
1ca409292272632f443733450313de5a82c54a9c

Portanto, nosso mestre local aponta para o mesmo local que o mestre de origem do controle remoto:

[local] master = [remote] origin master

Por fim, acho que também é útil dar uma olhada .git/packed-refs

$ cat packed-refs 
# pack-refs with: peeled fully-peeled 
3c1d4742e649fe9c8aed8c2817fe3e1f3364f298 refs/remotes/origin/aoo/aw080
e87c8b7922e9a73e0abb7f9a7a47c9ac3374a826 refs/remotes/origin/aoo/trunk
b70fdffb041c12f124dcc0822b61bf3450e53137 refs/remotes/origin/distro/capgemini/cg-4.1
5dbc3f1754809b9489faaf380b1a4bdbcfbb6205 refs/remotes/origin/distro/cib/libreoffice-5-0
cfdbc96ca47d68d6785fd21829a8d61f49d6e591 refs/remotes/origin/distro/cib/libreoffice-5-1
5189c8c47461ef09739086e55512fc6a10245273 refs/remotes/origin/distro/cib/libreoffice-5-2
3bee5917569ca8e6ee3b086458f5b1a917b88ca1 refs/remotes/origin/distro/cib/libreoffice-5-3
92fbe703f9ca480d3a2b8610d87e991c729edf77 refs/remotes/origin/distro/cib/libreoffice-5-4
05c0a5df66cc69d75280f05b804cf82f3387d42b refs/remotes/origin/distro/cib/libreoffice-6-0
7fe193e759b24b90852e6e327115b77114d7b119 refs/remotes/origin/distro/cib/libreoffice-6-1
8187f7aa413e7ef7b377eea2b057d336bf256867 refs/remotes/origin/distro/collabora/cd-5.3
7a6b608591e21ef61dc05cff9fc58da531035755 refs/remotes/origin/distro/collabora/cd-5.3-3.1
....

Sem dúvida, isso deixa mais perguntas do que respostas, mas acho que pode começar a ajudá-lo a responder suas próprias perguntas sobre o que é o quê.

Vista elíptica
fonte