Почему "git push helloworld +master:master" вместо просто "git push helloworld"?

Сначала я попытался запустить свое (первое в истории!) Git-репо следующим образом:

$ git push helloworld

Но я получил это обратно:

To git-smichaels@free5.projectlocker.com:helloworld.git
 ! [rejected]        HEAD -> master (non-fast forward) error:
 failed to push some refs to 'git-smichaels@free5.projectlocker.com:helloworld
git'

Поэтому я нашел другой вопрос Stackru о "исправленных коммитах" и попробовал оттуда предложение, не зная, поможет ли оно мне:

KaiserSosa@SMICHAELS /c/test/helloworld (master)
$ git push helloworld +master:master

Это сработало!

Но я не знаю, почему это решило мою проблему:(

Может ли кто-нибудь объяснить, почему это работает, но "git push helloworld"не?

1 ответ

Решение

Похоже, вы переписали свою историю (SHA-1, связанную с вашим коммитом) в вашей основной ветке.

Это означает, что вы больше не можете нажимать в режиме быстрой перемотки вперед.

+ мастер заставляет толчок произойти:
Имея опциональный ведущий +, вы можете сказать git обновить <dst> Ссылка, даже если обновление не является быстрой перемоткой вперед.

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


Примечание: как упомянул Хунио С. Хамано:

Существует два независимых механизма безопасности:

  • безопасность отправляющего конца может быть отмененаgit push --force"и / или используя refspec с префиксом '+");

  • безопасность принимающей стороны может быть переопределена переменной config receive.denynonfastworwards репозитория, в который вы продвигаетесь.

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


Как упоминалось в Git FAQ, возможный курс действий:

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

 $ git fetch origin
 $ git log master..origin/master

перечислит все изменения, которые есть у удаленной стороны, которых нет у вашей стороны.
Если вы хотите графическое представление, используйте gitk --left-right master...origin/master,
Стрелки слева - изменения, которые вы хотите нажать, стрелки справа - изменения на удаленной стороне.

Другое решение (что вы и сделали):

$ git push origin +branchname

Это заставит обновление. Если у вас нет разрешения, то иногда это будет работать:

$ git push origin :branchname
$ git push origin +branchname

то есть, сначала удалите ветку удаленно (это часто разрешено), затем повторно нажмите "новую" (или, возможно, перемотанную) ветку.

Имейте в виду, что если вы перематываете ветки, у других могут возникнуть проблемы при вытягивании.
Существует вероятность того, что они сольются в ветке, которую они загрузили, с новой, которую вы опубликовали, эффективно сохраняя изменения, от которых вы пытаетесь избавиться.
Однако, только их копии имеют плохие ревизии. По этой причине перематывание ветвей считается слегка асоциальным. Тем не менее, это часто уместно.

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