Необходимо понимать отслеживание филиалов - PullRequest
1 голос
/ 02 мая 2019

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

  • Я создал проект Gitlab.
  • Я клонировал этот проект на своем компьютере с git clone.
  • Я создал новую ветку в веб-интерфейсе Gitlab (с помощью кнопки «+»): my_server_branch.
  • Я поместил в эту ветку один файл (также с веб-интерфейсом).

Итак, на этом этапе мой компьютер ничего не знает о my_server_branch.

Я прочитал, что я должен создать «ветвь отслеживания» на моем компьютере с:

git branch --track my_server_branch origin/my_server_branch

Я не запускал эту команду.Я просто набрал (в основной ветке, на моем компьютере):

git pull

И вот что я вижу в консоли:

 * [new branch]      my_server_branch -> origin/my_server_branch

Так что git обнаруживает, что есть новая ветка, когдаЯ начинаю тянуть.Итак, еще раз, мой вопрос: в чем преимущество отслеживания ветви, если gits обнаруживает и выполняет все это?

Конечно, есть преимущество для отслеживания, потому что если нет, эта команда не будет существовать ... но яне вижу этого преимущества.

И если я наберу команду git branch --track, вот что я получу:

error: the requested upstream branch 'origin/my_server_branch' does not exist

Ответы [ 3 ]

2 голосов
/ 03 мая 2019

Здесь есть куча концепций, которые вам нужно держать отдельно в своей голове;и затем возникает проблема терминологии.

Это понятия:

  • имена ветвей подобно master;
  • удаленное отслеживание имена - часто называемые удаленное отслеживание ветвей - подобно origin/master;
  • идея в восходящем направлении; и
  • фиксирует , которые идентифицируются по их хэш-идентификаторам; хранят файлы плюс некоторые метаданные; и через эти метаданные образуют цепочки.

Первые два - имена веток и имена удаленного отслеживания - довольно тесно связаны, и вместе с именами тегов, такими как v2.1, все сгруппированы в одну концепцию, которую Git называет reference .

Проблема терминологии заключается в том, что иногда некоторые ветви - некоторые имена, такие как master - говорят, что они отслеживают .Другие имена, такие как origin/master, называются ветви удаленного отслеживания , что выглядит так же.Это не!Вот почему я называю последние имена для удаленного отслеживания , чтобы избежать слова branch , и поэтому я рекомендую вместо глагола tracking думать о ветвиимена типа master как с восходящим потоком или без восходящего .Это обходит хитрое слово track (которое имеет еще одно значение применительно к файлам в вашем рабочем дереве).

Давайте перейдем к вашим действиям:

Вот краткий пример, чтобы показать мою проблему:

  • Я создал проект gitlab

  • Я клонировал этот проект наМой компьютер с командой git clone

На данный момент у вас есть два отдельных хранилища.Один на сервере GitLab и один на вашем компьютере.Мы назовем GitLab один «их», а другой на вашем компьютере - «ваш», хотя в некотором смысле они оба ваши.Ваш репозиторий очень похож на их, но не совсем такой: это клон, и у него есть способ идентифицировать его как копию вместо оригинала.

Мы вернемся к вашему репозиторию,Ваш компьютер, немного.Следующие несколько шагов происходят в их репозитории.

  • Затем я создал новую ветку в веб-интерфейсе gitlab (с помощью кнопки '+'):my_server_branch

ОК, так что на данный момент, их репозиторий Git имеет ветку, о которой ваш не знает.

  • Я поместил один файл в эту ветку (также с веб-интерфейсом gitlab)

Технически, вы не можете поместить файл в репозиторий, напримерэтот.То, что вы сделали, это добавили новый коммит , с новым коммитом, содержащим файл.

Это важно, потому что способ работы имен веток заключается в запоминании хеш-идентификатора last коммит который идет в ветке.Когда вы добавляете новый коммит, идентификатор хеша, сохраненный в имени ветви, изменяется, чтобы запомнить новый коммит.Новый коммит запоминает предыдущий последний коммит.

Если мы вытянем их, используя одинарные заглавные буквы для замены реальных хеш-идентификаторов, мы получим картинку, подобную этой, для простого репозитория с тремя коммитами.только с веткой master:

A <-B <-C   <-- master

Здесь name master запоминает фактический хеш-идентификатор commit C.Этот коммит сам запоминает фактический хеш-идентификатор коммита B, который запоминает хэш-идентификатор коммита A.Так что Git нужно только иметь имя master запомнить идентификатор коммита C: остальное он находит, просматривая сами коммиты.

(Мыу master указывает на C, C указывает на B и B указывает на A.Поскольку A - самый первый коммит, когда-либо сделанный в хранилище, он нигде не указывает: это то, что говорит нам и Git, что мы можем остановиться и отдохнуть.Там нет предыдущей истории для изучения.Коммиты являются историей, а история идет C, затем B, затем A .)

