Git переписать мастер с веткой - PullRequest
0 голосов
/ 26 февраля 2019

Я клонировал репозиторий и создал новую ветку.Забыл оформить заказ в новом филиале.Сделал изменения (удалил большинство файлов), добавил, зафиксировал, а затем отправил на удаленный.Теперь я потерял мастера.

Попытка вернуться в предыдущее состояние:

git checkout master
git reset --hard Tony_branch
git push -f origin master

Результаты:

Total 0 (delta 0), reused 0 (delta 0)
remote: Processing changes: done
To ssh://<link> can't share the name obviously.
 ! [remote rejected] master -> master (non-fast forward)
error: failed to push some refs to

Все ответы предполагают "git pull".Но он будет повторно удалять файлы ...

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

РЕДАКТИРОВАТЬ:

Я пытаюсь восстановить старый мастер, перезаписав его с веткой Iсозданный до изменений ... другие пути могут быть лучше, конечно.

Ответы [ 4 ]

0 голосов
/ 26 февраля 2019

Если вы не уверены в сбросе / возврате, я бы сделал следующие шаги вместо сброса / возврата:

(давайте предположим, что ветвь, которую вы создали перед изменениями, - это good-master-branch")

  1. Переключите основную ветку git с главной на другую (например," good-master-branch ")

Если вы используете такие инструменты, как github илиbitbucket, вы можете сделать настройку в графическом интерфейсе.

Удалить вашу текущую плохую главную ветку

Сначала убедитесь, что вы не находитесь в главной ветви git checkout good-master-branch

удалить локальную git branch -D master

удалить удаленнуюgit push origin --delete master

Создать новую основную ветку с хорошим кодом

git checkout good-master-branch

git checkout -b master

Установите новую ветку 'master' в качестве основной ветки git

Теперь у вас есть новая и чистая ветка master!

0 голосов
/ 26 февраля 2019

Кажется, ваш пульт не примет git push -f.Поэтому, если вы не можете исправить защиту веток на удаленном компьютере (gitlab, github, bitbucket), вы не сможете отменить основную ветвь.

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

Другой способ - сделать

git checkout master
git reset --hard origin/master
git reset Tony_branch #soft reset on purpose
git add ... # all changes
git commit -m 'Reverting master to state before bad push'
git push origin master
0 голосов
/ 26 февраля 2019

Существует два основных способа исправить такую ​​ошибку:

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

Другие варианты - принять ошибку как часть истории и добавить исправление также в историю.

Естьпо крайней мере пару способов сделать каждый из них.


Перезапись истории

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

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

Вторая возможная проблема заключается в том, если другие клоны уже включили ошибочные коммиты в master, затем принудительное нажатие, чтобы удалить эти коммиты из истории master, «сломает» эти клоны, и им придется предпринять шаги для восстановления.Если они выполняют неправильные шаги, они могут легко повторно ввести удаленные коммиты, и это особенно важно, если у них есть какая-либо новая работа, основанная на коммитах, которые вы бы отменили.См. git rebase документы в разделе «Восстановление из исходной версии»;хотя то, что вы делаете, само по себе не является перебазированием, применима та же ситуация.

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


Добавление исправления

В настоящее время ваш репо может выглядеть как

... x <--(tony_branch)
     \
      A -- B -- C <--(master)(origin/master)

Теперь вам нужнопереместить origin/master в x;это сделало бы "самую чистую" историю.(И, если мы будем честными, это позволит избежать постоянного учета промахов. Это не означает, что у нас есть какие-либо причины вести учет ошибок; только то, что мы хотим избавиться от такогозапись может казаться более важной, чем она - , взвешенная с учетом стоимости переписывания истории.)

Но вы читали это далеко, потому что очевидно переписываете origin/masterИстория России не является приемлемым вариантом.Поэтому обычно люди предлагают использовать git revert.Это приведет к чему-то вроде

... x <--(tony_branch)
     \
      A -- B -- C -- ~CBA <--(master)(origin/master)

, где ~CBA отменяет изменения с A, B и C, оставляя содержимое (объект TREE) на master простокак то, что было на x.Это один из вариантов;это просто и оставляет вещи в прямом состоянии для любых будущих команд git.

Другой вариант - использовать коммит слияния для возврата.Это делает A, B и C похожими на боковую ветвь, которая была оставлена.«Верх» состоит в том, что немного легче понять, что A .. C можно / нужно игнорировать; «недостатком» является то, что рассматриваемое слияние будет немного неестественным - то, что иногда называют"злое слияние".Если вы, вероятно, перебазируете этот раздел коммитов, тогда может возникнуть проблема «злого слияния», но опять же, поскольку мы идем туда, потому что переписывание истории master не является чем-то, возможно, это не имеет значения,В любом случае, это выглядело бы как

... x <--(tony_branch)
    |\
    | \---------- Y <--(master)(origin/master)
     \           /
      A -- B -- C 

Чтобы сделать это, вы могли бы сказать

git checkout master
git reset --hard tony_branch
git merge -s ours origin/master
git push

Обратите внимание, что при любом подходе коммиты с A по C включаются в историю master.Это означает, что больше невозможно «повторно применить» изменения вашей ветви, объединив эти коммиты в master - потому что они «уже есть».Чтобы это исправить, вы можете создать копии коммитов A - C и поместить эти копии в tony_branch.Это можно сделать до или после обновления master (путем возврата или слияния);раньше это могло бы быть немного проще, но я не включил туда инструкции, потому что было проще объяснить почему здесь.

Так что вы бы сделали "принудительную перезагрузку" из A до C.Вопреки распространенному мнению, rebase не «заменяет» исходные коммиты, а скорее копирует их.Принудительная операция просто означает «сделать копии, даже если я не изменяю основание или что-то еще».Первый шаг - проверить C.Как это сделать, зависит от того, какие другие шаги вы предприняли:

(A) После применения слияния к master вы могли бы

git checkout master^2

, что ставит вас в отдельное состояние HEAD укажите второго родителя коммита слияния в master.ИЛИ

(B) После применения отмены вы можете

git checkout master^

(если возврат был применен за один коммит; это было бы что-то вроде master~3, если отдельные изменения отката были зафиксированыбыли использованы, заменив 3 тем не менее, было использовано много фактических возвращаемых коммитов).ИЛИ

(C) До исправления master, вы можете просто

git checkout --detach master

, но учтите, что do хотите оказаться всостояние «обособленная ГОЛОВА», чтобы избежать неправильного перемещения ветки master;следовательно, опция --detach.

Теперь, проверив C, вы можете

git rebase -f tony_branch
git branch -f tony_branch

, и вы получите что-то вроде

      A' -- B' -- C' <--(tony_branch)
     /
... x ----------- Y <--(master)(origin/master)
     \           /
      A -- B -- C 
0 голосов
/ 26 февраля 2019

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

Во-первых, извлеките новую ветку из master локально:

# from master
git checkout -b Tony_branch_real

Затем верните сделанные вами коммиты в master:

# again, from master
git revert A^..B

Здесь A представляет первый непреднамеренный коммит, который вы сделали для master, а B представляет последний непреднамеренный коммит.git revert добавит новый коммит к вашей ветке master, который функционально отменяет любой (включительно) диапазон коммитов, которые A до B делали.Ваша фактическая команда будет выглядеть примерно так:

git revert dk93kg93^..k20gjei9

, где A и B были заменены их хэшами SHA-1.Проверьте git log в ветке master, чтобы найти требуемые хэши SHA-1.

Наконец, вам нужно всего лишь регулярно нажимать master на пульте:

git push origin master

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

Причина, по которой мы избегаем таких вещей, как hard reset на master, заключается в том, что, возможно, эта ветвь используется другими разработчиками.Аппаратная перезагрузка переписывает историю, и поэтому мы хотим избежать этого для общедоступных веток.

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