Слияния коммитов не отображаются в git rebase --interactive

git log показывает следующее:

commit 1abcd[...]
Author: [...]
Date: [...]

    [Useful commit]

commit 2abcd[...]
Author: [...]
Date: [...]

    Merge branch [...] of [etc. etc.]

commit 3abcd[...]
Author: [...]
Date: [...]

    [Useful commit]

Это объединение бесполезно для меня - оно не представляет значимого состояния ветки и генерируется из удаленного пула, поэтому у меня есть реальные ошибки удаленной истории - нет необходимости в фиксации, чтобы отметить факт что я потянул. Я хотел бы выкачать это слияние. Моя обычная техника для сквоша:

git rebase --interactive HEAD~2 (или еще далеко назад мне нужно идти)

И затем я бы раздавил его в соседний коммит. Я делаю это несколько раз, если, например, я делаю фиксацию, понимаю, что я пропустил крошечную важную деталь (один файл или не изменил строку в одном из файлов), и сделайте еще одно коммитирование, которое в основном просто быстро. Таким образом, когда я подталкиваю свои изменения обратно к пульту дистанционного управления, все хорошо и чисто, и говорит сплоченный рассказ.

Однако в этом случае, когда я запускаю команду git rebase ..., commit 2abcd не появляется! Похоже, что он пропущен над 2abcd и вместо этого отображает 1abcd и 3abcd. Есть ли что-то особенное в фиксации слияния, которое мешает ему появляться в git rebase --interactive? Какую еще технику я мог бы использовать для сквоша этого коммита?

ОБНОВЛЕНИЕ за запрос @Cupcake:

Вывод git log --graph --oneline --decorate выглядит следующим образом:

* 1abcd (useful commit)
* 2abcd (merge)
|  \ <-- from remote
|   * 3abcd (useful commit)
|   |

Полезно?

Ответ 1

Rebase обычно не сохраняет комманды слияния без --preserve-merges

Хорошо, поэтому я не совсем уверен, что произойдет, если вы попытаетесь раздавить слияние с использованием интерактивной rebase с помощью --preserve-merges... но это то, как я удалю фиксацию слияния в вашем случае и сделаю ваш история линейная:

  • Восстановите все до того, как слияние будет выполнено поверх удаленной ветки.

  • Черри-выбор или перебазирование всего после того, как слияние будет выполнено поверх ранее перезаписанных коммитов.

Если у вас есть только 1 фиксация после фиксации слияния

Итак, с точки зрения команд, это выглядело бы примерно так:

# Reset to commit before merge commit
git reset --hard <merge>^

# Rebase onto the remote branch
git rebase <remote>/<branch>

# Cherry-pick the last commit
git cherry-pick 1abcd 

Если у вас более 1 фиксации после фиксации слияния

# Leave a temporary branch at your current commit
git branch temp

# Reset to commit before merge commit
git reset --hard <merge>^

# Rebase onto the remote branch
git rebase <remote>/<branch>

# Cherry-pick the last commits using a commit range.
# The start of the range is exclusive (not included)
git cherry-pick <merge>..temp

# Alternatively to the cherry-pick above, you can instead rebase everything
# from the merge commit to the tip of the temp branch onto the other
# newly rebased commits.
#
# You can also use --preserve-merges to preserve merge commits following
# the first merge commit that you want to get rid of...but if there were
# any conflicts in those merge commits, you'll need to re-resolve them again.
git rebase --preserve-merges --onto <currentBranch> <merge> temp

# These next steps are only necessary if you did the rebase above,
# instead of using the cherry-pick range.
#
# Fast-forward your previous branch and delete temp
git checkout <previousBranch>
git merge temp
git branch -d temp

Документация