У меня есть существующее хранилище, над которым я работаю, но в последнее время я узнал много нового о хороших практиках и о самом git. Я хотел потрясти свою историю по своему вкусу, особенно некоторые ранние коммиты.

Ниже приведен фрагмент текущей истории. Я хочу перебазировать коммит e5cb9b8 на 1a92e84, чтобы я мог иметь только один / два уровня глубины в графе истории (визуально, изменяя родителя e5cb9b8). Я пробовал перебазировать

git rebase -p --onto 1a92e84 e5cb9b8 master

И вишня в новую ветку, созданную из 9ecbe00. Cherrypicking возвращает мне полную историю, перебазирование завершается с помощью следующего сообщения

ошибка: commit ca230d8c048d22de6f219da8a22e70a773827c38 - это слияние, но опция -m не указана.

фатальный: вишня не удалась

Не удалось выбрать ca230d8c048d22de6f219da8a22e70a773827c38

* | 45a0a21 - (7 weeks ago) #17 Updates README.md - Kamil Pacanek
|/
*   ca230d8 - (8 weeks ago) Merge pull request #2 from KamilPacanek/feat/rmb-support-removing-parts - Kamil Pacanek
|\
| * e5cb9b8 - (8 weeks ago) Adds support for removing parts on ReactorCells - KamilPacanek
* |   1a92e84 - (8 weeks ago) Merge pull request #1 from KamilPacanek/enable-gh-pages - Kamil Pacanek
|\ \
| |/
| * 81761ff - (8 weeks ago) Adds GH Pages support - KamilPacanek
|/
* 9ecbe00 - (8 weeks ago) Initial commit - KamilPacanek

Ожидаемое :

* | 45a0a21' - (7 weeks ago) #17 Updates README.md - Kamil Pacanek
|/
*   ca230d8' - (8 weeks ago) Merge pull request #2 from KamilPacanek/feat/rmb-support-removing-parts - Kamil Pacanek
|\
| * e5cb9b8' - (8 weeks ago) Adds support for removing parts on ReactorCells - KamilPacanek
|/
*    1a92e84 - (8 weeks ago) Merge pull request #1 from KamilPacanek/enable-gh-pages - Kamil Pacanek
|\ 
| |
| * 81761ff - (8 weeks ago) Adds GH Pages support - KamilPacanek
|/
* 9ecbe00 - (8 weeks ago) Initial commit - KamilPacanek

Я искал в StackOverflow аналогичные проблемы, и, похоже, никто не описывал такие модификации так глубоко в истории.

Решение

Хорошо, для будущих читателей и я пишу решение для моей проблемы. @alfunx ответ был ключом к его решению - я нашел объяснение в git rebase другой теме и git rebase --onto и начал экспериментировать с моим хранилищем. Методом проб и ошибок мне удалось * достичь ожидаемого графа истории, выполнив

git rebase -ir --onto 1a92e84 81761ff develop

И замена следующего фрагмента списка задач

label onto

# Branch KamilPacanek/feat/rmb-support-removing-parts
reset onto
pick e5cb9b8 Adds support for removing parts on ReactorCells
label KamilPacanek/feat/rmb-support-removing-parts

# Branch enh/add-uranium-cells
reset 9ecbe00 # Initial commit
merge -C 1a92e84 onto # Merge pull request #1 from KamilPacanek/enable-gh-pages
merge -C ca230d8 KamilPacanek/feat/rmb-support-removing-parts # Merge pull request #2 from KamilPacanek/feat/rmb-support-removing-parts
label branch-point

С последующим (изменил позицию сброса и удалил один, избыточный, фиксация слияния):

label onto

# Branch KamilPacanek/feat/rmb-support-removing-parts
reset onto
pick e5cb9b8 Adds support for removing parts on ReactorCells
label KamilPacanek/feat/rmb-support-removing-parts

# Branch enh/add-uranium-cells
reset onto
merge -C ca230d8 KamilPacanek/feat/rmb-support-removing-parts # Merge pull request #2 from KamilPacanek/feat/rmb-support-removing-parts
label branch-point

* ) На самом деле, было еще многое сделать для достижения этого состояния, но я не хочу запутывать решение второстепенными проблемами. Сначала git rebase не удалось с этим сообщением:

ошибка: отказ от обновления ref с недопустимым именем 'refs / rewritten / Implement-durability-loss.'

подсказка: не удалось выполнить команду todo

подсказка: ярлык орудия-долговечность-потеря.