Чтобы добавить новую ветвь в хранилище, мы обычно выбираем какой-то существующий коммит внутрихранилище и проверьте его, чтобы это был текущий коммит, затем добавьте новое имя, которое указывает на тот же коммит:

A--B--C   <-- master, my_server_branch (HEAD)

Git должен знать какое имя обновлять примы делаем новые коммиты, поэтому Git присоединяет специальное имя HEAD (например, в верхнем регистре) к имени ветви.Если мы используем локальный компьютер (а не веб-интерфейс), мы должны создать файл, использовать git add, чтобы добавить его, и запустить git commit, чтобы сделать новый коммит.Если мы используем веб-интерфейс, GitLab делает то же самое в их хранилище, оно просто скрыто за их веб-интерфейсом.В итоге они набирают:

A--B--C   <-- master
       \
        D   <-- my_server_branch (HEAD)

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

Клоны получают свои собственные ветви

Теперь пришло время посмотретьвернуться в свой собственный репозиторий.Когда вы запустили:

git clone <url>

, ваш компьютер создал новый пустой репозиторий Git с no коммитами, no ответвлениями, в основном ничего, кроме пустого репозиторияракушка.Затем ваш Git на вашем компьютере заполнил эту оболочку, взяв все коммиты из их Git.Поэтому, если у них было три простых коммита:

A--B--C   <-- master

ваш Git получил эти три коммита:

A--B--C

