39. Что такое origin?
Мы видим, что клонированный репозиторий знает об имени по умолчанию удаленного репозитория. Давайте посмотрим, можем ли мы получить более подробную информацию об имени по умолчанию:
Выполните:
git remote show origin
Результат:
$ git remote show origin * remote origin Fetch URL: /Users/alex/Documents/Presentations/githowto/auto/hello Push URL: /Users/alex/Documents/Presentations/githowto/auto/hello HEAD branch (remote HEAD is ambiguous, may be one of the following): style master Remote branches: style tracked master tracked Local branch configured for 'git pull': master merges with remote master Local ref configured for 'git push': master pushes to master (up to date)
Мы видим, что «имя по умолчанию»(«origin») удаленного репозитория – оригинальное hello. Удаленные репозитории обычно размещаются на отдельной машине, возможно, централизованном сервере. Однако, как мы видим здесь, они могут с тем же успехом указывать на репозиторий на той же машине. Нет ничего особенного в имени «origin», однако существует традиция использовать «origin» в качестве имени первичного централизованного репозитория (если таковой имеется).
Что такое remotes/origin/HEAD?
Я так понял, что HEAD может указывать только на ветки удаленного репазитория. Но почему тогда после переключения на удаленную ветку дев стока HEAD все равно указывает на мастер??
remotes/origin/HEAD -> origin/master
Вот согласно статье на хабре
текущее состояние не изменённых файлов, находящихся под контролем версий, есть тот коммит, на который указывает HEAD
ниче не понятно, HEAD в итоге указывает на ту ветку где ты находится или на ветку в которую ты сделал последний коммит?
Отслеживать
задан 10 июл 2016 в 9:05
10.9k 17 17 золотых знаков 62 62 серебряных знака 127 127 бронзовых знаков
head — это указатель на текущее состояние. См. habrahabr.ru/post/157175
10 июл 2016 в 10:02
зачем вы постоянно ставите метки github и gitlab?
10 июл 2016 в 10:40
@Etki ну мне так показалось как будто этот вопрос относится к ним.
10 июл 2016 в 10:41
gitlab и github — всего лишь хранилища, никак не изменяющие интерфейс гита.
10 июл 2016 в 11:19
4 ответа 4
Сортировка: Сброс на вариант по умолчанию
ветка (branch) в git — это (плавающий) указатель на commit.
HEAD / .git/HEAD (технически) — это файл, содержащий указатель либо на текущую (для репозитория) ветку (например, файл может содержать такой текст ref: refs/heads/master ), либо на текущий commit (т.н. detached head, файл содержит строку с хэш-суммой этого commit-а).
удалённый репозиторий ничем не «хуже» вашего локального, и в нём тоже есть такой файл, и информация, выдаваемая командой branch :
remotes/origin/HEAD -> origin/master
сообщает вам о том, что этот файл в удалённом репозитории в момент клонирования содержал ссылку на ветку master (в том же, удалённом репозитории).
Я так понял, что head это та ветка в которую я делаю пуш
push вы делаете в ту ветку, которую сами и указали. либо явно, например так:
$ git push репозиторий ветка
либо неявно, «привязав» вашу локальную ветку к (произвольной) ветке в удалённом репозитории, и вызывая git push без дополнительных параметров.
посмотреть «привязки» веток можно, например, командой remote show репозиторий :
$ git remote show origin . Local branch configured for 'git pull': master merges with remote master Local ref configured for 'git push': master pushes to master (up to date)
по поводу дополнения к вопросу
во-первых, я уже ответил практически на тот же вопрос: Почему получаю detached head?.
во-вторых, вынесу (и дополню) сюда основное:
-
эта строка ( remotes/origin/HEAD -> origin/master ) в выдаче команды branch появляется благодаря наличию в вашем локальном хранилище файла refs/remotes/origin/HEAD , содержащего в вашем случае:
$ cat .git/refs/remotes/origin/HEAD ref: refs/remotes/origin/master
Я так понял, что HEAD может указывать только на ветки удаленного репазитория.
- либо указатель на локальную ветку (т.е., содержать что-то вроде ref: refs/heads/master )
- либо хэш коммита (т.н. «состояние detached head»)
Но почему тогда после переключения на удаленную ветку дев стока HEAD все равно указывает на мастер?
remotes/origin/HEAD -> origin/master
Вот согласно статье на хабре текущее состояние не изменённых файлов, находящихся под контролем версий, есть тот коммит, на который указывает HEAD
- если файл .git/HEAD содержит указатель на локальную ветку (т.е., содержит что-то вроде ref: refs/heads/master ), то, значит, у вас в рабочем каталоге распакован коммит, на который указывает локальная ветка master . хэш этого коммита хранится в файле .git/refs/heads/master
- если же файл .git/HEAD содержит хэш коммита (т.н. «состояние detached head»), то именно этот коммит сейчас и распакован в вашем рабочем каталоге.
Отслеживать
ответ дан 10 июл 2016 в 10:30
aleksandr barakin aleksandr barakin
67.9k 216 216 золотых знаков 77 77 серебряных знаков 219 219 бронзовых знаков
Я вот такой ветки у себя ни разу не видел. Может ли вопрос автора быть связан с тем, что его удаленный репозиторий имеет рабочую копию (не является bare)?
10 июл 2016 в 10:34
Кроме того, не понятно почему HEAD удаленного репозитория вообще оказалась вытянута. Я почему-то всегда думал, что «вытягиваются» только refs/heads/* , а HEAD под этот шаблон не попадает же.
10 июл 2016 в 10:37
@PavelMayorov, Может ли вопрос автора быть связан с тем, что его удаленный репозиторий имеет рабочую копию (не является bare)? — скорее всего, так и есть. по крайней мере у меня в тестах такая строка в выдаче branch -r присутствует только в такой ситуации.
10 июл 2016 в 10:43
@PavelMayorov, «вытягиваются» только refs/heads/* — «вытягивается» то, что указано в директиве fetch в файле config. по умолчанию это +refs/heads/*:refs/remotes/origin/* . вот в refs/remotes/origin и попадает файл HEAD . и, насколько вижу, он не изменяется и остаётся таким же, каким создан при клонировании.
10 июл 2016 в 10:44
@PavelMayorov, stackoverflow.com/q/12613793/4827341
10 июл 2016 в 10:59
head это то состояния версии в которой вы в данный момент находитесь. это значит, если вы переключились на другую ветку и у вас хед позади других коммитов, значит вам нужно сделать pull , чтобы получить свежую версию этой ветки.
И для переключения между ветками лучше использовать git checkout , а для просмотра удаленных веток git remote .
Отслеживать
ответ дан 10 июл 2016 в 9:11
2,904 19 19 серебряных знаков 44 44 бронзовых знака
remotes/origin/master
Это ветка, предназначенная «только для чтения». Её положение обозначает последнее известное (после последнего push / pull / fetch ) положение ветки master на сервере origin .
remotes/origin/HEAD -> origin/master
HEAD в Git это «текущая верхушка». Локальный HEAD обычно показывает место на графе коммитов, в котором сейчас находится рабочее дерево [0] (например, сделан checkout ).
Но здесь другой случай. это не просто HEAD , а из origin . Как и все remote-ветки, предназначен только для чтения, но на что он указывает?
На практике origin/HEAD обычно указывает ветку по умолчанию для удалённого репозитория. Практических последствий у этого почти никаких, разве что при клонировании репозитория локальный HEAD будет там же, где на момент клонирования был HEAD на сервере. Когда вы работаете у себя на машине, origin/HEAD вам не нужен.
Ситуация становится чуть интереснее, когда к удалённому репозиторию есть интерфейс доступа. Для него HEAD может означать что-то ещё. Например, на GitHub origin/HEAD или, как у них называется, default branch можно выбрать в настройках, и прочитать пояснение о том, для чего это надо:
The default branch is considered the “base” branch in your repository, against which all pull requests and code commits are automatically made, unless you specify a different branch.
(«Ветка по умолчанию считается «основной» веткой в вашем репозитории, в которую делаются все pull-request’ы и коммиты, если не выбирать другую ветку явно.» прим. пер.)
Почему origin/* только для чтения? Эти ветки являются «отражением» [1] того, что есть на сервере origin . Поэтому эти ветки меняются только тогда, когда ваши действия меняют репозиторий в origin . Скажем, в процессе push Git передаёт серверу коммиты, дожидается его подтверждения о получении и сдвигает «отражение» на новую точку. Любые изменения в обход этого механизма рискуют сломать саму суть origin/* как отражений.
Если переместиться в ветку-отражение (посредством checkout ), Git заметит, что её нельзя [2] менять, поэтому HEAD перейдёт не в ветку, а на коммит, на котором она находится, отделившись от веток (отсюда detached HEAD ). И с этого момента надо быть осторожным.
текущее состояние не изменённых файлов, находящихся под контролем версий, есть тот коммит, на который указывает HEAD
Надеюсь, из текста выше понятно, что у вас есть HEAD (ваш) и origin/HEAD (удалённый). В статье о первом. А в списке веток есть только последний.
[0] на самом деле скорее наоборот, рабочее дерево само по себе, а HEAD нужен, чтобы вычислить и записать внесённые изменения, это «отправная точка»
[1] этот термин честно выдуман мной, употребляйте осторожно
[2] можно всё, но многие вещи ломают настолько много, что оно того не стоит
3.3 Ветвление в Git — Управление ветками
Теперь, когда вы уже попробовали создавать, объединять и удалять ветки, пора познакомиться с некоторыми инструментами для управления ветками, которые вам пригодятся, когда вы начнёте использовать ветки постоянно.
Команда git branch делает несколько больше, чем просто создаёт и удаляет ветки. При запуске без параметров, вы получите простой список имеющихся у вас веток:
$ git branch iss53 * master testing
Обратите внимание на символ * , стоящий перед веткой master : он указывает на ветку, на которой вы находитесь в настоящий момент (т. е. ветку, на которую указывает HEAD ). Это означает, что если вы сейчас сделаете коммит, ветка master переместится вперёд в соответствии с вашими последними изменениями. Чтобы посмотреть последний коммит на каждой из веток, выполните команду git branch -v :
$ git branch -v iss53 93b412c Fix javascript issue * master 7a98805 Merge branch 'iss53' testing 782fd34 Add scott to the author list in the readme
Опции —merged и —no-merged могут отфильтровать этот список для вывода только тех веток, которые слиты или ещё не слиты в текущую ветку. Чтобы посмотреть те ветки, которые вы уже слили с текущей, можете выполнить команду git branch —merged :
$ git branch --merged iss53 * master
Ветка iss53 присутствует в этом списке потому что вы ранее слили её в master . Те ветки из этого списка, перед которыми нет символа * , можно смело удалять командой git branch -d ; наработки из этих веток уже включены в другую ветку, так что ничего не потеряется.
Чтобы увидеть все ветки, содержащие наработки, которые вы пока ещё не слили в текущую ветку, выполните команду git branch —no-merged :
$ git branch --no-merged testing
Вы увидите оставшуюся ветку. Так как она содержит ещё не слитые наработки, попытка удалить её командой git branch -d приведёт к ошибке:
$ git branch -d testing error: The branch 'testing' is not fully merged. If you are sure you want to delete it, run 'git branch -D testing'.
Если вы действительно хотите удалить ветку вместе со всеми наработками, используйте опцию -D , как указано в подсказке.
Если в качестве аргумента не указан коммит или ветка, то опции —merged и —no-merged покажут что уже слито или не слито с вашей текущей веткой соответственно.
Вы всегда можете указать дополнительный аргумент для вывода той же информации, но относительно указанной ветки предварительно не извлекая и не переходя на неё.
$ git checkout testing $ git branch --no-merged master topicA featureB
Переименование ветки
Не переименовывайте ветки, которые всё ещё используются другими участниками. Не переименовывайте ветку в master/main/mainline, не прочитав раздел «Изменение имени главной ветки».
Предположим, у вас есть ветка с именем bad-branch-name , и вы хотите изменить её на corrected-branch-name , сохранив при этом всю историю. Вместе с этим, вы также хотите изменить имя ветки на удалённом сервере (GitHub, GitLab или другой сервер). Как это сделать?
Переименуйте ветку локально с помощью команды git branch —move :
$ git branch --move bad-branch-name corrected-branch-name
Ветка bad-branch-name будет переименована в corrected-branch-name , но это изменение пока только локальное. Чтобы все остальные увидели исправленную ветку в удалённом репозитории, отправьте её туда:
$ git push --set-upstream origin corrected-branch-name
Теперь проверим, где мы сейчас находимся:
$ git branch --all * corrected-branch-name main remotes/origin/bad-branch-name remotes/origin/corrected-branch-name remotes/origin/main
Обратите внимание, что текущая ветка corrected-branch-name , которая также присутствует и на удалённом сервере. Однако, старая ветка всё ещё по-прежнему там, но её можно удалить с помощью команды:
$ git push origin --delete bad-branch-name
Теперь старое имя ветки полностью заменено исправленным.
Изменение имени главной ветки
Предупреждение
Изменение имени ветки, например master/main/mainline/default, сломает интеграции, службы, вспомогательные утилиты и скрипты сборки, которые использует ваш репозиторий. Прежде чем сделать это, обязательно проконсультируйтесь с коллегами. Также убедитесь, что вы выполнили тщательный поиск в своём репозитории и обновили все ссылки на старое имя ветки в вашем коде или скриптах.
Переименуйте локальную ветку master в main с помощью следующей команды:
$ git branch --move master main
После этого, локальной ветки master больше не существует, потому что она была переименована в ветку main .
Чтобы все остальные могли видеть новую ветку main , вам нужно отправить её в общий репозиторий. Это делает переименованную ветку доступной в удалённом репозитории.
$ git push --set-upstream origin main
В итоге, состояние репозитория становится следующим:
$ git branch --all * main remotes/origin/HEAD -> origin/master remotes/origin/main remotes/origin/master
Ваша локальная ветка master исчезла, так как она заменена веткой main . Ветка main доступна в удалённом репозитории. Старая ветка master всё ещё присутствует в удалённом репозитории. Остальные участники будут продолжать использовать ветку master в качестве основы для своей работы, пока вы не совершите ряд дополнительных действий.
Теперь, для завершения перехода на новую ветку перед вами стоят следующие задачи:
- Все проекты, которые зависят от текущего, должны будут обновить свой код и/или конфигурацию.
- Обновите конфигурацию всех запускаемых тестов.
- Исправьте скрипты сборки и публикации артефактов.
- Поправьте настройки репозитория на сервере: задайте новую ветку по умолчанию, обновите правила слияния, а также прочие настройки, которые зависят от имени веток.
- Обновите документацию, исправив ссылки, указывающие на старую ветку.
- Слейте или отмените запросы на слияние изменений, нацеленные на старую ветку.
После того, как вы выполнили все эти задачи и уверены, что ветка main работает так же, как ветка master , вы можете удалить ветку master :
$ git push origin --delete master
git pull
Команда git pull используется для извлечения и загрузки содержимого из удаленного репозитория и немедленного обновления локального репозитория этим содержимым. Слияние удаленных вышестоящих изменений в локальный репозиторий — это обычное дело в процессе совместной работы на основе Git. Команда git pull на самом деле представляет собой комбинацию двух других команд: git fetch и git merge. На первом этапе git pull выполняется команда git fetch , ограниченная локальной веткой, на которую указывает HEAD . Сразу после загрузки содержимого команда git pull выполняет слияние. Для слитого содержимого создается новый коммит, а указатель HEAD обновляется и переносится на этот новый коммит.
Использование git pull
Порядок действий
Сначала команда git pull запускает команду git fetch для загрузки содержимого из указанного удаленного репозитория. Затем выполняется команда git merge , объединяющая ссылки и указатели удаленного содержимого в новый локальный коммит слияния. Чтобы лучше продемонстрировать процесс извлечения и слияния, рассмотрим пример. Предположим, у нас есть репозиторий с главной веткой main и удаленный репозиторий origin.
В этом сценарии команда git pull загрузит все изменения, начиная с того места, где разошлись локальная и главная ветки. В данном примере это точка E. Команда git pull получит удаленные коммиты из отходящей ветки (т. е. точки A‑B‑C). Затем в процессе запуска команды pull будет создан новый локальный коммит слияния, включающий содержимое новых удаленных коммитов из отходящей ветки.

Связанные материалы
Расширенный журнал Git
СМ. РЕШЕНИЕ
Изучите Git с помощью Bitbucket Cloud
На вышеприведенной схеме мы видим новый коммит H. Это коммит слияния, в который входит содержимое удаленных коммитов A‑B‑C и который имеет общее сообщение в журнале. Этот пример демонстрирует одну из нескольких стратегий слияния с помощью команды git pull . Чтобы сделать перебазирование, а не коммит слитого содержимого, укажите для команды git pull параметр —rebase . В следующем примере демонстрируется, как работает перебазирование с помощью команды pull. Предположим, что мы находимся в начальной точке нашей первой схемы и выполнили команду git pull —rebase .

На этой схеме видно, что при перебазировании с помощью команды pull не был создан новый коммит H. Вместо этого удаленные коммиты A‑B‑C были скопированы и добавлены в историю в локальной ветке origin/main перед локальными коммитами E–F–G с перезаписью последних.
Распространенные опции
git pull
Извлечь из указанного удаленного репозитория копию текущей ветки и немедленно слить ее с локальной копией. Эта команда аналогична команде git fetch , после которой следует команда git merge origin/ .
git pull --no-commit
Подобно вызову по умолчанию, извлекает удаленное содержимое, но не создает новый коммит со слитым содержимым.
git pull --rebase
Аналогично предыдущей команде pull, только вместо команды git merge для интеграции удаленной ветки с локальной веткой используется команда git rebase .
git pull --verbose
Во время выполнения команды pull выдает подробный вывод о загружаемом содержимом и информацию о слиянии.
Обсуждение git pull
Команду git pull можно представить как версию команды svn update , только применимую в системе Git. Это простой способ синхронизировать локальный репозиторий с вышестоящими изменениями. На диаграмме ниже даны пояснения к каждому шагу процесса выполнения команды pull.
Сначала вы думаете, что ваш репозиторий синхронизирован, однако команда git fetch показывает, что с момента последней проверки версия origin ветки main была изменена. Затем команда git merge сразу интегрирует удаленную ветку main в локальную ветку.
Git pull и синхронизация
Команда git pull — одна из множества команд, отвечающих за синхронизацию удаленного содержимого. Команда git remote используется, чтобы указать, на каких удаленных конечных точках будут работать команды синхронизации. Команда git push используется для выгрузки содержимого в удаленный репозиторий.
Команду git fetch можно перепутать с командой git pull . Обе они используются для загрузки удаленного содержимого, но при этом git pull и git fetch значительно различаются по уровню безопасности. Команду git fetch можно считать «безопасным» вариантом, а git pull — «небезопасным». Команда git fetch загружает удаленное содержимое, но не изменяет состояние локального репозитория, в то время как git pull загружает удаленное содержимое и сразу пытается изменить состояние локального репозитория, чтобы оно соответствовало этому содержимому. Это может привести к возникновению непредумышленного конфликта в локальном репозитории.
Сравнение pull и rebase
Параметр —rebase можно использовать, чтобы сохранить линейную историю и избежать ненужных коммитов слияния. Многие разработчики предпочитают выполнять перебазирование, а не слияние, как бы заявляя: «Я хочу, чтобы мои изменения добавились поверх всех остальных». В этом смысле команда git pull с флагом —rebase больше похожа на команду svn update , чем на простую команду git pull .
На самом деле команда pull с опцией —rebase используется в рабочем процессе настолько часто, что для нее существует выделенная опция конфигурации:
git config --global branch.autosetuprebase always
После выполнения этой команды все команды git pull будут интегрироваться с помощью команды git rebase , а не git merge .
Примеры использования git pull
В нижеприведенных примерах показано, как использовать команду git pull в общих сценариях.
Поведение по умолчанию
git pull
Вызов команды git pull по умолчанию эквивалентен выполнению команд git fetch origin HEAD и git merge HEAD , где HEAD — это указатель на текущую ветку.
Команда git pull на удаленных ветках
git checkout new_feature
git pull
В этом примере сначала создается ветка и происходит переключение на нее. После этого выполняется команда git pull , в которой передается удаленный репозиторий . Это приводит к неявной загрузке (выполнению команды pull) ветки newfeature из удаленного репозитория . Как только загрузка завершается, начинается выполнение команды git merge .
Перебазирование с помощью git pull вместо слияния
В следующем примере показано, как выполнить синхронизацию с главной веткой main центрального репозитория, используя перебазирование.
git checkout main
git pull --rebase origin
В этом примере ваши локальные изменения просто помещаются поверх изменений всех остальных участников разработки.