git push –force и как с этим бороться

Вы когда-нибудь оказывались в ситуации, когда неправильная команда git наносила ущерб репозиторию вашего проекта? Люди совершают ошибки, и иногда они могут стоить вашей команде часов рабочего времени. В этом руководстве мы покажем вам, как быстро восстановиться после неудачного git push --force .

Не будем слишком самоуверенны. Рано или поздно это произойдет. При работе с несколькими пультами в одном репозитории git вы в конечном итоге git push --force в master (или еще одна важная ветка, с которой никогда не следует связываться).

Это может произойти, например, при развертывании с помощью Deis или Heroku, которые используют отдельные пульты git для сборки и развертывания приложения. После долгого рабочего дня невероятно легко выполнить git push --force вместо обычного git push --force deis master .

Ой! В мгновение ока ваши товарищи по команде потеряли все свои последние работы. Пора столкнуться с их гневом.

Однако, как говорит нам один отличный гид, НЕ ПАНИКА! Хорошо, что вы используете git, а это значит, что все можно исправить.

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

Если вам повезет , в их локальном репозитории будет полная история коммитов, ваша ошибка будет перезаписана новым кодом, и ничего не будет потеряно. Но что, если вам не повезло? Тогда читайте дальше!

Случай 1: вы были последним, кто перешел на master до ошибки

Хорошие новости! У вас есть все необходимое, чтобы исправить ошибку прямо на ваших глазах. Просто не закрывайте и не очищайте терминал. Сначала зайдите в чат своей команды и исповедуйте свои грехи. Попросите людей не связываться с репозиторием в течение следующей минуты или около того, пока вы что-то исправляете.

В выводе команды git push --force в вашем оболочка найдите строку, похожую на эту:

  + deadbeef ... f00f00ba master -> master (принудительное обновление)  

Первая группа символов (которая выглядит как префикс SHA коммита) – это ключ к спасению. deadbeef – это ваша последняя удачная фиксация перед master непосредственно перед тем, как вы нанесли ущерб.

Итак, все, что вам нужно, это… принудительно нажать (тушить огонь огнем!) Эту фиксацию обратно в ветку master , поверх плохой.

  $ git push --force origin deadbeef: master  

Поздравляю! Вы спасли положение. Пришло время учиться на своих ошибках.

Случай 2: master был изменен кем-то другим, прежде чем вы напортачили

Итак, непосредственно перед тем, как вы сделали git push --force кто-то закрыл кучу запросов на вытягивание, и теперь master не похож на вашу локальную копию. Вы больше не можете выполнять git push --force sha1: master , поскольку у вас нет последних локальных коммитов (и вы не можете получить их с помощью git fetch , потому что они больше не принадлежат ни одной ветке). Тем не менее, сохраняйте спокойствие и попросите своих товарищей по команде ненадолго держаться подальше от пульта ДУ.

Мы выиграем от того факта, что GitHub не удаляет сразу недоступные коммиты. Конечно, вы также не можете получить их, но есть обходной путь.

Обратите внимание, что он будет работать, только если вы «наблюдаете» за репозиторием, так что все, что в нем происходит появляется в ленте, отображаемой на главной странице вашего GitHub. Откройте этот канал и найдите что-то вроде этого:

  час назад Имя пользователя передано в master в org/repo - deadbeef Implement foo - deadf00d Fix bar  

Теперь вы можете:

  • Составить URL https://github.com/org/repo/tree/deadbeef , где deadbeef – это хэш последнего исправного коммита в поврежденную ветку;
  • Откройте переключатель ветвей/тегов в веб-интерфейсе GitHub;

Переключатель веток/тегов GitHub

  • Создайте имя для новой временной ветви (например, master-before-force-push );
  • Нажмите «Создать ветку».

Теперь вы можете получить все недостающие коммиты:

  $ git fetchFrom github.com:org/repo * [новая ветка] master-before-force-push -> origin/master-before-force-push  

Теперь ваша проблема сведена к проблеме, описанной в предыдущем примере:

  $ git push --force origin origin/master-before-force-push: master  

Если вам по-прежнему нужно, чтобы ваша работа находилась в master , просто переместите поверх нее:

  $ git rebase origin/master  

