История сквоша Git после слияния

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

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


person E-rich    schedule 26.12.2012    source источник


Ответы (4)


Мне удалось раздавить несколько коммитов после нескольких слияний из основной ветки, используя стратегию, найденную здесь: https://stackoverflow.com/a/17141512/1388104

git checkout my-branch            # The branch you want to squash
git branch -m my-branch-old       # Change the name to something old
git checkout master               # Checkout the master branch
git checkout -b my-branch         # Create a new branch
git merge --squash my-branch-old  # Get all the changes from your old branch
git commit                        # Create one new commit

Вам придется принудительно обновить, если вам нужно отправить свою сжатую ветку в удаленный репозиторий, в который вы ранее отправили, например. git push origin my-branch -f

person Aaron Swan    schedule 03.10.2018

Решение, которое я использовал, заключалось в том, чтобы вручную воссоздать историю. Я сделал это главным образом потому, что не хотел тратить слишком много времени на поиск элегантного решения, а истории было не так много (около 30 коммитов, которые мне пришлось бы объединять вручную).

Итак, я создал ветку перед тем, как объединить огромный апстрим:

git checkout -b remove-history-fix <commit ID before merge>

Затем повторно объединил восходящий поток, используя параметр --squash.

git merge --squash <upstream tag>

Затем вручную отбирали коммиты после слияния из старой ветки (той, у которой огромное количество восходящей истории).

git cherry-pick <commit ID>

После того, как все эти коммиты были объединены в мою ветку remove-history-fix, я удалил ветку с исходной историей.

git branch -D <upstream-history-branch>
person E-rich    schedule 28.12.2012
comment
Примите ваш ответ тогда. :) - person sjas; 28.12.2012
comment
просто хотел добавить, что после многих попыток сам этот процесс (или варианты копирования-вставки этого процесса) также является единственным способом, который я мог найти, чтобы раздавить материал, который больше не находится на кончиках ветвей после того, как коммиты слияния заполняют временную шкалу ветки . Такие слияния необходимы для филиалов, которым требуется много времени для PR (с другой стороны, сквош — небольшая роскошь). Просто добавьте свои задачи rebase -i перед любым предварительным слиянием, и это избавит вас от беспокойства позже. - person leRobot; 08.05.2015
comment
Стоит отметить, что, выполняя сквош-слияние, вы не записываете фактическое слияние, что может привести к тому, что ваши восходящие коммиты останутся потерянными (например, если вы сквэш-слияете ветку исправлений, а затем удаляете вышестоящую ветку исправлений без тега). - person void.pointer; 26.08.2019

Пара вариантов для вас:

Ограничить ведение журнала

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

В этом случае вы бы сделали обычное слияние, но при регистрации добавили бы --first-parent к команде.

Например, без опции, которую я мог бы иметь (предположим, что «больше образцов» от 1 до 3 на самом деле было намного больше коммитов)

$ git log --oneline
0e151bf Merge remote-tracking branch 'origin/master' into nosquash
f578cbb sample more 3
7bc88cf sample more 2
682b412 sample more 1
fc6e1b3 Merge remote-tracking branch 'origin/master'
29ed293 More stuff
9577f30 my local change
018cb03 Another commit
a5166b1 Initial

Но, если я добавлю --first-parent, это приведет к следующему:

$ git log --oneline --first-parent
0e151bf Merge remote-tracking branch 'origin/master'
fc6e1b3 Merge remote-tracking branch 'origin/master'
9577f30 my local change
018cb03 Another commit
a5166b1 Initial

Обратите внимание, что все коммиты от мастера после того, как я разветвился («мое локальное изменение» является моей расходящейся фиксацией), исчезли. Отображаются только те коммиты, которые я сделал, в том числе при слиянии. Если бы я использовал более качественные сообщения коммитов во время слияния, я мог бы даже знать, что это была за партия изменений.

Заменить историю

