К сожалению, ваш ярлык неправильно использовал «слияние». Когда вы пытаетесь объединить две ветви, получить конфликты, разрешить их вручную, а затем зафиксировать объединение, вы говорите Git, что «правильный» способ объединения этих двух ветвей (и все коммиты, сделанные на этих ветвях две ветви) - это способ , который вы выбрали для ручного разрешения фиксации. Если вы «заново слились» из develop
, Git не отменит ваше ручное разрешение конфликтов, потому что вы уже сказали Git, что такое правильное слияние, и не будет пытаться противоречить вам (ну, если оно действительно не получится) смущенный). Git не может определить разницу между внесенными вами изменениями, необходимыми для разрешения двух слияний, и изменениями, которые вы хотели «сохранить на потом».
Вам придется сбросить неудачное слияние, но вот как вы можете сделать это относительно автоматически и без особых хлопот. Вы упомянули, что у вас был еще один коммит на master
после слияния. Если этого вообще не было, вы могли бы пропустить несколько шагов, но ниже я дал более общее решение, которое также сработало бы, если бы вы добавили дополнительные коммиты как на master
, так и на develop
.
Я предполагаю следующее.
- Когда вы совершили «плохое слияние», вы слились
develop
в master
(то есть вы были на master
и набрали git merge develop
, а не наоборот).
- Вам не слишком важно, как история выглядит в данный момент, вы просто хотите получить "потерянные" изменения от
develop
до "плохого слияния" (плюс дополнительные изменения с тех пор, если вы кто-нибудь) успешно слился в master
.
- Вы нигде не публиковали
master
или develop
, поэтому другие репозитории не полагаются на их историю.
- В настоящее время вы получили
master
в чистом дереве.
Как и в случае с любой грязной манипуляцией с Git, неплохо сделать полную резервную копию (cp -a
или git clone mirror
) вашего хранилища здесь.
Во-первых, давайте назовем плохое слияние. Найдите его хэш в своем журнале и создайте для него тег. (В вашем случае это master^
, но в более общем случае вам, возможно, придется его искать.)
git tag bad_merge 8354cbeb
git log bad_merge # !! double check that this points to the bad merge !!
Теперь мы собираемся проверить новую ветку fix_merge
. Мы начнем это в bad_merge
:
git checkout -b fix_merge bad_merge
Затем мы вернем ветвь обратно в состояние master
как раз перед «плохим слиянием», но оставим рабочий каталог без изменений (чтобы он содержал ваши ручные изменения для добавления первой функции в * 1050). *):
git reset HEAD^
и мы повторим ручное редактирование:
git add -A
git commit -m 'fix_merge: add first feature to master'
Теперь мы собираемся сделать несколько сложную ребазу. (Этот шаг будет ненужным, если у вас не было коммитов на master
с момента неудачного слияния.)
git checkout master
git branch master_backup # make a copy in case something goes wrong
git rebase --onto fix_merge bad_merge master
Это трансплантирует изменения, сделанные в ветке master
, начиная с после , когда плохое объединяется с текущим состоянием (т. Е. Часть дерева после bad_merge
до master
) ONTO наш отремонтированный филиал fix_merge
. После перебазировки master
будет указывать на пересаженную ветвь. Не должно быть конфликтов, потому что деревья в bad_merge
и fix_merge
точно совпадают; это просто история коммитов, которая переписывается, потому что у одного есть слияние, а у другого нет.
Теперь у нас следующая ситуация:
История master
, вместо слияния с develop
, теперь имеет один коммит для ручных правок, которые вы сделали, чтобы добавить первую функцию, плюс дополнительная работа, которую вы проделали master
с момента неудачного слияния. Чего не хватает, так это истории (ужасно) слияния с develop
.
Ветвь develop
теперь имеет (сложную) историю этой первой функции, плюс функции, которые вы разработали до неудачного слияния, но хотели «сохранить на потом», плюс дополнительную работу, которую вы проделали с тех пор ( что у вас нет в вашем случае, но это решение будет работать и для тех).
Это более или менее в том случае, если бы вы выбрали вишню первую функцию из develop
, за исключением того, что все вишни были выбраны за один коммит вместо нескольких коммитов. Теперь, если вы объедините develop
в master
:
git checkout master # probably already there, but make sure
git merge develop
и разрешать любые конфликты - и их может быть немало, поскольку Git пытается сопоставить все отдельные коммиты для первой функции в ветви develop
с большим монолитным коммитом в master
, так что это потенциально уродливое слияние - тогда вы можете совершить слияние:
git commit
и, наконец, master
должно быть успешно объединено со всеми изменениями с develop
как до, так и после неудачной фиксации.
На данный момент, вы, вероятно, захотите рассмотреть возможность слияния master
обратно в develop
или отказаться от develop
полностью и перенести его из master
.