Как избежать такой катастрофы в будущем

  1. GitHub и GitLab имеют функцию под названием «защищенные ветки». Отметьте master , develop , stable или любые другие важные ветки как защищенные, и никто не сможет принудительно нажать в них. Всегда можно временно «снять защиту» с ветки, если вам действительно нужно перезаписать историю.

    Подробности читайте в документации GitHub.

  2. Вместо параметра - force используйте - force-with-lease . Он остановит операцию отправки, если кто-то нажал на ту же ветку, пока вы над ней работали (и не извлек никаких изменений).

    См. Эту статью в Atlassian.

  3. Создайте псевдонимы для команд, использующих git push --force , чтобы предотвратить случайные деструктивные действия:

      # ~/.gitconfig [alias] deploy = "! git push --force deis " $ (git rev-parse --abbrev-ref  HEAD): master  ""  

    Прочтите главу ProGit о псевдонимах.

  4. Никогда не проводите эксперименты в основной ветке репозитория! git checkout -bexamples – ваш лучший друг.


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



Как мне правильно принудительно выполнить Git push?

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

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

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

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

  git push --force  

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

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

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

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


Просто выполните:

  git push origin  --force  

или, если у вас есть конкретное репо:

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

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

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

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

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

  git push origin  -f  

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


263

И если push --force не работает, вы можете использовать push --delete . Посмотрите на 2 строки nd в этом экземпляре:

  git reset --hard HEAD ~ 3 # сбросить текущую ветку до 3, фиксирует agogit push origin  master --delete # сделать очень-очень плохую вещь git push origin master # обычный push  

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

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

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

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

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

  git revert -n HEAD ~ 3..HEAD # подготовить новую фиксацию откат последних 3 коммитов git commit -m "извините - отменить последние 3 коммита, потому что я не был осторожен  "git push origin master # regular push  

По сути, оба исходных HEAD (из revert и из злого сброса ) будет содержать те же файлы.


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

Рассмотрите возможность принудительного использования силы с арендой вместо push, но все же предпочтите возврат

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

git push - -force-with-lease , представленный в git 1.8.5 (благодаря комментарию @VonC к вопросу), пытается решить эту конкретную проблему. По сути, это приведет к ошибке и не будет нажимать, если пульт был изменен с момента последней загрузки.

Это хорошо, если вы действительно уверены, что push --force необходим, но все же хочет предотвратить другие проблемы. Я бы сказал, что это должно быть поведение по умолчанию push --force . Но это все еще далеко не повод для принудительного push . Люди, которые загрузили до вашего rebase , по-прежнему будут иметь множество проблем, которых можно было бы легко избежать, если бы вы вместо этого вернули .

И поскольку мы говорим об экземплярах git --push

Зачем кому-то принудительно нажимать ?

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

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

Улучшить этот ответ
отредактировал 20 июня ’20 в 9:12
Сообщество ♦
111 серебряных значков
ответил 22 мая ’13 в 22:03
  • 1
    Проблема, @rogerdpack, не в том, выполнима ли она. Это. Но это может привести к большой катастрофе. Чем больше кто-то это делает (принудительно нажимает) и чем реже вы обновляете (извлекаете) из публичного репо, тем больше катастрофа. Он может разрушить мир, каким вы его знаете !!! 111 По крайней мере, мир, состоящий из этого конкретного хранилища. – cregox 24 сен. ’13 в 19:14
  • 3
    Если у вас есть конфиденциальные данные, нажмите их принудительно – linquize 26 ноября 2013 г., 16:58
  • 3
    @Cawas: Я думаю, он имеет в виду, что если вы пытаетесь удалить конфиденциальные данные из репозитория, тогда вы хотите переписать историю. Если вы вернетесь, конфиденциальные данные останутся в предыдущем коммите. Тем не менее, если кто-то другой уже получил данные из репозитория, то перезапись истории не поможет вам предотвратить доступ к конфиденциальным данным – в этот момент уже слишком поздно. – Стюарт Голодец, 12 дек. ’13 в 9:38
  • 1
    @StuartGolodetz спасибо за разъяснения! Я совершенно неверно истолковал здесь « чувствительный » – я думал просто «важный», а не «секретный». – Cregox 12 дек. ’13 в 12:58
  • 3
    git push origin master --delete # сделать очень-очень плохую вещь git push origin master # регулярный push это на самом деле отлично решило мою проблему (в репо только со мной и мой друг). возможно, это неправильно для публичных репозиториев, но для частных это спасение жизни. – Джан Пойразоглу 26 янв., 2014 в 23:44
| показать 5 дополнительных комментариев

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

  git reset --hard HEAD ~ 3 # сбросить текущую ветку до 3, фиксирует agogit push origin  master --delete # сделать очень-очень плохую вещь git push origin master # обычный push  

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

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

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

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

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

  git revert -n HEAD ~ 3..HEAD # подготовить новую фиксацию откат последних 3 коммитов git commit -m "извините - отменить последние 3 коммита, потому что я не был осторожен  "git push origin master # regular push  

По сути, оба исходных HEAD (из revert и из злого сброса ) будет содержать те же файлы.


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

