TL; DR
Вы в порядке, но у вас есть дополнительный репозиторий, который вы, вероятно, должны просто удалить. Обычно вы должны начать с клонирования (с git clone
) хранилища, для которого вы хотите, чтобы ваш вызов Git origin
, а затем git remote add upstream <the other url>
и работал оттуда.
Прочитайте подробное описание ниже, чтобы увидеть, что у вас есть сейчас и как с ним работать.
Долго: что вы сделали, подробно
git init
Это создает новый пустой Git-репозиторий в текущем каталоге. (Если здесь уже есть Git-репозиторий - если git rev-parse --git-dir
напечатает какое-то имя каталога, а не произойдет сбой и произнесет «Я не нахожу репозиторий»), то он в основном ничего не делает, что делает его безопасным для запуска. Есть несколько угловых случаев здесь, но вы вряд ли столкнетесь с ними.) Поскольку вы намереваетесь клонировать репозиторий, вы на самом деле этого не хотите, потому что git clone
также выполняет git init
, как мы увидим в мгновение.
Прежде чем мы перейдем к git clone
ниже, давайте немного поговорим о странном состоянии нового пустого хранилища. Вы, наверное, уже знакомы с идеей, что имя ветки подобно master
на самом деле просто содержит хэш-идентификатор одного (1) коммита. Git использует имя, чтобы найти последний коммит в ветви, который Git вызывает tip commit . Затем Git использует коммит tip для поиска предыдущего или parent commit и использует родителя parent для обработки истории. Следуя цепочке родителей, Git находит все коммиты, которые достижимы из названия ветви.
Но пустой репозиторий не имеет коммитов . Нет подсказки master
для имени master
для указания - нет последнего коммита в master
, чей хэш-идентификатор можно сохранить под именем master
. Решение Git - не иметь ветви master
. В то же время, Git объявляет, что вы «на ветке master», как сказал бы git status
, поэтому вы на ветке, которая еще не существует .
Это странность факторов позже. А сейчас давайте перейдем к git clone
и посмотрим, что он делает. В этом случае он создает другой отдельный репозиторий, который вы впоследствии вообще не используете.
git clone https://github.com/abelbraaksma/visualfsharp
Это в основном эквивалентно серии команд:
mkdir visualfsharp
: создать новый подкаталог в текущем каталоге (текущий /D/Projects/OpenSource/VisualFSharp2
)
cd visualfsharp
: введите новый подкаталог
git remote add origin https://github.com/abelbraaksma/visualfsharp
: добавить пульт с именем origin
(для него также можно настроить несколько параметров)
git fetch origin
: получить все их коммиты
git checkout <em>somebranch</em>
, где somebranch
обычно master
: создает имя локальной ветви из одного из origin/*
имен и делает ее текущей ветвью.
Когда это будет сделано, вы вернетесь в исходный каталог (т.е. все еще /D/Projects/OpenSource/VisualFSharp2
). Обратите внимание, что ваш исходный каталог - это один репозиторий Git, а его подкаталог visualfsharp
- другой.
Теперь мы увидим, что вы снова выполняете большинство из этих команд, но на этот раз применительно к вашему пустому в данный момент репозиторию, который находится в том странном состоянии, в котором вы находитесь на master
, а master
- нет. есть.
git fetch https://github.com/Microsoft/visualfsharp
Это вызывает Git на https://github.com/Microsoft/visualfsharp
и получает коммиты и другие объекты от них в ваш ранее пустой репозиторий (а не клон, который вы только что сделали!). Это похоже на git fetch <em>remote</em>
за исключением того, что нет имен для удаленного отслеживания - нет origin/*
или upstream/*
- так как не существует пульта, который можно использовать для создания таких имен. Эта конкретная форма git fetch
восходит к древним временам (2005), до изобретения git remote
, и, вероятно, никогда не следует использовать его. Это не вредно , это просто не полезно здесь.
git remote add upstream https://github.com/Microsoft/visualfsharp
git remote add origin https://github.com/abelbraaksma/visualfsharp
Все в порядке: они установили два пульта . Пульт ДУ - это просто короткое имя, которое:
- сохраняет URL, а
- обеспечивает ведущую часть имен удаленного слежения,
upstream/*
и origin/*
соответственно.
git fetch upstream
Это яс почти повторение вашего предыдущего git fetch
. Однако на этот раз ваш Git использует имя, которое вы назначили - upstream
- для получения URL. Итак, ваш Git снова вызывает Git на https://github.com/Microsoft/visualfsharp
. Ваш Git получает от них любые новые коммиты (и любые другие необходимые объекты Git, чтобы идти с этими коммитами) с момента последней выборки - вероятно, нет, в зависимости от того, как долго вы проходили между первой выборкой и этой второй. Если бы вы не запустили более раннюю git fetch
, это получило бы каждый объект Git при получении всех коммитов.
Но теперь, получив коммиты, есть критическая разница: ваш Git берет все их имена ветвей и переименовывает их в ваши имена для удаленного слежения, записанные upstream/<em>whatever</em>
. Это можно сделать сейчас, потому что теперь вы используете удаленный, а не просто необработанный URL. Пульт дистанционного управления - буквальная строка upstream
- получает вам это переименование. 1 Таким образом, ваш Git и его Git очень быстро переносят все новые объекты (вероятно, ни одного), а затем ваш Git устанавливает ваш upstream/master
и так далее, исходя из их master
и так далее.
git checkout master
Вот тут и появляется странное состояние хранилища. Ваш Git скажет:
Branch master set up to track remote branch master from upstream.
Already on 'master'
Что случилось, так это то, что git checkout
искал master
, а не нашел его (потому что у вас нет ветвей), поэтому он создал один. Сначала он просмотрел все ваши имена для удаленного слежения, upstream/*
в данном случае. Он нашел тот, который соответствовал: master
против upstream/master
. Таким образом, он создал ваш master
, указывая на тот же коммит, что и ваш upstream/master
. Затем он также установил для master
значение upstream/master
как upstream .
После всего этого - создавая master
- git checkout
, попытался поставить вас на master
и обнаружил, что вы были только на master
, и распечатал это сбивающее с толку сообщение «уже включено». Тем не менее он правильно подключил ваш HEAD в процессе, проверяя все файлы, то есть копируя их в индекс и в рабочее дерево.
Вы можете или не хотите, чтобы ваш master
был настроен таким образом - вы, скорее всего, захотите, чтобы ваш master
начал указывать на тот же коммит, что и ваш origin/master
, как только вы создадите origin/master
, и origin/master
установить в качестве восходящего потока. Для получения дополнительной информации о том, что является восходящим потоком, т. Е. Что означает, что для одной ветви установлено значение track 2 другой ветви - см., Например, мой ответ to Как настроить несколько уровней отслеживания веток с помощью git .
Ваша последняя команда здесь была:
git merge upstream/master
Ваш собственный master
был только что создан из вашего upstream/master
, так что объединять нечего: оба имени указывают на один и тот же хэш-идентификатор фиксации.
Вы еще ничего не получили от вашего origin
. Вы, вероятно, должны сделать это сейчас:
git fetch origin
Как только вы это сделаете, у вас будет origin/master
, а также upstream/master
. 3 Если вы хотите, как я подозреваю, иметь собственную master
дорожку origin/master
вместо upstream/master
(и начать с этого), вы должны:
- убедитесь, что нечего коммитить (не следует указывать приведенную выше последовательность, но всегда разумно проверять перед использованием
git reset --hard
);
- запустите
git reset --hard origin/master
, чтобы заставить master
указать тот же коммит, что и origin/master
; и
- Запустите
git branch --set-upstream-to=origin/master master
, чтобы изменить настройку восходящего потока.
Теперь вы можете запустить git merge upstream/master
. Если у восходящего потока есть новые коммиты с тех пор, как произошел ваш собственный форк, они объединят эти коммиты, используя либо полное слияние, если требуется, либо ускоренную пересылку, если не возможно слияние, если это возможно.
В любом случае вы, вероятно, захотите удалить дополнительный репозиторий.
1 Базовый механизм, с помощью которого Git достигает этого переименования, ужасно сложен, вероятно, по историческим причинам, но в обычной практике это просто "изменение их master
на <em>remote</em>/master
" и так далее.
2 NОтметим, что здесь Git использует еще более запутанную терминологию: если имя ветви отслеживает a имя удаленного отслеживания (это локальное имя, создаваемое вашим Git на основе имени, найденного в другом Git, чей URL-адрес обнаруживается через remote ), затем мы называем этот филиал (или имя филиала) upstream . Все это полностью отличается от отслеживаемых и неотслеживаемых файлов. Хлоп!
3 Я предполагаю, что репозиторий Git на https://github.com/abelbraaksma/visualfsharp
является вашим собственным, и что вы создали его с помощью кликающих кнопок GitHub "fork a repository" в их интерфейсе Web GUI. Когда вы это сделали, GitHub сделал несколько сложных git clone
для самого GitHub, создав там свой репозиторий из любого исходного репозитория, который вы выбрали. Это означает, что ваш репозиторий GitHub имеет все те же ветви, что и исходный репозиторий.
(Клон, созданный GitHub, не переименовывает ветви. У него также есть специальные функции, предназначенные только для GitHub, которые позволяют GitHub предоставлять возможность извлечения запросов; это не является частью Git. Люди GitHub также обмениваются базовыми закулисные дисковые объекты и множество других хитростей, чтобы сделать это намного быстрее, чем это было бы, если бы это было сделано наивно. Так что это обычный клон в принципе , но они его подправили, чтобы сделать это полезнее через их веб-интерфейс. Именно так они заставляют вас использовать GitHub вместо того, чтобы делать все самостоятельно. ?)