(внутренние стрелки, обращенные назад, слишком раздражают, чтобы рисовать, но они 'все еще там: C указывает на B и B указывает на A).

Все идентификаторы хеша совпадают: каждый Git во вселенной согласится с тем, что находится внутри коммита C, что делает его хэш-идентификатором C хэш-идентификатор.Таким образом, ваш Git и его Git могут определить, какой Git имеет какие коммиты, просто взглянув на эти хэш-идентификаторы.Но у вашего Git все еще нет ветвей.

Ваш Git спрашивает у Git, каковы все их ветви и имена тегов, и они говорят: My masterидентификатор хеша для коммита C. Итак, ваш Git теперь создает, а не master, а origin/master, указывая на коммит C:

A--B--C   <-- origin/master

Коммитов нет иветок не осталось, поэтому ваш Git завершил копирование.Ваш Git теперь выполняет последний шаг git clone, который должен быть запущен:

git checkout master

Вы можете заставить свой Git использовать другое имя, и если вы этого не сделаете, ваш Git запрашивает их Git, какое имя использовать;но это обычный, обычный случай: ваш Git пытается проверить ваш master.

У вас нет master. И все же,эта проверка в любом случае успешна.Причиной этого является то, что их Git имеет master и ваш Git скопировал это в ваш origin/master.Так что ваш Git, вместо того, чтобы просто провалить проверку, говорит сам себе: Хм, нет master, но есть origin/master ... который очень похож на master, держу пари, вы имели в виду, что я должен make master с использованием origin/master. Итак, ваш Git делает это:

git checkout --track master origin/master

, который создает вашего собственного master и устанавливает его вверх по течению до origin/master.Итак, теперь у вас есть это:

A--B--C   <-- master (HEAD), origin/master

Ваша ветка master существует и имеет origin/master в качестве восходящего потока.

Боковая панель: если вы не уверены, будьте уверены, этосбивает с толку!

Запутанный способ объяснить это тем, что ваша ветка master (1) теперь отслеживает (2) вашу ветку удаленного отслеживания (3, 4, 5) origin/master с удаленного (6) origin. Здесь в точках (1) и (5) оба слова или фразы используют слово branch , но оба означают что-то другое. В (2) и (4) у нас есть слово tracking , оба означающие что-то другое. В (3) и (6) у нас есть слово remote , оба означающие что-то другое. Вы можете понять, почему мне не нравятся эти слова, и я предпочитаю называть это именем ветви master, с восходящим origin/master, с origin/master, являющимся имя удаленного отслеживания , связанное с remote origin. Мне все еще приходится использовать слово remote дважды, но «дистанционное отслеживание» как минимум переносится.

Один правильный и хороший способ получить my_server_branch локально

Сделав my_server_branch в их Git и добавив туда коммит D, теперь вы можете выполнить команду:

git fetch

в вашем собственном Git на вашем компьютере. (Вы можете использовать git fetch origin, если хотите быть явным.) Это заставляет ваш Git вызывать Git и снова запрашивать у него список названий веток. На этот раз они говорят: У меня есть master, на коммите C. У меня есть my_server_branch, при коммите D. Ваш Git говорит: Ах, у меня уже есть коммит C, так что никаких проблем нет. Дайте мне совершить D хотя. Они делают это, и теперь разговор между вашим мерзавцем и их мерзавцем завершен. Теперь ваш Git обновляет ваш origin/master так, чтобы он указывал на C - что вообще не изменится - и создает ваш origin/my_server_branch, указывая на новый коммит D. Итак, теперь у вас есть:

A--B--C   <-- master (HEAD), origin/master
       \
        D   <-- origin/my_server_branch

Теперь вы можете запустить git checkout my_server_branch. Как и раньше, у вас нет my_server_branch на данный момент, но вместо просто неудачи ваш Git скажет: Ага, у меня нет my_server_branch. Но у меня есть origin/my_server_branch. Я создам my_server_branch, указывая на коммит D. Я установлю восходящий поток my_server_branch равным origin/my_server_branch. Тогда я сделаю заказ, о котором вы просили. Результат:

A--B--C   <-- master, origin/master
       \
        D   <-- my_server_branch (HEAD), origin/my_server_branch

Вам почти никогда не нужно использовать git checkout --track

Единственный раз, когда вам нужно git checkout --track, это когда git checkout не сделает для вас правильную вещь. Это происходит в двух случаях:

  • Предположим, у вас есть более одного пульта , например, если у вас есть origin плюс второй пульт fred для получения материала из хранилища Фреда. Предположим далее, что у вас есть собственный origin/hello, скопированный из ветви hello в источнике, и у Фреда есть Фреда hello, который теперь скопирован в ваш fred/hello. Если вы попытаетесь git checkout hello, ваш Git найдет двух кандидатов - fred/hello и origin/hello - и не знает, какой из них использовать. Так что теперь вы можете запустить вместо:

    git checkout --track fred/hello
    

    если вы действительно хотели использовать Фреда, или:

    git checkout --track origin/hello
    

    если вы действительно хотели использовать origin.

  • Или, если по какой-то странной причине у вас есть, скажем, origin/my_server_branch, но в вашем хранилище вы хотите назвать это bob_server_branch. Использование git checkout my_server_branch дает вам my_server_branch; и, конечно же, с помощью git checkout bob_server_branch пытается найти origin/bob_server_branch. Итак, здесь вам нужна длинная форма:

    git checkout --track bob_server_branch origin/my_server_branch
    

О git pull

Команда git pull является сокращением для:

  • пробег git fetch; тогда, при условии, что это успешно
  • запустить вторую команду Git, обычно git merge.

Поскольку git fetch будет (при запуске с правильными параметрами, в любом случае) создавать и / или обновлять ваши origin/* имена для удаленного отслеживания из ветвей origin, это первая половина git pull это сделало origin/my_server_branch для вас.

Вторая команда - git merge, или, если вы скажете ей использовать git rebase, git rebase - принимает коммиты, введенные с помощью первой команды, и использует их для слияния, или перебазировать.

Я неКак и команда git pull, по ряду причин, некоторые из которых носят чисто исторический характер (git pull использовался, чтобы иногда уничтожать вашу локальную работу в нескольких редких, но не случайных случаях, и я случился со мной вне реже одного раза).Наиболее практичное возражение довольно простое: пока вы не увидите, что git fetch извлечено, как вы узнаете, хотите ли вы запустить git merge, git rebase или что-то еще целиком? Поэтому я предпочитаюизбегать git pull: сначала я запускаю git fetch, затем возможно запускаю git merge или git rebase или, возможно, делаю что-то еще полностью.Что делать, зависит от того, что я видел из git fetch (а также, конечно, от того, что я делаю с этим конкретным репозиторием).

Есть несколько исключений, особенно с репозиториями, которые я использую для чтения-только - я просто хочу их последний коммит плюс его историю, поэтому git pull это , вероятно нормально, пока они ведут себя хорошо - или где я контролирую оба конца, например,origin репозиторий действительно мой на GitHub, и я знаю , что я туда вставил.Но даже в последнем случае я стараюсь избегать git pull, потому что иногда я забываю, что я положил в какой репозиторий.Использование git fetch позволяет сначала проверить.

1 голос
/ 02 мая 2019

git pull работает git fetch и git merge.Просто приятно знать

С первой частью этой команды (git fetch) вы получили все ветви с пульта.Как вы можете прочитать здесь , эта команда получает все refs.

По умолчанию, когда вы извлекаете новую ветку удаленно, git создаст ее как новую ветку восходящего потока.По сути, команда, о которой вы спрашиваете, была запущена для вас неявно, когда вы выбрали все ветви.

1 голос
/ 02 мая 2019

Я не уверен на 100%, что понимаю, о чем вы спрашиваете, но преимущество отслеживания удаленной ветви состоит в том, что вы можете нажимать и извлекать ее.

Проверьте ветку локально: git checkout my_server_branch

Вносить изменения и фиксировать.

Теперь git push перенесет ваши изменения в удаленную ветку origin/my_server_branch.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...