GIT: как объединить изменения, которые ранее были удалены из объединенного коммита - PullRequest
0 голосов
/ 30 августа 2018

У меня две ветви, развивайся и осваивай. Я хотел выбрать несколько коммитов, касающихся одной конкретной функции, от разработки до мастера. Но число коммитов, которые вишня может выбрать от разработчика к мастеру, составило около 106, это означает, что мне пришлось пройти через все из них, чтобы отфильтровать соответствующие. Чтобы избежать необходимости проходить изменения каждого коммита, а затем выбирать отдельные или целый ряд изменений, я подумал о том, чтобы сократить путь: D. Я слил развитие в мастер, в коммите слияния было около 115 изменений файла.

Я просмотрел каждый файл и удалил те изменения, которые не имели отношения к этой функции. В случае некоторых файлов я удалил их полностью, а для некоторых я принял только частичные изменения и удалил ненужные изменения. После прохождения всех 115 из них осталось около 55 отфильтрованных файлов, относящихся к функции, которую я затем зафиксировал в коммите слияния.

Теперь, когда я смотрю на git log master, log выглядит так, как будто все 106 коммитов были объединены в master, а сверху появляется мой коммит merge под названием 'merged development to master'. Теперь я хочу объединить развитие в мастер, чтобы фактически объединить оставшиеся файлы, которые я удалил ранее, из коммита слияния, git говорит, что объединять нечего, хотя в обеих ветвях есть изменения, но из-за того, что я удалил их из коммит слияния Я не могу перенести эти изменения в мастер сейчас. Нужно ли удалять коммит слияния из мастера или есть ли способ принудительно полностью слить различия? каким должен быть правильный метод, чтобы избежать каких-либо проблем в будущем?

Ответы [ 2 ]

0 голосов
/ 31 августа 2018

К сожалению, ваш ярлык неправильно использовал «слияние». Когда вы пытаетесь объединить две ветви, получить конфликты, разрешить их вручную, а затем зафиксировать объединение, вы говорите 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.

0 голосов
/ 30 августа 2018

я думаю, что вам нужно сделать следующее: добавить небольшое изменение в ветку разработки (пусть это будет дополнительный пробел), а затем переключиться на мастер Git Merge Develop добавит изменения, включая ранее удаленные изменения. тогда мерзавец толчок На мой взгляд, чтобы избежать проблем в будущем, каждая функция должна быть на ветке, и после ее завершения она будет объединена с master

.
...