Как правильно заставить Git push? - PullRequest
1157 голосов
/ 01 апреля 2011

Я установил удаленное, но не «голое» репо и клонировал его на свой компьютер. Я сделал некоторые локальные изменения, обновил свой локальный репозиторий и перенес изменения в мое удаленное хранилище. До этого все было хорошо.

Теперь мне нужно было что-то изменить в удаленном репо. Затем я изменил что-то в своем локальном репо. Я понял, что смена удаленного репо не нужна. Поэтому я попытался git push из моего локального репо в мое удаленное репо, но я получил ошибку вроде:

Чтобы предотвратить потерю истории, обновления не были перенесены отклонено Объединить удаленные изменения перед повторным нажатием. Смотрите «Примечание о разделе ускоренной перемотки git push --help для деталей.

Я думал, что, вероятно,

git push --force

заставит мою локальную копию отправить изменения в удаленную и сделать ее такой же. Это вызывает принудительное обновление , но когда я возвращаюсь к удаленному репо и выполняю фиксацию, я замечаю, что файлы содержат устаревшие изменения (те, которые ранее были в основном удаленном репо).

Как я уже упоминал в комментариях к одному из ответов :

[Я] пытался форсировать, но когда возвращаюсь на главный сервер, чтобы сохранить изменения, я получаю устаревшую постановку. Таким образом, когда я фиксирую репозитории, они не совпадают. И когда я снова пытаюсь использовать git push, я получаю ту же ошибку.

Как я могу исправить эту проблему?

Ответы [ 8 ]

2112 голосов
/ 27 сентября 2012

Просто сделайте:

git push origin <your_branch_name> --force

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

git push https://git.... --force

Это удалит ваши предыдущие коммиты и подтолкнет ваш текущий.

Это может быть неправильно, но если кто-то наткнется на эту страницу, подумал, что может захотеть простое решение ...

Короткий флаг

Также обратите внимание, что -f - это сокращение от--force, поэтому

git push origin <your_branch_name> -f

также будет работать.

230 голосов
/ 23 мая 2013

А если push --force не работает, вы можете сделать push --delete. Посмотрите на строку 2 nd в этом случае:

git reset --hard HEAD~3  # reset current branch to 3 commits ago
git push origin master --delete  # do a very very bad bad thing
git push origin master  # regular push

Но будьте осторожны ...

Никогда не возвращайся в публичную историю!

Другими словами:

  • Никогда force не открывать публичный репозиторий.
  • Не делайте этого или чего-либо, что может сломать кому-то pull.
  • Никогда reset или rewrite истории в репо кто-то, возможно, уже вытащил.

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

Вместо этого сделайте возврат.

И всегда будьте осторожны с тем, что вы подталкиваете к публичному репо . Откат:

git revert -n HEAD~3..HEAD  # prepare a new commit reverting last 3 commits
git commit -m "sorry - revert last 3 commits because I was not careful"
git push origin master  # regular push

Фактически, оба исходных ГОЛОВКИ (из revert и из reset ) содержат одинаковые файлы.


изменить, чтобы добавить обновленную информацию и больше аргументов вокруг push --force

Подумайте о толкающем усилии с арендой, а не о толчке, но все же предпочитайте возвращение Другая проблема push --force может возникнуть, когда кто-то что-то нажимает до вас, но после того, как вы уже получили. Если вы нажмете на вашу перебазированную версию, теперь вы замените работу у других . git push --force-with-lease, представленный в git 1.8.5 ( благодаря @ VonC комментарию к вопросу) пытается решить эту конкретную проблему. По сути, это приведет к ошибке и не будет выдвигаться, если пульт был изменен с момента последней загрузки. Это хорошо, если вы действительно уверены, что push --force нужен, но все же хотите предотвратить больше проблем. Я бы пошел так далеко, чтобы сказать, что это должно быть поведение по умолчанию push --force. Но это еще далеко не оправдание, чтобы заставить push. У людей, которые получили до вашей перебазировки , все равно будет много проблем, которых можно легко избежать, если вместо этого вы вернете . И так как мы говорим о git --push случаях ... Зачем кому-то принудительно толкать?

@ linquize привел хороший пример толкающей силы в комментариях: конфиденциальные данные . Вы ошибочно просочились данные, которые не должны быть отправлены. Если вы достаточно быстры, вы можете «исправить» *, принудительно нажимая сверху.

* Данные будут по-прежнему находиться на удаленном , если вы не выполните сборщик мусора или очистите его как-нибудь . Существует также очевидный потенциал для его распространения другими, которые уже принесли , но вы поняли.

18 голосов
/ 01 апреля 2011

Прежде всего, я бы не стал вносить никаких изменений непосредственно в «основной» репо.Если вы действительно хотите иметь «основное» репо, то вам следует только подтолкнуть его, а не изменять его напрямую.

Что касается получаемой ошибки, пробовали ли вы git pull из локального репо, итогда git push в основной репо?То, что вы сейчас делаете (если я хорошо это понял), это форсирование, а затем потеря ваших изменений в «основном» репо.Сначала вы должны объединить изменения локально.

15 голосов
/ 28 мая 2015

Если я нахожусь в моей локальной ветви A, и я хочу принудительно отправить локальную ветвь B в исходную ветвь CI, можно использовать следующий синтаксис:

git push --force origin B:C
11 голосов
/ 01 апреля 2011

Я бы порекомендовал:

  • толчок только к главному репо

  • убедитесь, что основное репо является голым репо , чтобы никогда не возникало проблем с тем, что рабочее дерево основного репо не синхронизировано с его базой .git. Смотрите " Как перенести локальный репозиторий git на другой компьютер? "

  • Если вам нужно внести изменения в основной репозиторий (клон), клонируйте его (на главном сервере), внесите изменения и вернитесь к нему

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

8 голосов
/ 10 апреля 2017

используйте следующую команду:

git push -f origin master
5 голосов
/ 27 мая 2016

Это было наше решение для замены master в корпоративном репозитории gitHub при сохранении истории.

push -f для мастеринга в корпоративных репозиториях часто отключается для ведения истории веток. Это решение сработало для нас.

git fetch desiredOrigin
git checkout -b master desiredOrigin/master // get origin master

git checkout currentBranch  // move to target branch
git merge -s ours master  // merge using ours over master
// vim will open for the commit message
git checkout master  // move to master
git merge currentBranch  // merge resolved changes into master

подтолкните свою ветку к desiredOrigin и создайте PR

1 голос
/ 23 апреля 2019

У меня был тот же вопрос, но я наконец понял его.Скорее всего, вам нужно выполнить следующие две команды git (заменив хэш номером редакции git commit):

git checkout <hash>
git push -f HEAD:master
...