2016-03-24 3 views
2

У меня возникла проблема между моими ветвями git, и я не уверен, как подойти. Допустим, у меня есть отдельные ветви для каждого выпуска, над которым я работаю. Например, у меня есть «Release-1» и «Release-2» в качестве моих ветвей. Эти выпуски являются последовательными по своей природе, то есть «Release-2» содержит все в «Release-1», но не наоборот. В моем случае я случайно слил «Release-2» в «Release-1» и толкал его, не осознавая свою ошибку. Один я понял, что ошибся, я пошел и выпустил:Фиксация «назад» git merge, которая была нажата

git revert -m 1 <sha-of-bad-merge-commit> 

Это, казалось, исправить все; ни один из кода «Release-2» не был в «Release-1», и все оказалось правильным. Я подтолкнул это к моему восходящему потоку, думая, что это было разрешено. Ускорьте вперед. Я применил исправление ошибки в ветке «Release-1». Теперь я хочу объединить «Release-1» в «Release-2», но я столкнулся с конфликтами. Гит думает, что изменения, сделанные в результате возврата из ранее, должны быть объединены в «Release-2». По сути, git хочет удалить изменения из «Release-2», которые случайно попали в «Release-1» из «Release-2», когда я пытаюсь объединиться.

Я пробовал исследовать решение и не нашел его. Самое близкое, что я нашел, применительно к слиянию слишком рано, возвращаясь, а затем снова пытаюсь объединиться. Решение состояло в том, чтобы вернуть реверс и снова выполнить слияние. Я не думаю, что это будет работать в этом случае, потому что это приведет к повторному внесению изменений в «Release-1», которые не предназначены для «Release-1».

Если вы не просмотрите каждый затронутый файл по очереди, чтобы выбрать правильный набор изменений, есть ли хороший подход, основанный на «git-based»? Я не хочу просто принимать изменения из ветки «Release-2», где есть конфликты, поскольку некоторые из них могут быть законными. Кроме того, я рассматривал просто слияние в ветке исправления ошибок с «Release-2», но тогда проблема, скорее всего, снова появится в будущем. Я бы хотел предотвратить это.

Вот грубый рисунок ситуации:

(Release-2) ---A----B----C---x---x---------*D* 
          \    /
(Release-1) ---x----Y------M---x---^M----Z 

Пусть A, B и C являются нормальными фиксаций, что я хочу для 'Release-2'. Наконечник «Release-1» - Y и содержит только «Release-1». Commit 'M' - это случай, когда я случайно объединяю фиксацию «C» и фиксирую «Y» в ветке «Release-1». В какой-то момент я замечаю свою ошибку и возвращаю слияние (commit '^ M'). В Commit 'Z' есть мое исправление. На этом этапе я хочу объединить «Release-1» обратно в «Release-2». Я делаю это и заканчиваю на «D.» Здесь у меня есть моя проблема. По сути, мое слияние в «D» говорит, что он хочет удалить все изменения, сделанные в «A», «B» и «C», которые мне не нужны. Другие файлы отображаются как конфликты из-за возврата слияния. Например, некоторые файлы, которые я хочу в «Release-2», были удалены в «Release-1», когда я сделал возврат. Теперь, в 'D', git говорит мне, что существует конфликт слияния, потому что одна ветвь удалила файл, а другая модифицировала файл.

Если у кого-то есть предложения, я был бы очень признателен за их слушание. Благодаря!

ответ

3

(я буду ссылаться на ваш ^M совершить, как Mrevert, так как ^ персонаж имеет особое значение в некоторых из команд, которые следуют.)

ли git merge --abort отказаться от вашей попытки создать совершить D.

Поскольку у вас есть ряд фиксаций x--Mrevert--Z, и вы должны тянуть в x и Z «s изменения, но не Mrevert» s, вам нужен трехступенчатый процесс:

  1. Используйте git merge Mrevert^ тянуть во всех изменениях до Mrevert. (Синтаксис c^ означает «родительский элемент фиксации c».)
  2. Использовать git merge -s ours Mrevert, чтобы сообщить git, что изменения от окончательной фиксации уже находятся в вашей ветке. -s ours означает сохранить нашу (то есть версию-2) версию дерева, не беспокоясь о каком-либо реальном «слиянии».
  3. Используйте git merge Z, чтобы сменить сменить текст с Z.

Это будет производить коммит график, как:

(Release-2) ---A----B----C---x---x---M1-----M2------M3 
          \  / / /
(Release-1) ---x----Y------M-------x---Mrevert----Z 

Если вы git diff M1 M2, вы увидите, что M2 не тянет каких-либо изменений в Release-2.

+1

Это * в основном * справа и будет * полностью * правильным, если бы только то, что зафиксировано «x» между «M» и «^ M», не было. Я думаю, что способ сделать это состоит в том, чтобы сделать * три * слияния вместо двух: один для слияния в commit 'x', один с' -s ours' для слияния '^ M', а последний для объединения в commit' Z '. – torek

+0

@Matt Спасибо! Это решение работало, как ожидалось. Причина, по которой я использовал символ «^» с обращением «М», заключалась в том, что я следовал тому же изображению, что и те, что были здесь: https://git-scm.com/blog/2010/03/02/ undoing-merges.html –

+0

@torek Я не заметил никаких проблем в фиксации «x», когда я следил за инструкциями Мэтта. Я думаю, что это происходит потому, что revert commit не влияет на «x» вообще, поэтому он все равно сливается, как ожидается позже. Были некоторые коммиты в «М», которые я * * хотел в «Release-1.0», которые были возвращены в «^ M», поэтому мне пришлось выполнить дополнительную работу (выбор вишни после фиксации после возврата) получить эти изменения на Z. –