Это для того, что вы спросили.

Черпая вдохновение из https://git-scm.com/book/en/v2/Git-Tools-Replace

Что мы будем делать здесь, так это сжимать историю удаленного устройства, заменять его историю нашей сжатой версией с нашей точки зрения и объединять сжатую версию.

В моем примере репозитория ревизии, добавленные восходящим потоком, которые я еще не объединил, были 682b412 "sample more 1" to origin/master (f578cbb "sample more 3") (хотя для этого примера это не так уж долго, представьте, что есть 50 коммитов). или что-то среднее).

Первое, что я хочу, это локальная ветка удаленной стороны:

git checkout -b squashing origin/master

Далее я хочу быстро раздавить его

git reset --soft 682b412~
git commit -m "Squashed upstream"

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

На данный момент исходная/главная и сжимающая ветки имеют идентичное содержимое дерева, но разные истории.

Теперь мы говорим git, что, когда он увидит ссылки на исходный коммит origin/master, вместо этого использовать наш сжатый коммит. Используя git log, я вижу, что новый коммит «Squashed upstream» — 1f0bc14, поэтому мы делаем:

git replace f578cbb 1f0bc14

С этого момента ваш git будет использовать коммит «squashed upstream».

Вернемся к нашей исходной ветке (если она была "master")

git checkout master
git merge f578cbb

Похоже, что это объединяет мастер-источник (f578cbb), фактически получает содержимое 1f0bc14, но регистрирует его как родительский SHA1 f578cbb.

Нам больше не нужна раздавливающая ветка, так что можете от нее избавиться.

Теперь предположим, что апстрим добавил больше возможностей. В этом простом примере в репозитории основной ветки журнал может показать следующее:

84f5044 new feature
f578cbb sample more 3
7bc88cf sample more 2
682b412 sample more 1
29ed293 More stuff
018cb03 Another commit
a5166b1 Initia

Однако после того, как мы получим восходящий поток, если мы посмотрим на его журнал из нашего репо, вместо этого мы увидим это:

84f5044 new feature
f578cbb squashed upstream
29ed293 More stuff
018cb03 Another commit
a5166b1 Initial

Обратите внимание, как нам кажется, что история также сжата, и, что более важно, сжатый SHA1 восходящего потока показывает тот, который использовался в истории восходящего потока (для них это действительно коммит «sample more 3»).

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

git merge origin/master

Но у нас нет такого захламленного лога:

4a9b5b7 Merge remote-tracking branch 'origin/master' for new feature
46843b5 Merge remote-tracking branch 'origin/master'
84f5044 new feature
f578cbb squashed upstream
fc6e1b3 Merge remote-tracking branch 'origin/master'
29ed293 More stuff
9577f30 my local change
018cb03 Another commit
a5166b1 Initial

Если бы коммит «новой функции» в восходящем потоке был таким же большим количеством коммитов, мы могли бы повторить этот процесс, чтобы также уменьшить его.

person John O'M.    schedule 28.06.2015

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

Вам придется жить с большой историей.

person Femaref    schedule 26.12.2012
comment
Никак нельзя заставить? Мне никогда не нужно будет отталкиваться, и любое слияние в будущем я смогу сделать так же, как и раньше. - person E-rich; 26.12.2012
comment
Как вы объединили его на этот раз? Каково происхождение этого репозитория? - person Femaref; 26.12.2012
comment
Происхождение было с нуля. Для начала мне дали tar-файл с исходниками, вероятно, из тега, затем я внес свои изменения/дополнения, а затем захотел объединить обновления/исправления из официального репозитория основной ветки разработки. Слияние потребовало приличного количества ручных слияний, что меня вполне устраивает, поскольку я не буду делать это часто. - person E-rich; 26.12.2012
comment
Не могли бы вы обновить вопрос с помощью команд, которые вы использовали для слияния из восходящего потока? - person Femaref; 26.12.2012