Рассмотрите возможность принудительного использования силы с арендой вместо push, но все же предпочтите возврат

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

git push - -force-with-lease , представленный в git 1.8.5 (благодаря комментарию @VonC к вопросу), пытается решить эту конкретную проблему. По сути, это приведет к ошибке и не будет нажимать, если пульт был изменен с момента последней загрузки.

Это хорошо, если вы действительно уверены, что push --force необходим, но все же хочет предотвратить другие проблемы. Я бы сказал, что это должно быть поведение по умолчанию push --force . Но это все еще далеко не повод для принудительного push . Люди, которые загрузили до вашего rebase , по-прежнему будут иметь множество проблем, которых можно было бы легко избежать, если бы вы вместо этого вернули .

И поскольку мы говорим об экземплярах git --push

Зачем кому-то принудительно нажимать ?

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

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


18

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

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

Улучшите этот ответ
ответил 01 апр. ’11 в 17:42
  • Да, я пробовал тянуть, но из-за этого теряю данные. Я хочу, чтобы мои основные репозитории были такими же, как и мои локальные, без предварительного обновления из основного. – Спайрос 01 апр. ’11 в 18:28
  • 1
    В этом случае используйте git push -f , но затем, если вы снова измените свое основное репо, вам придется вернуться к локальному репо и git pull , чтобы синхронизировать с последними изменениями. Затем вы можете делать свою работу и снова толкать. Если вы будете следовать этому рабочему процессу «push-pull», вы не получите ошибку, на которую жаловались. – ubik 01 апр. ’11 в 17:22
  • Да, я понимаю, что это была моя вина:/Я попробую это и вернусь через некоторое время, спасибо – Спайрос 01 апр. ’11 в 18:56
  • 1
    пробовал форсировать, но при возврате чтобы мастер-сервер сохранить изменения, я получаю устаревшую постановку. Таким образом, когда я фиксирую, репозитории не совпадают. И когда я снова пытаюсь использовать git push, я получаю ту же ошибку. – Spyros 02 апр. ’11 в 18:11
добавить комментарий |

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

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


17

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

  git push --force origin B: C   

Улучшите этот ответ
ответил 28 мая 2015, 18:25
  • 2
    I обнаружил, что даже я нахожусь в своей локальной ветке B, мне все равно нужно выполнить git push --force origin B: C . В моем случае кажется, что git push --force origin C будет нажимать только с локального мастера на удаленную ветку C, независимо от того, в какой ветке я сейчас нахожусь. git версии 2.3.8 (Apple Git-58) – Вейши Цзэн, 10 октября 2015 г., 17:28
добавить комментарий |

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

  git push --force origin B: C  

12

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

  git push -f origin master  

Улучшите это ответ
ответ дан 10 апр. ’17 в 14:00
  • 2
    Может быть, дайте еще несколько объяснений, почему этот ответ предпочтительнее других и чем он отличается. – Адам, 10 апр. 2017, 15:41
  • о, извините за неудобства, у меня была та же проблема, и эта команда решает ее, я подумал, что должен поделиться ею. – Мустафа Эльсайед 11 апр. ’17 в 14:30
  • 14
    Он такой же, как и другие, вы просто изменили положение флага -f … – svelandiag 31 мая ’17 в 15:38
добавить комментарий |

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

  git push -f origin master  

11

Я действительно рекомендую:

  • нажимать только на основное репо

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

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

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

Улучшите этот ответ
отредактировано 23 мая ’17 в 12:02
Сообщество ♦
111 серебряный значок
ответил 01 апр. : 53
добавить комментарий |

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

  • нажимать только на основное репо

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

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

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


5

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

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

  git fetch желаемыйOrigingit checkout -b master desireOrigin/master//получить исходный мастер  

  git checkout currentBranch//перейти к целевой ветке git merge -s ours master//merge using ours over master//vim откроется для сообщения фиксации git checkout master//перейти к mastergit merge currentBranch//объединить разрешенные изменения в master  

переместите свою ветку в desireOrigin и создайте PR

Улучшить этот ответ
ответил 26 мая ’16 в 21:31
добавить комментарий |

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

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

  git fetch желаемого   pre>  git checkout currentBranch//перейти к целевой ветке git merge -s ours master//merge using ours over master//vim откроется для сообщения фиксации git checkout master//перейти к mastergit merge currentBranch//merge  разрешенные изменения в мастер  

переместите свою ветку в desireOrigin и создайте PR


3

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

  git checkout  git push -f HEAD:  мастер  

Улучшите этот ответ
ответил 23 апр. ’19 в 18:02
добавить комментарий |

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

  git checkout  git push -f HEAD:  мастер  

Оцените статью
futurei.ru
Добавить комментарий