Разветвление Git: мастер против источника / мастер против удаленных / источник / мастер

201

Я думаю, что я на правильном пути, чтобы понять основные концепции Git.

Я уже настроил и клонировал удаленный репозиторий. Я также создал пустой репозиторий на стороне сервера и связал с ним свой локальный репозиторий.

Моя проблема в том, что я не понимаю разницу между:

  • Происхождение / мастер против удаленных / происхождение / мастер

Насколько я понял, master - это локальная ветвь, а remotes / origin / master - удаленная.

Но что такое происхождение / мастер ?

Джон Румпель
источник
1
@ChristopherWallace: При редактировании вы вызвали два вопроса о мета: « Действительно ли нам нужен тег [origin]? » И « Что такое настоящий [Master]? ».
Дедупликатор
@Deduplicator Это проблема?
nbro
@ChristopherWallace: Многие считают, что оба тега (созданный вами и добавленный) плохие. Я согласен, но, возможно, у вас есть что добавить к обсуждению, которое не было рассмотрено. Если нет, кажется, так.
Дедупликатор
Последующий вопрос: с чего бы .git/refs/origin/masterвообще дрейфовать .git/refs/remotes/origin/master? Это происходит со мной сейчас, и меня сбивают с толку.
Пол

Ответы:

219

Возьмите клон удаленного репозитория и запустите git branch -a(чтобы показать все ветки, о которых знает git). Вероятно, это будет выглядеть примерно так:

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

Здесь masterнаходится ветка в локальном хранилище. remotes/origin/masterэто ветка с именем masterна удаленном имени origin. Вы можете ссылаться на это origin/masterкак на:

git diff origin/master..master

Вы также можете ссылаться на это как remotes/origin/master:

git diff remotes/origin/master..master

Это всего лишь два разных способа обращения к одной и той же вещи (кстати, обе эти команды означают «показать мне изменения между удаленной masterветкой и моей masterветкой»).

remotes/origin/HEADэто default branchдля удаленного имени origin. Это позволяет вам просто сказать originвместо origin/master.

larsks
источник
5
Хороший ответ. Я думаю, что git branch -aпоказ удаленной ветви как remotes/origin/masterесть, потому что основной ref хранится в .git/refs/remotes/origin(если он не был упакован). По моему мнению, вывод git branch -aмог бы быть намного более ясным, возможно, отделяя имя удаленного от имени ветви чем-то кроме слэша.
Мэтт Хёрн
14
Также обратите внимание git branch -r, что для показа только удаленных ветвей ветка будет отображаться просто origin/masterпотому, что remotes/префикс не нужен.
Мэтт Хёрн
3
@misterbiscuit: это правда. Вывод более запутанный, чем уточняющий. Большое спасибо, отличный ответ на мой вопрос, который дал мне правильные подсказки
Джон Румпель
Если я смотрю, git logя вижу commit fa9sd8jasdf98 (HEAD -> master), что это значит? Что такое ГОЛОВА в этом случае? Я думал, что я в настоящее время "мастер" и обязался origin/master. Я думаю, что я что-то перепутал, кто-то может помочь завести? РЕДАКТИРОВАТЬ ОБНОВЛЕНИЕ: Я думаю, что я понял, правильно ли считать, что HEAD в данный момент указывает на ветку master, то есть я сейчас нахожусь в процессе фиксации для master?
Себастьян Нильсен,
@SebastianNielsen да, вы правы, часть HEAD -> master означает, что вы в данный момент находитесь в основной ветке.
iRestMyCaseYourHonor
108

Краткий ответ для чайников вроде меня (украденных у Торека):

  • Происхождение / мастер - это "где мастер был там, когда я последний раз проверял"
  • мастер "где мастер здесь на основе того, что я делал"
ErichBSchulz
источник
9
origin / master = резервная копия удаленной машины, обновленная в последний раз, когда вы проверяли master = ваша копия origin / master
sakurashinken
40

Технически на самом деле нет никаких «удаленных» вещей 1 в вашем репозитории Git, есть только локальные имена, которые должны соответствовать именам в другом, другом репо. Те, что названы, origin/whateverбудут изначально совпадать с теми в репо, с которого вы клонировали:

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

