Как разделить изменения между несколькими ветками в git?

Каков «лучший» (читай: «самый простой», «предпочтительный», «правильный») способ разделить набор изменений между несколькими ветвями в git? Например, предположим, что я сделал набор (незафиксированных) изменений во время работы в ветке X, но некоторые изменения действительно нужно зафиксировать в ветке Y, другие - в ветке Z, а третьи - в ветке W; обычно то, что я делал бы инстинктивно (например, рекомендованный здесь) заключается в том, чтобы сохранить изменения, проверить Y, применить изменения, зафиксировать только то, что имеет отношение к Y, и повторить для других веток. Проблема, с которой я сталкиваюсь, заключается в том, что применение сохраненных изменений часто приводит к конфликтам слияния, которые необходимо обрабатывать, и если я делаю всплывающее окно тайника вместо применения (что случается достаточно часто, чтобы быть реальным риском для меня!), Я В конечном итоге изменения, предназначенные для Z, смешиваются с ветвью Y, и их приходится распутывать вручную.

Есть ли способ лучше? Как лучше мне справиться с этой ситуацией?

Обратите внимание, что мой вопрос связан с такими вопросами, как этот, но отличается тем, что я ищу лучший способ разделить текущий набор изменений между несколькими ветвями. Также обратите внимание, что я не могу переключиться на Y, Z или W до разработки набора изменений; Я должен начать с X и разработать набор изменений на X.


person BlueBomber    schedule 10.07.2013    source источник
comment
Также обратите внимание, что я не могу переключиться на Y, Z или W до разработки набора изменений; Я должен начать с X и разработать набор изменений для X: похоже, что все эти изменения связаны. Если да, то как вы предполагаете зафиксировать их в разных ветвях, если они зависят от изменений, зафиксированных в другой ветке?   -  person Daniel Hilgarth    schedule 10.07.2013
comment
@DanielHilgarth, изменения связаны, но я хочу зафиксировать их в разных ветках, чтобы другие, использующие ветки Y, Z и W, также могли использовать эти улучшения; некоторые изменения логически относятся к веткам Y, Z и W, и люди, желающие этих улучшений, могут объединить их из этих ветвей.   -  person BlueBomber    schedule 10.07.2013
comment
Так почему бы вам не разработать эти изменения непосредственно в соответствующих ветках? Просто пытаюсь понять ваш сценарий здесь ...   -  person Daniel Hilgarth    schedule 10.07.2013
comment
@DanielHilgarth, я должен разрабатывать эти изменения одновременно с изменениями в X, просто из-за характера моего репо. Подумайте об этом так: X - это ветвь функций, а Y - ветка для тестирования функций, а тестирование X требует обновления тестового программного обеспечения в Y, но другие также должны иметь возможность использовать улучшения Y.   -  person BlueBomber    schedule 10.07.2013
comment
Как ветви связаны общими корнями и расходятся? Кстати: я до сих пор не понимаю, почему вы не можете написать улучшения в Y сначала, объединить их в X, а затем разработать новую функцию.   -  person Daniel Hilgarth    schedule 10.07.2013
comment
@DanielHilgarth, мне очень жаль, но я действительно не знаю, как на это ответить. X (и другие ветви) сливаются в изменениях с Y всякий раз, когда есть изменения в Y, но без коммитов слияния X и Y давно разошлись. Что касается вашего BTW, можете ли вы просто работать с предположением, что эти конкретные изменения X и Y необходимо разрабатывать одновременно? К сожалению, я не смогу дать вам полностью точное описание нашего репозитория, ветвей и их взаимосвязей.   -  person BlueBomber    schedule 10.07.2013


Ответы (2)


Проблема с git stash и несколькими ветвями заключается в том, что после того, как они появятся, вам придется снова спрятать их для следующей ветки. Чтобы обойти это, достаточно просто использовать временную ветку.

git checkout -b temp_branch
git commit -a -m 'Changes that will go to several branches.'
git checkout W
git cherry-pick -n temp_branch
(fixup all files here here)
git commit -a -m 'Changes for W.'
git checkout X
git cherry-pick -n temp_branch
(fixup all files here here)
git commit -a -m 'Changes for X.'
git checkout Y
git cherry-pick -n temp_branch
(fixup all files here here)
git commit -a -m 'Changes for Y.'
git checkout Z
git cherry-pick -n temp_branch
(fixup all files here here)
git commit -a -m 'Changes for Z.'
git branch -D temp_branch
person cforbish    schedule 10.07.2013
comment
Мне кажется, что это эквивалентно хранению, затем применению (но не извлечению) тайника для каждой ветки и выборочной фиксации изменений. Я что-то упускаю? - person BlueBomber; 10.07.2013
comment
Эти шаги не помогут вам с конфликтами слияния. Я не думаю, что этого можно избежать, поскольку вы не хотите, чтобы git пытался что-то сделать для вас в этой ситуации. - person cforbish; 10.07.2013

Один из способов избежать проблем слияния - сделать несколько коммитов в исходной ветке, затем выбрать их из целевых веток и, наконец, откатить изменения.

Вот так:

git add -i
git commit -m 'changes for X'
git add -i
git commit -m 'changes for Y'
git log -n 2 # to see hashes
git checkout X
git cherry-pick <hash of the first commit>
git checkout Y
git cherry-pick <hash of the second commit>
git checkout original_branch
git reset --hard HEAD~2
person Dmitry Vyal    schedule 27.08.2013