Git ReBase Интерактивный: Сквош слияния совершает вместе - PullRequest
51 голосов
/ 13 ноября 2009

Я хотел иметь простое решение для объединения двух коммитов слияния во время интерактивной перебазировки.

Мой репозиторий выглядит так:

   X --- Y --------- M1 -------- M2 (my-feature)
  /                 /           /
 /                 /           /
a --- b --- c --- d --- e --- f (stable)

То есть, у меня есть ветвь my-feature, которая недавно была слита дважды, между которыми нет реальных коммитов. Я не просто хочу перебазировать ветку my-feature, поскольку она является отдельной опубликованной веткой, я просто хочу объединить последние два коммита слияния в один (еще не опубликовал эти коммиты)

   X --- Y ---- M (my-feature)
  /            /
 /            /
a --- ... -- f (stable)

Я пытался:

git rebase -p -i M1^

Но я получил:

Refusing to squash a merge: M2

Что я наконец-то сделал:

git checkout my-feature
git reset --soft HEAD^  # remove the last commit (M2) but keep the changes in the index
git commit -m toto      # redo the commit M2, this time it is not a merge commit
git rebase -p -i M1^    # do the rebase and squash the last commit
git diff M2 HEAD        # test the commits are the same

Теперь новый коммит слияния больше не считается коммитом слияния (он оставил только первого родителя). Итак:

git reset --soft HEAD^               # get ready to modify the commit
git stash                            # put away the index
git merge -s ours --no-commit stable # regenerate merge information (the second parent)
git stash apply                      # get the index back with the real merge in it
git commit -a                        # commit your merge
git diff M2 HEAD                     # test that you have the same commit again

Но это может осложниться, если у меня много коммитов, у вас есть лучшее решение? Спасибо.

Милдред

Ответы [ 4 ]

48 голосов
/ 09 ноября 2010

Это старая тема, но я просто наткнулся на нее, когда искал похожую информацию.

Уловка, подобная описанной в Слияние осьминогов с поддеревом - действительно хорошее решение проблемы такого типа:

git checkout my-feature
git reset --soft Y
git rev-parse f > .git/MERGE_HEAD
git commit

Это возьмет индекс в том виде, в каком он существует на кончике my-feature, и использует его для создания нового коммита из Y с 'f' в качестве второго родителя. Результат такой же, как если бы вы никогда не выполняли M1, но сразу приступили к выполнению M2.

8 голосов
/ 13 ноября 2009

если вы не опубликовали последние два коммита слияния, вы можете выполнить сброс и простое слияние.

git reset --hard Y
git merge stable
5 голосов
/ 05 июля 2013

Я пришел к этой теме, желая раздавить один коммит слияния; поэтому мой ответ не так полезен для первоначального вопроса.

               X
                \   
                 \  
a --- b --- c --- M1 (subtree merge)

Я хотел перебазировать слияние M1 и раздавить все как один коммит поверх b.

a --- b --- S (include the changes from c, X and M1)

Я пробовал все виды различных комбинаций, но вот что сработало:

git checkout -b rebase b (checkout a working branch at point b)
git merge --squash M1

Это будет применять изменения в индексе, где они могут быть зафиксированы git commit

0 голосов
/ 09 марта 2012

Ни один из упомянутых методов не работает для меня с последней версией git. В моем случае следующее сделали:

git reset --soft Y
git reset --hard $(git commit-tree $(git write-tree) -p HEAD -p stable < commit_msg)

Однако сначала вам нужно будет записать сообщение коммита в файл commit_msg.

...