Повторное выполнение отмененного слияния в Git
-
21-08-2019 - |
Вопрос
Здесь я столкнулся с небольшой проблемой:У меня была ветка, посвященная конкретной проблеме 28s
в Git, который я объединил в общий develop
ветвь.Оказывается, я сделал это слишком быстро, поэтому использовал git-revert, чтобы отменить слияние.Однако теперь пришло время объединиться. 28s
в develop
, но команда git-merge видит исходное слияние и радостно сообщает, что все в порядке и ветки уже объединены.Что мне теперь делать?Создать коммит «Revert «Revert «28s -> development»»?Кажется, это не лучший способ сделать это, но на данный момент я не могу представить другого.
Как выглядит древовидная структура:
Решение
Вам нужно «вернуть возвращение».В зависимости от того, как вы это вернули, это может быть не так просто, как кажется.Посмотрите на официальный документ по этой теме.
---o---o---o---M---x---x---W---x---Y
/
---A---B-------------------C---D
позволять:
---o---o---o---M---x---x-------x-------*
/ /
---A---B-------------------C---D
Но все ли это работает?Конечно, это так.Вы можете вернуть слияние, и с чисто технического угла GIT сделал это очень естественно и не имел реальных проблем.
Это просто считало это изменением от «государства до слияния» к «состоянию после слияния», и это было так.
Ничего сложного, ничего странного, ничего действительно опасного.Git сделает это, даже не задумываясь об этом.Итак, под техническим углом нет ничего плохого в том, чтобы вернуть слияние, но С угла рабочего процесса это то, чего вы обычно должны пытаться избежать.
Если это вообще возможно, например, если вы найдете проблему, которая была объединена в главное дерево, вместо того, чтобы отменить слияние, попробуйте Действительно сложно:
- разделите проблему пополам на ветку, которую вы объединили, и просто исправьте ее,
- или попытаться отменить отдельную фиксацию, вызвавшую это.
Да, это сложнее, и нет, это не всегда будет работать (иногда ответ:"Ой, я действительно не должен был объединять его, потому что это еще не было готово, и мне действительно нужно отменить все о слиянии»).Итак, вы действительно должны вернуть слияние, но когда вы хотите повторно сделать слияние, теперь вам нужно сделать это, отказавшись от возврата.
Другие советы
Предположим, у вас есть такая история
---o---o---o---M---W---x-------x-------*
/
---A---B
Где A, B не удалось зафиксировать, а W - возврат M
Поэтому, прежде чем я начну исправлять найденные проблемы, я делаю выборочный коммит W в свою ветку.
git cherry-pick -x W
Затем я возвращаю фиксацию W в свою ветку.
git revert W
После этого я смогу продолжить исправление.
Окончательная история могла бы выглядеть так:
---o---o---o---M---W---x-------x-------*
/ /
---A---B---W---W`----------C---D
Когда я отправлю PR, он ясно покажет, что PR отменяется и добавляется несколько новых коммитов.
Чтобы отменить возврат, не слишком усложняя рабочий процесс:
- Создайте локальную мусорную копию development
- Отменить фиксацию возврата в локальной копии разработки.
- Объедините эту копию с вашей функциональной веткой и отправьте ее на свой git-сервер.
Теперь вашу ветку функций можно будет объединить как обычно, когда вы будете к этому готовы.Единственным недостатком здесь является то, что в вашей истории будет несколько дополнительных коммитов слияния/отката.
Чтобы отменить возврат в GIT:
git revert <commit-hash-of-previous-revert>
Вместо использования git-revert
вы могли бы использовать эту команду в devel
ответвление на выбросить (отменить) неправильный коммит слияния (вместо того, чтобы просто отменить его).
git checkout devel
git reset --hard COMMIT_BEFORE_WRONG_MERGE
Это также соответствующим образом скорректирует содержимое рабочего каталога. Будь осторожен:
- Сохраните изменения В разработке ветви (с неверного слияния), потому что они тоже будут стерты
git-reset
.Все коммиты после того, что вы указываете какgit reset
спор пропадет! - Кроме того, не делайте этого, если ваши изменения уже были получены из других репозиториев, потому что сброс переписывает историю.
Рекомендую изучить git-reset
внимательно просмотрите man-страницу, прежде чем пытаться это сделать.
Теперь после сброса вы можете повторно применить изменения в devel
а потом сделай
git checkout devel
git merge 28s
Это будет настоящее слияние 28s
в devel
как начальный (который сейчас стирается из истории Гита).
Я только что нашел этот пост, когда столкнулся с той же проблемой.Я нахожу выше, что страшно делать сброс настроек и т. д.В конечном итоге я удалю то, что мне не нужно, и не смогу вернуть это.
Вместо этого я проверил коммит, к которому хотел вернуться, например. git checkout 123466t7632723
.Затем преобразован в филиал git checkout my-new-branch
.Затем я удалил ветку, которая мне больше не нужна.Конечно, это сработает только в том случае, если вы сможете выбросить испорченную ветку.
Я бы посоветовал вам выполнить следующие шаги, чтобы отменить возврат, скажем, SHA1.
git checkout develop #go to develop branch
git pull #get the latest from remote/develop branch
git branch users/yourname/revertOfSHA1 #having HEAD referring to develop
git checkout users/yourname/revertOfSHA1 #checkout the newly created branch
git log --oneline --graph --decorate #find the SHA of the revert in the history, say SHA1
git revert SHA1
git push --set-upstream origin users/yourname/revertOfSHA1 #push the changes to remote
Теперь создайте PR для филиала users/yourname/revertOfSHA1
- создайте новую ветку при фиксации до исходного слияния - назовите ее «develop-base»
- выполнить интерактивное перебазирование «разработки» поверх «разработки-базы» (даже если оно уже находится сверху).Во время интерактивного перебазирования у вас будет возможность удалить как фиксацию слияния, так и фиксацию, которая отменила слияние, т.е.удалить оба события из истории git
На этом этапе у вас будет чистая ветка «разработки», в которую вы сможете объединить свою ветку функций, как вы обычно это делаете.