Github: выборка и перебазирование форка на разветвленном мастере

Я создал форк проекта и добавил ~40 коммитов в наш master, В какой-то момент я бездумно переписал историю с принудительным толчком, потому что я не мог толкать "без всякой причины", а иногда вы просто хотите увидеть, как мир горит.

Сейчас все хорошо, но последние ~100 фиксируются на upstream которые также находятся в моем репо, больше не считаются одинаковыми: я вижу "240 коммитов вперед" вместо "40 коммитов вперед".

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

1 ответ

Решение

Я полагаю, у вас есть чистая песочница, где origin указывает на ваш форк, и у вас есть доступ к репозиторию восходящего направления по другому URL. Я также предполагаю origin/master а также master в вашей песочнице синхронизируются.

С этими допущениями это должно работать:

git remote add upstream <upstream_url>
git fetch upstream
git checkout master
git rebase upstream/master

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

Прежде чем начать ребаз, git log --graph --decorate --all (или же gitk -all или любая другая визуальная замена журнала Git, которая показывает полный график) может показать вам, почему у вас возникли проблемы.

РЕДАКТИРОВАТЬ: альтернативный и более консервативный подход заключается в использовании git cherry-pick, Решение rebase опирается на то, что Git признает, что история, которая должна быть общей, состоит из коммитов, уже присутствующих на upstream/master, Но вместо перебазировки вы можете определить родителя 1-го коммита, который вы хотите сохранить, скажем, origin/master~40 если у вас действительно есть 40 фиксированных коммитов, и добавьте их в конце upstream/master:

git remote add upstream <upstream_url>
git fetch upstream
git checkout master
git reset --hard upstream/master
git cherry-pick origin/master~40..origin/master

Это дает вам новый master который явно начинается в upstream/master и добавляет только новую историю, которую вы хотите.

Обратите внимание --hard в git reset --hard upstream/master: как указано OP в комментариях, это необходимо, чтобы убедиться, что вы начинаете с чистого состояния перед сбором вишни. Но сначала убедитесь, что у вас не было ничего незафиксированного, что вы хотели сохранить.

Проверка работоспособности: после вишни (или перебазировки), git diff master origin/master ничего не должен возвращать или снова указывать на другие проблемы, с которыми вам нужно справиться. КОНЕЦ РЕДАКТИРОВАНИЯ

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

git push -f origin master

следует вернуть вилку к тому, чтобы всего 40 коммитов впереди upstream,

Предостережение: я не тестировал решение для rebase, но я вполне уверен, что оно должно работать, основываясь на вашем описании ситуации. Однако я с успехом использовал решение "вишневый пик" в подобных ситуациях. Если вы попробуете любой из этих методов, пожалуйста, сообщите о своем успехе или что-то не так, что потребует корректировки.

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