делает локальную копию другого репо. По пути он отмечает все ветви, которые были там, и фиксирует те, на которые ссылаются, и вставляет их в локальный репозиторий под именами refs/remotes/origin/.

В зависимости от того, как долго вы git fetchпроделываете или эквивалентно обновляете «мою копию что-то some.where.out.there», они могут менять свои ветви вокруг, создавать новые и удалять некоторые. Когда вы выполняете свою задачу git fetch(или git pullчто действительно является извлечением плюс слияние), ваше хранилище сделает копии своей новой работы и при необходимости изменит все refs/remotes/origin/<name>записи. Это тот момент, fetchкогда все совпадает (ну, это, и первоначальный клон, и некоторые случаи использования pushтоже - в основном, когда у Git есть возможность проверить - но смотрите предостережение ниже).

Git обычно имеет вы обратитесь к своему усмотрению , refs/heads/<name>как только что <name>, и удаленные из них , как origin/<name>, и все это просто работает , потому что это очевидно , какой из них есть что. Иногда можно создать свои собственные имена веток, которые делают это неочевидным, но не беспокойтесь об этом, пока это не произойдет. :-) Просто дайте Git самое короткое имя, которое делает его очевидным, и оно пойдет оттуда: origin/master«где мастер был там в прошлый раз, когда я проверял», и master«где мастер здесь, основываясь на том, что я делал» , Запустите, git fetchчтобы обновить Git на «где мастер там» по мере необходимости.


Предостережение: в версиях Git более старых, чем 1.8.4, git fetchесть некоторые режимы, которые не обновляют «где мастер там» (точнее, режимы, которые не обновляют ветви удаленного отслеживания). Бег git fetch origin, или git fetch --all, или даже просто git fetch, делает обновление. Бег git fetch origin master не . К сожалению, этот режим «не обновляется» запускается обычным способом git pull. (Это в основном незначительное раздражение и исправлено в Git 1.8.4 и более поздних версиях.)


+1 Ну, есть одна вещь, которая называется «дистанционная». Но это также локально! Имя origin- это то, что Git называет «удаленным». Это просто краткое имя для URL, который вы использовали, когда делали клон. Это также , где originв origin/masterприходит. Имя origin/masterназывается удаленной ветвью , которая иногда сокращается до «удаленной ветви», особенно в более старой или более неофициальной документации.

Торек
источник
2
Отличное описание для новичка, как я, спасибо! Выяснили, почему она наклеила origin/masterнаклейку на localграфик репо, а не на remoteодин (я искренне рекомендую презентацию «Git Happens» Джессики Керр для новичковgit : vimeo.com/46010208 . Я чесал голову между 30:00 - 30: 19.)
старший старший
11

Я бы постарался сделать ответ @ ErichBSchulz более простым для начинающих:

  • origin / master - это состояние ветки master в удаленном хранилище.
  • master - состояние ветки master в локальном хранилище
MKJ
источник
1
хорошая попытка, но ИМХО без last time I've checkedнее теряет важный момент
Алексей
6
  1. origin - это пользовательское и наиболее распространенное имя, указывающее на удаленное.

$ git remote add origin https://github.com/git/git.git--- Вы запустите эту команду, чтобы связать ваш проект github с origin. Здесь происхождение определяется пользователем. Вы можете переименовать его$ git remote rename old-name new-name


  1. master - в Git по умолчанию используется имя ветки master. Для удаленного и локального компьютера.

  1. origin / master - это просто указатель для ссылки на главную ветку в удаленном репо. Помните, я сказал, что происхождение указывает на удаленный.

$ git fetch origin- Загружает объекты и ссылки из удаленного хранилища на локальный компьютер [origin / master]. Это означает, что это не повлияет на вашу локальную главную ветку, если вы не объедините их, используя $ git merge origin/master. Не забудьте оформить правильную ветвь, где вам нужно объединиться, прежде чем запускать эту команду

Примечание. Извлеченное содержимое представляется в виде удаленной ветви. Fetch дает вам возможность просмотреть изменения, прежде чем интегрировать их в вашу копию проекта. Чтобы показать изменения между вашим и удаленным$git diff master..origin/master

