Git push с полным refspec не работает
У меня 2 ветки (локально и удаленно на github). Я буду называть их BranchA и BranchB. У меня есть BranchA с коммитами c1, c2 и c3. У меня есть BranchB только с коммитом c1. Обе ветви полностью обновлены с помощью github, и я могу проверить, что у BranchA есть c1, c2 и c3, а у BranchB только c1.
Я хочу нажать от локального BranchA до удаленного BranchB. Для этого я стараюсь:
git push origin refs/heads/BranchA:refs/remotes/origin/BranchB
Когда я делаю это, я получаю странный вывод:
Total 0 (delta 0), reused 0 (delta 0)
To https://github.com/<username>/<repo>.git
<hash> BranchA -> origin/BranchB
Когда я захожу на github, я вижу, что BranchB не обновляется и все еще имеет только c1. Затем, если я снова выполню команду, она вернет, что все обновлено.
Это сбивало меня с толку, но стало еще хуже, так как, когда я пытаюсь выполнить команду без полного ref, вот так:
git push origin BranchA:BranchB
...это сработало.
Я очень смущен этим. Я искал его и думал, что использование полной ссылки (например,/refs/heads) никогда не принесет вреда.
Почему это происходит? Разве это не должно работать, когда я указываю полное имя ветви?
1 ответ
Как прокомментировал прахлад венката, ссылка на пульте refs/heads/BranchB
не refs/heads/remotes/BranchB
,
Помните, что при использовании git push
или его аналог, git fetch
В этом процессе участвуют два Gits и два хранилища. Давайте назовем эти ваши (Матовски) и GitHub's.
Ваш Git имеет ветку с именем BranchA
чье полное имя refs/heads/BranchA
, Это имя хранит (один) хэш-идентификатор.
Их Git имеет ветку с именем BranchB
чье полное имя refs/heads/BranchB
, Их Git, вероятно, также имеет ветку с именем BranchA
, В этих именах также хранятся хэш-идентификаторы (по одному).
Когда ваш Git общается с GitHub's Git, ваш Git видит их refs/heads/BranchA
и их refs/heads/BranchB
, Ваш Git хотел бы запомнить эти две пары имя-идентификатор, но если ваш Git сохранил их как refs/heads/BranchA
а также refs/heads/BranchB
Ваш Git перезапишет ваши собственные ветви. Таким образом, ваш Git переименовывает их ветви названия, заменяя refs/heads/
с refs/remotes/origin/
,
Другими словами, refs/remotes/origin/BranchB
это память вашего Git's их Git's refs/heads/BranchB
, Но когда ваш Git говорит со своим Git, ваш Git должен сказать своему Git:Пожалуйста, установите вашrefs/heads/BranchB
, Если ваш Git просит их Git установить их refs/heads/origin/BranchB
, что бы установить их Git's память о каком-то третьем Git's refs/heads/BranchB
(что, как вы только что видели, иногда разрешено! - в данном случае это просто не имеет никакого полезного эффекта, так как Git-репозитории GitHub не используют их самостоятельно).
Когда вы используете сокращенный синтаксис git push origin BranchA:BranchB
Ваш Git отправляет Git запрос на установку BranchB
, На основании этого запроса их Git выясняет, что вы, вероятно, хотели установить их refs/heads/BranchB
и делает то, что (он думает) вы имели в виду, а не то, что вы просили. Этот конкретный трюк работает только тогда, когда у них уже есть refs/heads/BranchB
так как их Git не будет пытаться сделать то же самое предположение, если у них его еще нет.