Ramificazione git: master vs. origin / master vs. telecomandi / origin / master


201

Penso di essere sulla buona strada per comprendere i concetti di base di Git.

Ho già impostato e clonato un repository remoto. Ho anche creato un repository vuoto sul lato server e collegato ad esso il mio repository locale.

Il mio problema è che non capisco la differenza tra:

  • origine / master vs. telecomandi / origine / master

Per quanto ho capito, master è un ramo locale e telecomandi / origin / master sono remoti.

Ma cos'è esattamente origine / maestro ?


1
@ChristopherWallace: Hai provocato due domande sulla meta con la tua modifica: " Abbiamo davvero bisogno di un tag [origine]? " E " Qual è il vero [Maestro]? ".
Deduplicatore

@Deduplicator È un problema?
nbro,

@ChristopherWallace: Beh, molti sembrano pensare che entrambi i tag (quello che hai creato e quello che hai appena aggiunto) siano cattivi. Mi capita di concordare, ma forse hai qualcosa da aggiungere alla discussione collegata che non è stata presa in considerazione. In caso contrario, sembra di sì.
Deduplicatore


Domanda di follow-up: Perché .git/refs/origin/mastermai deriverebbe .git/refs/remotes/origin/master? Questo sta succedendo a me ora e mi stanno buttando via.
Paul

Risposte:


219

Prendi un clone di un repository remoto ed esegui git branch -a(per mostrare tutti i rami che Git conosce). Probabilmente sarà simile a questo:

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

Qui, masterè un ramo nel repository locale. remotes/origin/masterè un ramo denominato mastersul telecomando denominato origin. Puoi fare riferimento a questo come uno origin/master, come in:

git diff origin/master..master

Puoi anche fare riferimento ad esso come remotes/origin/master:

git diff remotes/origin/master..master

Questi sono solo due modi diversi di riferirsi alla stessa cosa (per inciso, entrambi questi comandi significano "mostrami i cambiamenti tra il masterramo remoto e il mio masterramo).

remotes/origin/HEADè il default branchnome del telecomando origin. Ciò consente di semplicemente dire original posto di origin/master.


5
Buona risposta. Penso che git branch -amostrare il ramo remoto come remotes/origin/mastersia parzialmente perché il riferimento sottostante è memorizzato .git/refs/remotes/origin(se non è stato compresso). Secondo me, l'output di git branch -apotrebbe essere molto più chiaro, forse separando il nome del telecomando dal nome del ramo con qualcosa di diverso da una barra.
Matt Hurne,

14
Si noti inoltre che git branch -r, che mostra solo i rami remoti, mostrerà il ramo solo origin/masterperché il remotes/prefisso non è necessario.
Matt Hurne,

3
@misterbiscuit: è vero. L'output è più confuso che chiarificante. Grazie mille, un'ottima risposta alla mia domanda che mi ha dato i giusti suggerimenti
John Rumpel,

Se guardo git logvedo commit fa9sd8jasdf98 (HEAD -> master), cosa significa? Che cos'è HEAD in questo caso? Pensavo di essere attualmente "maestro" e mi stavo impegnando origin/master. Penso di aver combinato qualcosa, qualcuno potrebbe aiutare a calmarsi? MODIFICA AGGIORNAMENTO: Penso di averlo capito, è corretto supporre che HEAD stia attualmente indicando il ramo master, nel senso che sono attualmente in procinto di impegnarmi a master?
Sebastian Nielsen,

@SebastianNielsen sì, hai ragione, HEAD -> parte principale significa che sei attualmente nel ramo principale.
iRestMyCaseYourHonor il

108

Risposta breve per manichini come me (rubati da Torek):

  • origin / master è "dove master era laggiù l'ultima volta che ho controllato"
  • master è "dove il master è qui in base a ciò che ho fatto"

9
origin / master = backup della macchina remota, aggiornato l'ultima volta che hai controllato master = la tua copia di origin / master
sakurashinken

40

Tecnicamente non ci sono in realtà cose "remote" 1 nel tuo repository Git, ci sono solo nomi locali che dovrebbero corrispondere ai nomi su un altro repository diverso. Quelli nominati origin/whateverinizialmente corrisponderanno a quelli nel repository da cui hai clonato:

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

crea una copia locale dell'altro repository. Lungo la strada prende nota di tutti i rami che erano lì, e li impegna a cui fanno riferimento e li inserisce nel tuo repository locale sotto i nomi refs/remotes/origin/.

A seconda di quanto tempo ti precede git fetcho equivalente per aggiornare "la mia copia di ciò che è some.where.out.there", possono cambiare i loro rami intorno, crearne di nuovi ed eliminarne alcuni. Quando esegui il tuo git fetch(o git pullche è veramente recupero più unione), il tuo repository farà copie del loro nuovo lavoro e cambierà tutte le refs/remotes/origin/<name>voci secondo necessità. È quel momento fetchdell'ing che fa combaciare tutto (beh, quello e il clone iniziale e alcuni casi dipush ing - praticamente ogni volta che Git ha la possibilità di controllare - ma vedi le avvertenze di seguito).

Git normalmente ti fa riferimento al tuo refs/heads/<name>come giusto <name>, e a quelli remoti come origin/<name>, e tutto funziona semplicemente perché è ovvio quale sia quale. A volte è possibile creare i propri nomi di filiali che non lo rendono ovvio, ma non preoccuparti fino a quando non accade. :-) Basta dare a Git il nome più breve che lo rende ovvio, e andrà da lì: origin/masterè "dove il maestro era laggiù l'ultima volta che ho controllato", ed masterè "dove il maestro è qui in base a quello che ho fatto" . Esegui git fetchper aggiornare Git su "dove master è laggiù", se necessario.