Гнанасекар С
источник
5

Одно уточнение (и пункт, который меня смутил):

«remotes / origin / HEAD является веткой по умолчанию» не совсем правильно.

remotes / origin / master был веткой по умолчанию в удаленном репозитории (когда вы последний раз проверяли). ГОЛОВА не ветвь, она просто указывает на ветвь.

Думайте о ГОЛОВЕ как о вашей рабочей зоне. Когда вы думаете об этом таким образом, то «git checkout branchname» имеет смысл изменить файлы рабочей области на файлы определенной ветви. Вы «извлекаете» файлы веток в свою рабочую зону. Голова для всех практических целей - это то, что вы видите в своей рабочей зоне.

стог
источник
Точнее говоря, HEADэто «указатель на ветку» (фактический файл в вашем локальном репо часто содержит строку ref: refs/heads/master, например ... если только он не «отсоединен», что совсем другое дело). Однако в способе cloneинтерпретации «удаленного HEAD» есть своего рода ошибка : протоколы передачи вообще не могут отправлять непрямую ветвь, просто необработанный SHA-1, поэтому у git есть kludge, который делает это «главным образом работой». Время от времени кто-то натыкается на странный случай, хотя. Я бы хотел, чтобы git вообще не создавался remotes/origin/HEAD, особенно когда он выходит из строя ...
torek
2

Я думаю, что эту нотацию git slash, вероятно, лучше всего понять, заглянув в вашу .gitпапку.


Например, вот несколько сокращенное дерево моего .git для исходной базы LibreOffice.

В Linux sudo apt-get install tree полезно посмотреть это.
В Windows я думаю, что treeкоманда все еще может работать.

Прокрутите вниз и посмотрите на ссылки (так называемые «ссылки») внизу:

$ 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

Это могло бы быть менее запутанным, если бы оно было так изложено, но это не так:

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

У нас есть три основных типа ссылок: головы , пульты и теги .

  • .git / refs / head содержит нашего местного мастера .

  • .git / refs / remotes может содержать несколько пультов, хотя на данный момент мы имеем только источник .

  • .git / refs / tags (обсуждается в другом месте).

Происхождение, таким образом, является нашим единственным и отдаленным. Это держит происхождение / мастер .


Мы находим, что у нас есть 2 HEADS (указатели на текущие ветви), один локальный и один удаленный:

$ 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

Если вы перечислите свои филиалы :

$ 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
  ...
  • Первая ветвь в списке ( главная ) - единственная, которая не является удаленной. Так что в этом случае у нас есть один местный филиал. Это то место, с которого мы начнем нашу собственную работу для наших новых веток и последующих коммитов.

Далее, у вас может быть много удаленных веток отслеживания, и мы делаем это здесь. Вы знаете, что это удаленные ветви отслеживания, потому что они имеют префикс « remotes ». Показанные здесь для удаленного именованного источника.

  • Таким образом, вторая строка является указателем текущей ветви источника . Remotes / origin: HEAD - указывает на -> мастер. Это показывает, что в удаленном хранилище текущей веткой является их ветвь с именем master (не путать с нашей локальной веткой с именем master ).

  • Остальные ветви не найдены в вашем .git / refs / tree, скорее вы найдете их в .git/packed-refs.

Когда мы GIT выборки выполняем мы загружаем изменения из удаленного репозитория в наш удаленный репозиторий отслеживания.

Когда мы сливаемся выполняем мы объединяем изменения в этом локальном удаленном репозитории отслеживания с нашей рабочей локальной ветвью или ветвями, в данном случае с нашей главной ветвью.

(Когда мы выполняем git pull, мы выполняем оба эти шага за одну операцию.)


Также интересно отметить, что эти локальные и удаленные UUID для master в настоящее время указывают на один и тот же узел (он же «commit»):

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

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

Таким образом, наш локальный мастер указывает на то же место, что и мастер источника на пульте:

[local] master = [remote] origin master

Наконец, я думаю, что также полезно взглянуть на .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
....

Без сомнения, это оставляет больше вопросов, чем ответов, но я думаю, что это может помочь вам ответить на ваши собственные вопросы о том, что к чему.

Эллиптический вид
источник