2014-01-18 3 views
2

Предположим, у меня есть репозиторий вроде этого:Как перенести фиксацию через фиксацию слияния?

I --- C --- M master 
    \  /
    `- A -´  topic 

где M является слияние совершить включение topic в master.

Позже я нашел ошибку в C, поэтому я делаю фиксации ее фиксации на master ветви, на вершине M:

I --- C --- M --- C1 master 
    \  /
    `- A -´    topic 

, но в идеале я хотел бы историю, чтобы выглядеть следующим образом:

I --- C --- C1 --- M master 
    \   /
    `- A --------´  topic 

Как я могу переписать историю так, чтобы перед слиянием C1 появился M?

я мог удалить M, применить патч, сделанное C1, и объединить topic в master снова, решить все конфликты снова, но я хотел бы избежать усилий, и я бы предпочел, чтобы сохранить первоначальные фиксации информации (автор, дата и т. д.), если это возможно, что снова отменяет git commit. Я надеюсь, что это возможно с git rebase, но я потерпел неудачу, либо один, либо оба из -p и -i.

ответ

1

Лучший способа я нашел:

git checkout -b tmp master^^ 
# Now tmp is on top of C 

git cherry-pick master 
# Now tmp is on top of C1', a copy of C1 

git rebase -p tmp master 
# Now master is on top of a merge commit from C1' and A 

git branch -d tmp 

Я не знаю, почему git rebase не может сделать это сразу без git cherry-pick, но, по крайней мере, я знаю, что это работает.

+0

Выполнено ли создание слияния, созданное 'git rebase -p' правильно? Как и в случае, правильно ли его родители «C1» и «A»?У меня возникли проблемы при сбрасывании слияний, поскольку изменения слияния получают повторное воспроизведение как нормальное коммитирование, а не слияние. – LopSae

+0

@LopSae: Да, объединение слияния производится поверх C1 'и A. Сохраняющиеся слияния - это точка '-p' (aka' --preserve-merges'), но есть ошибка об использовании '-p' и '-i' вместе упомянуты в' git-rebase (1) '. – musiphil

1

Конец M в вашем третьем графике не совпадает с M во 2-м, поскольку он имеет другую родословную. Поэтому вам нужно сбросить мастер назад до M или использовать rebase для этого.

Сначала фиксированием исправить и затем использовать git rebase -i, чтобы переместить новые совершить, прежде чем М.

Чтобы избежать необходимости повторного разрешения конфликтов, убедитесь, что у вас есть rerere.enabled набора, чтобы получить мерзавец, чтобы помнить резолюции. Вы должны сделать это, прежде чем сначала решите его, чтобы он запомнился. Rerere (повторное использование записанных разрешений) - фантастическая функция.

+0

Спасибо. Можете ли вы объяснить команду 'git rebase -i' более подробно? Я попробовал 'git rebase -i C', и слияние потеряно; Я попробовал 'git rebase -i -p C', а фиксация' C1' была потеряна, хотя я сделал «выбор» в интерактивном режиме. – musiphil

1

Это можно сделать с помощью одной перестановки для перемещения фиксации (или любого количества коммитов), а затем повторного слияния с темой.

# Create some branches just for readability 
git branch mergeCommit master^ 
git branch beforeMerge master^^ 

# Run the rebase 
git rebase --onto beforeMerge mergeCommit master 
# After the rebase master will have the replayed commits on top of C 

# Redo the merge 
git merge topic 

С помощью этой перестановки вы можете перемещать больше, чем один, совершать до слияния. Вы можете прочитать инструкцию перебазироваться в плане английского как:

захватить совершающие от mergeCommit к master и перебазировать их в верхней части beforeMerge.

+0

Да, я вижу, что ветви только для удобочитаемости; вы можете сделать то же самое только с двумя командами: 'git rebase --onto master ^^ master^master', за которым следует' git merge topic'. (Не нужно удалять временные ветви, это дополнительный бонус.) – musiphil

Смежные вопросы