Avvertenza: nelle versioni di Git precedenti alla 1.8.4, git fetchha alcune modalità che non si aggiornano "dove master è laggiù" (più precisamente, modalità che non aggiornano alcun ramo di tracciamento remoto). In esecuzione git fetch origin, o git fetch --all, o anche solo git fetch, si aggiorna. La corsa git fetch origin master no . Sfortunatamente, questa modalità "non aggiorna" è attivata dall'ordinario git pull. (Questo è principalmente solo un piccolo fastidio ed è stato risolto in Git 1.8.4 e versioni successive.)


1 Bene, c'è una cosa che si chiama "remoto". Ma è anche locale! Il nome originè la cosa che Git chiama "un telecomando". Fondamentalmente è solo un nome breve per l'URL che hai usato quando hai fatto il clone. E 'anche il luogo dove l' originin origin/masterproviene. Il nome origin/mastersi chiama ramo di tracciamento remoto , che a volte viene abbreviato in "ramo remoto", specialmente nella documentazione precedente o più informale.


2
Ottima descrizione per un principiante come me, grazie! Chiarito perché ha messo l' origin/masteradesivo sul localgrafico del repository e non su remotequello (consiglio vivamente la presentazione "Git Happens" di Jessica Kerr per le persone che non conosconogit : vimeo.com/46010208 . Mi stavo grattando la testa tra le 30:00 e le 30:30: 19.)
Anziano anziano

11

Vorrei provare a semplificare la risposta di @ ErichBSchulz per i principianti:

  • origin / master è lo stato del ramo master sul repository remoto
  • master è lo stato del ramo master sul repository locale

1
buona prova ma IMHO senza uscita last time I've checkedperde punto importante
Alexei Martianov

6
  1. origine : si tratta di un nome personalizzato e più comune che punta a remoto.

$ git remote add origin https://github.com/git/git.git--- Eseguirai questo comando per collegare il tuo progetto github all'origine. Qui l'origine è definita dall'utente. Puoi rinominarlo$ git remote rename old-name new-name


  1. master - Il nome del ramo predefinito in Git è master. Per computer remoto e locale.

  1. origin / master - Questo è solo un puntatore per fare riferimento al ramo master nel repository remoto. Ricorda che ho detto che i punti di origine sono remoti.

$ git fetch origin- Scarica oggetti e riferimenti dal repository remoto sul tuo computer locale [origine / master]. Ciò significa che non influirà sul ramo principale locale se non li unisci utilizzando $ git merge origin/master. Ricordarsi di verificare il ramo corretto in cui è necessario unire prima di eseguire questo comando

Nota: il contenuto recuperato è rappresentato come un ramo remoto. Fetch ti dà la possibilità di rivedere le modifiche prima di integrarle nella tua copia del progetto. Per mostrare i cambiamenti tra il tuo e il telecomando$git diff master..origin/master


