Git: Как "отменить" слияние

Ситуация: Начиная с Мастера в A, я разветвлялся и делал некоторые изменения на B, а затем объединил эту ветку в (C). После внесения некоторых изменений я был в D, но обнаружил, что мне нужно развернуть код без изменений, произошедших в ветке. Если бы я объединил его, это было бы хорошо.

A_______C___D
 \     /
  \_B_/

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

Во-вторых...

У меня не было времени для разработки наилучшего метода для решения этой проблемы, поэтому я удалил файлы, добавленные филиалом, и вручную отменил несколько изменений, сделанных в ветке, затем выполнил результат для развертывания (F)

A_______C___D___F
 \     /
  \_B_/

Я хочу иметь возможность продолжать развивать ветку и объединять любые изменения от мастера в нее, чтобы поддерживать ее в актуальном состоянии, но если я это сделаю, то материал, который я сделал для создания F, будет объединен и вызовет файлы, которые нужно удалить, и изменения, которые необходимо удалить. Каков наилучший способ справиться с этим?

Ответы

Ответ 1

Вы можете использовать rebase для этого в один шаг:

git rebase --onto A C D

Я только что проверил это, с соответствующими результатами:

$ edit test.txt
$ git add .
$ git commit -mA
$ git checkout -b the_branch
$ edit test.txt
$ git commit -a -mB
$ git checkout master
$ git merge master the_branch --no-ff
$ edit test.txt
$ git commit -a -mD

Отсюда вы описываете ситуацию. Тогда:

$ git rebase --onto <SHA1-for-A> <SHA1-for-C> master

rebases фиксируется от C (исключается) для управления на A. Мне нужно было исправить некоторые конфликты, так как я изменил их в тех же местах в B и D, но я думаю, что вы этого не сделаете.

   _D'
  /
 /
A_______C___D
 \     /
  \_B_/

Док о git rebase --onto, который более или менее соответствует вашей ситуации: http://git-scm.com/docs/git-rebase


Если у вас есть:

A_______C___D___F
 \     /
  \_B_/

то у вас есть:

   _D'___F'_(master)
  /
 /
A_______C___D___F
 \     /
  \_B_/(the_branch)

Отсюда слияние изменений в мастер в ветку легко. Отмените commit F' вообще.

$ git checkout master # if you were not here already
$ git branch old_fix  # if you want to be able to return to F' later
$ git reset --hard <SHA1-to-D'>

После приведенных выше команд:

     (master)
    /
   _D'___F'_(old_fix)
  /
 /
A_______C___D___F
 \     /
  \_B_/(the_branch)

Чтобы объединить обновления мастера в the_branch:

$ git checkout the_branch
$ git merge master

... и исправить конфликты.

Ответ 2

Очевидное решение - от reset до A, повторное использование всех патчей вручную и разрешение конфликтов (которых у вас не будет).

В качестве альтернативы вы можете просто git revert patch B, но это создаст новую фиксацию.

Хотя ответ Готье лучше.