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 не будет пытаться сделать то же самое предположение, если у них его еще нет.

Другие вопросы по тегам