5

Un chiarimento (e un punto che mi ha confuso):

"telecomandi / origine / HEAD è il ramo predefinito" non è proprio corretto.

remotes / origin / master era il ramo predefinito nel repository remoto (l'ultima volta che hai controllato). HEAD non è un ramo, indica solo un ramo.

Pensa a HEAD come alla tua area di lavoro. Se la pensi in questo modo, allora 'git checkout branchname' ha senso rispetto alla modifica dei file dell'area di lavoro in quello di un determinato ramo. "Esegui il checkout" dei file di diramazione nell'area di lavoro. HEAD per tutti gli scopi pratici è ciò che è visibile nella tua area di lavoro.


Più precisamente, HEADè un "puntatore a un ramo" (il file effettivo nel repository locale spesso contiene la stringa ref: refs/heads/master, ad esempio ... a meno che non sia "scollegato", che è completamente un'altra cosa). Tuttavia, c'è un bug nel modo in cui cloneinterpreta "HEAD remoto": i protocolli di trasferimento non possono affatto inviare un ramo indiretto, solo un SHA-1 crudo, quindi git ha un kludge che lo rende "per lo più funzionante". Ogni tanto qualcuno si imbatte in uno strano caso però. Vorrei che Git non creasse remotes/origin/HEADaffatto, specialmente quando esce male ...
Torek,

2

Penso che questa notazione git slash sia probabilmente meglio compresa guardando nella tua .gitcartella.


Ad esempio, ecco un albero in qualche modo abbreviato del mio .git per la base di sorgenti di LibreOffice.

In Linux sudo apt-get install tree è utile per visualizzare questo.
In Windows penso che il treecomando potrebbe ancora funzionare.

Scorri verso il basso e dai un'occhiata ai riferimenti (noti anche come "riferimenti") nella parte inferiore:

$ 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

Sarebbe stato meno confuso se fosse stato presentato in questo modo, ma non lo era:

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

Abbiamo tre tipi base di riferimenti: teste , telecomandi e tag .

  • .git / refs / heads detiene il nostro padrone locale .

  • .git / refs / remotes può contenere un numero di telecomandi, sebbene al momento ne abbiamo solo l' origine .

  • .git / refs / tags (è discusso altrove).

origine quindi, è il nostro unico e solo remoto. Contiene origine / master .


Troviamo che abbiamo 2 HEADS (puntatori ai rami correnti), uno locale e uno 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 elenchi le tue filiali :

$ 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
  ...
  • Il primo ramo elencato ( master ) è l'unico che non è un telecomando. Quindi in questo caso abbiamo una filiale locale. È da qui che inizieremo il nostro lavoro, per le nostre nuove filiali e per i successivi impegni.

Successivamente, potresti avere molte filiali di tracciamento remoto, e lo facciamo qui. Sai che questi sono rami di tracciamento remoti perché hanno il prefisso " telecomandi / ". Quelli mostrati qui sono per l'origine remota denominata.

  • Quindi la seconda riga è il puntatore del ramo corrente di origine . Telecomandi / origine: HEAD - punta a -> master. Questo dimostra che nel repository remoto, il ramo corrente è il loro ramo chiamato master , (da non confondere con il nostro ramo locale chiamato master ).

  • I rami rimanenti non si trovano nel tuo .git / refs / tree, ma piuttosto li troverai in .git/packed-refs.

Quando andiamo a prendere , scarichiamo le modifiche dal repository remoto, nel nostro repository di tracciamento remoto.

Quando ci uniamo uniamo le modifiche in questo repository di tracciamento locale e remoto nel nostro ramo o rami locali di lavoro, in questo caso nel nostro ramo principale.

(Quando eseguiamo pull facciamo entrambi questi due passaggi in un'unica operazione.)


È anche interessante notare che questi UUID locali e remoti per master puntano attualmente allo stesso nodo (noto anche come "commit"):

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

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

Quindi il nostro master locale punta allo stesso posto del master di origine del telecomando:

[local] master = [remote] origin master

Infine, penso che sia anche utile dare un'occhiata .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
....

Senza dubbio questo lascia più domande che risposte, ma penso che possa iniziare ad aiutarti a rispondere alle tue domande su cosa sia cosa.

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.