Как клонировать, а затем синхронизировать / обновить / протолкнуть форк с ведущим мастером - PullRequest
0 голосов
/ 28 июня 2018

Я думаю, что прочитал некоторые учебные пособия и застрял на чем-то совершенно простом (я почти никогда не использую git командной строки, поэтому, пожалуйста, будьте терпеливы;)).

Все, что я хочу сделать, это обновить мой форк (https://github.com/abelbraaksma/visualfsharp) до последней версии Master (https://github.com/Microsoft/visualfsharp) из репозитория вверх по течению). Поскольку у меня есть локальные изменения, которые меня не волнуют, я решил создать новый клон (ранее я использовал инструменты с графическим интерфейсом, но они настолько запутанные и ограничивающие, что я разочаровался в этом и погрузился в лес команд git;).

Я сделал:

cd /D/Projects/OpenSource/VisualFSharp2
git init
git clone https://github.com/abelbraaksma/visualfsharp
git fetch https://github.com/Microsoft/visualfsharp
git remote add upstream https://github.com/Microsoft/visualfsharp
git remote add origin https://github.com/abelbraaksma/visualfsharp
git fetch upstream
git checkout master
git merge upstream/master

Последние две команды дают:

git checkout master
Уже на "хозяине"
Ваша ветка обновлена ​​до 'upstream / master'.

git merge upstream/master
Уже в курсе.

Я понимаю, что сделал некоторые вещи в неправильном порядке, и, поскольку я пришел из миров SVN и Mercurial, меня часто смущает терминология.

Я понимаю, что в настоящее время я нахожусь в "хозяине" репозитория верхнего уровня. Но мне нужно слиться из репозитория upstream в репо origin (мой форк). Я предполагаю, что мне нужно обновить локальную копию до того, что принадлежит моей вилке (но git checkout master этого не делает).

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

Где я запутался или лучше, какие команды я получил задом наперед?

Выполнение git remote -v дает мне:

origin  https://github.com/abelbraaksma/visualfsharp (fetch)  
origin  https://github.com/abelbraaksma/visualfsharp (push)  
upstream        https://github.com/Microsoft/visualfsharp (fetch)  
upstream        https://github.com/Microsoft/visualfsharp (push)

1 Ответ

0 голосов
/ 29 июня 2018

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 (и начать с этого), вы должны:

  1. убедитесь, что нечего коммитить (не следует указывать приведенную выше последовательность, но всегда разумно проверять перед использованием git reset --hard);
  2. запустите git reset --hard origin/master, чтобы заставить master указать тот же коммит, что и origin/master; и
  3. Запустите 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 вместо того, чтобы делать все самостоятельно. ?)

...