Как видите, у меня есть точка в конце сообщения о коммите. После того, как я решил это (с помощью другого ребазинга с помощью команды reword), я смог двигаться вперед.

Кроме того, похоже, что git rebase --abort не очищает ссылки, созданные во время git rebase -r .. поэтому у меня был беспорядок в истории. Решил это через rm -rf .git/refs/rewritten. Еще у меня была оставшаяся папка .git / sequencer, которую можно было удалить через git revert --quit.

3
Kamil Pacanek 29 Май 2019 в 16:35

2 ответа

Лучший ответ

База, которую вы выбрали для перебазирования, неверна и должна быть 81761ff вместо e5cb9b8. Я бы предложил вам сделать интерактивную перебазировку и использовать --rebase-merges вместо --preserve-merges. Итак, команда должна быть:

git rebase -ir --onto 1a92e84 81761ff master

Теперь Git, вероятно, создаст еще один коммит слияния. Чтобы избежать этого и получить желаемый результат, вы должны настроить список задач на что-то вроде:

label onto
pick e5cb9b8 Adds support for removing parts on ReactorCells
label new
reset onto
merge -C ca230d8 new
pick 45a0a21 #17 Updates README.md
# Remaining commits...

В списке задач label может использоваться для маркировки текущего коммита (HEAD), а reset может использоваться для установки HEAD для некоторого коммита / метки. merge очевидно используется для создания коммита слияния, -C заставляет слияние использовать то же сообщение коммита, что и исходный коммит слияния.

Это довольно продвинутое и действительно не требуется для большинства пользователей и вариантов использования, поэтому рассмотрите man git-rebase, раздел Перебазировать слияния (или онлайн-версия здесь) для получения более подробной информации. Пример на самом деле очень похож на вашу ситуацию.

2
alfunx 29 Май 2019 в 15:16

Если вы используете git rebase -ir, сделайте это с Git 2.25 (первый квартал 2020 года).

Метка, используемая в списке todo, который генерируется "git rebase --rebase-merges", используется как часть refname; логика создания метки была ужесточена, чтобы избежать имен, которые нельзя использовать как таковые.

См. commit cd55222 (17 ноября 2019 г.) по Мэтью Роджерс (soniqua).
См. commit 867bc1d (17 ноября 2019 г.) от Йоханнес Шинделин (dscho).
(Объединено с Junio C Hamano - gitster - в commit 917d0d6, 05 декабря 2019 г.)

rebase -r: позвольте label создавать более безопасные ярлыки

Подписано: Мэтью Роджерс
Подписано: Йоханнес Шинделин

Команда todo label в интерактивных перебазировках создает временные ссылки в пространстве имен refs/rewritten/. Эти ссылки хранятся как свободные ссылки, то есть как файлы в .git/refs/rewritten/, поэтому они должны соответствовать ограничениям имени файла в текущей файловой системе в дополнение к принятому формату ссылки.

Это создает проблему, в частности, для NTFS / FAT, где, например, двоеточие, двойные кавычки и символы канала запрещены как часть имени файла.

Давайте защитимся от этого, заменив не только символы пробела на тире, но и все не буквенно-цифровые символы.

Однако от этого мы освобождаем не-ASCII символы UTF-8, так как должно быть вполне возможно отразить имена веток, такие как ↯↯↯ в именах ссылок / файлов.


А также:

С Git 2.25 (Q1 2020), логика, позволяющая избежать дублирования имен меток, сгенерированных "git rebase --rebase-merges", забыла, что само устройство использует "onto" в качестве имени метки, чего следует избегать сгенерированным автоматически ярлыки, которые были исправлены.

См. коммит e02058a (18 ноября 2019 г.) автора Доан Тран Конг Данх (congdanhqx-zz).
(Объединено с Junio C Hamano - gitster - в commit 995b1b1, 05 декабря 2019 г.)

sequencer: обрабатывать смещения rebase для сообщения «на»

Подписано: Доан Тран Конг Дан
Автор: Йоханнес Шинделин

Для правильной работы git rebase --rebase-merges необходимо создать начальный список задач с уникальными метками.

Эти уникальные метки обрабатываются путем использования хэш-карты и добавления уникального номера, если обнаружен какой-либо дубликат.

Но мы забываем, что помимо этих меток для боковых ветвей у нас также есть специальная метка onto для нашей так называемой новой базы.

В особом случае, когда любой из этих ярлыков для боковых ветвей с именем `into ', git столкнется с проблемой.

Исправь это.

1
VonC 12 Дек 2019 в 20:14