Раздавливание первых нескольких десятков коммитов git, содержащих коммиты слияния

У меня есть существующий репозиторий с корнем R, затем несколько десятков коммитов, включая множественные слияния, до X, а затем линейная история до Y. Я хотел бы объединить все от R до X в один коммит и принудительно нажать его. Как я могу сделать это без особых усилий, связанных с повторным разрешением слияний?

В качестве альтернативы эту проблему можно сформулировать как изменение корневого коммита с R на X и отсечение графика перед X.

Вот иллюстрация, упрощающая граф фиксации:

R           ---- I want to squash from here...
|
A
|\
B C
| |
D E
| |\
F G H
| |/
I J
|\ \
K L M
|/  |
N  /
|/
O 
|
X           ---- to here.
|
P
|
Q
|
Y

Сокращение всего с помощью обычной перебазировки потребует повторного разрешения нескольких коммитов слияния. Я знаю о git rerere, но не знаю, как его использовать в этой ситуации. Он не был включен при совершении всего этого.

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
0
56
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Это можно сделать с помощью перебазирования, но гораздо проще сделать вручную.

git checkout --orphan temp X
# now you are on a brand new branch with no history, and your working tree is just like X
git commit -m "Single shot"
# now let's carry over X up to Y
git cherry-pick X..Y

Если вам нравится результат, установите свою ветку здесь и живите долго и счастливо.

Почему бы просто не поставить reset --soft X и не повторить? Не могу поверить, что спрашиваю это у самого «мистера Reset Soft» :-D (и это настоящий вопрос, интересно, есть ли разница, которую я упускаю)

Romain Valeri 15.02.2023 11:09

@RomainValeri Разве это не раздавит не ту половину коммитов? Обратите внимание, что представленный график «перевернут» (по сравнению с тем, что показал бы git log --graph).

j6t 15.02.2023 11:10

Если я этого не сделал, значит, у @RomainValeri есть причина :-) График перевернут. Корень — R, а кончик — Y. Как дела?

eftshift0 15.02.2023 11:15

@eftshift0 Это то, чего мне не хватало. Д'о. Направление диаграммы. Извините за шум.... ^^

Romain Valeri 15.02.2023 11:23

Замечательная идея. Однако, похоже, это не работает как есть: option orphan requires a value и -b, -B and --orphan are mutually exclusive. Тем не менее, я поэкспериментирую с этой идеей.

Xilexio 15.02.2023 13:21

Виноват. Попробуйте без -b.

eftshift0 15.02.2023 13:23

Все еще не работает, потому что --orphan требует значения — вероятно, оно должно идти сразу после checkout. Обновлено: git checkout --orphan X temp работает!

Xilexio 15.02.2023 13:31

По какой-то причине я получаю конфликты (конфликт слияния, изменение/удаление, переименование/переименование) при выборе вишни X..Y из осиротевшей ветки, которая начинается с X. Есть идеи, где я накосячил? Должно было быть (X+1)..Y?

Xilexio 15.02.2023 13:35

Нет... потому что X будет отброшен, это должно быть X..Y. Вы уверены, что это прямая линия от X до Y?

eftshift0 15.02.2023 13:59

В чем проблема с конфликтами?

eftshift0 17.02.2023 11:43

Работает! Большое спасибо. Ранее конфликты, вероятно, были вызваны некоторым оставшимся мусором при экспериментировании со старым репо, таким как ветка с тем же именем, что и хэш коммита, но на свежем клоне все работает правильно.

Xilexio 17.02.2023 11:44

Предисловие: я не фанат сквоша и вообще не советую этого делать. Могут быть ситуации, когда вы хотите сделать это по уважительной причине (например, отмена ужасных слияний параллельных зеркальных ветвей, которые производят некоторые графические инструменты / интерфейсы (например, Visual Studio)), но, пожалуйста, действительно убедитесь, что вы не раздавливаете коммиты как дезодорант, чтобы скрыть за плохую гигиену контроля версий вместо правильного использования и фильтрации временных коммитов.


Тем не менее, вот как сделать то, что просят, полностью бесконфликтно:

git status              # Make sure you start with no untracked files.
git branch new_branch1 commit_R
git branch new_branch2 commit_Y
git switch new_branch1
git diff HEAD commit_X | git apply - # This makes the worktree identical to X, in
                                     # effect "fast-forward merge" of R..X
git add .
git commit -m "Some message describing the R..X changes"
git rebase --onto new_branch1 commit_X new_branch2
git branch --delete new_branch1
# Now you're done, new_branch2 is now R'--X'--P'--Q'--Y'


# If you want to (forcibly) change the original branch that pointed to Y do the
# following:
git switch the_original_branch
git reset --hard new_branch2
git branch --delete new_branch2

Поскольку new_branch1 и commit_X имеют одинаковый контент (сама цель команд diff...apply) при выполнении команды rebase, конфликтов не будет, потому что применение P..Y поверх любой из них абсолютно одинаково.

Спасибо за помощь и новый взгляд на проблему! Я понимаю общую идею этих команд, особенно трюк diff | apply, но это решение не работает, потому что в репо есть некоторые нетекстовые активы: error: cannot apply binary patch to '(...).png' without full index line и error: (...).png: patch does not apply. Возможно, для его работы требуется дополнительная настройка. Другой ответ обходит это, создавая осиротевшую ветку, хотя я не знаю, сработает ли ваш ответ с ней вместо трюка diff | apply.

Xilexio 17.02.2023 11:53

Ах, бинарные файлы. Да, они не будут созданы с помощью apply. Чтобы включить такие файлы, выберите коммит(ы), который вводит эти файлы (или последний коммит для изменения файлов) прямо перед выполнением diff | apply. Возможно, выборки будут включать и текстовые файлы, но это не имеет значения (если это создает конфликты, вы можете выбрать простой выход и просто удалить их). Затем выполните diff | apply, как описано. Затем вы получите промежуточные коммиты «добавить изображение», которые затем можно уменьшить до R'--I1--I2--I3--X'--P'--Q'--Y' с помощью интерактивной перебазировки.

hlovdal 17.02.2023 12:23

Другие вопросы по теме