Нет встроенного способа сделать это.
Как nologin эффективно отметил в комментарии , если вы достигнете желаемого набора коммитов, у вас будет new история, несовместимая с оригинальной историей.Если все в порядке, есть процесс - не встроенный, но не чрезвычайно трудный - с помощью которого вы можете достичь желаемого набора коммитов.Однако сначала убедитесь, что вы хотите.
Вы описываете коммиты как линейные, и они могут на самом деле быть линейными, но это не так.Они будут линейными в некоторых областях.Но коммиты образуют направленный ациклический граф или DAG.Этот график является историей в хранилище.В тех частях, где он линейный, он довольно прост:
... <-F <-G <-H <-- master
Здесь имя ветви master
идентифицирует или указывает на , фиксирует H
.Точнее, имя master
хранит хэш-идентификатор commit H
.Коммит H
, тем временем, сохраняет хэш-идентификатор родительского коммита H
G
, в котором хранится хэш-идентификатор его родительского F
и т. Д.Начиная с конца и работая в обратном направлении, git log
показывает вам эти коммиты, а является историей.
Однако некоторые коммиты являются merge коммитами.Такой коммит имеет двух (или более, но обычно только двух) родителей.Мы можем нарисовать их следующим образом:
I--J
/ \
...--H M <-- dev
\ /
K--L
Здесь имя ветви dev
указывает на фиксацию M
, но M
указывает на оба J
и L
.J
указывает на I
;L
указывает на K
;и I
и K
оба указывают на коммит, из которого сформировались две дочерние ветви внутри ветви, а именно на коммит H
(на который предположительно указывает имя master
: коммиты H
и более ранние включены и master
и dev
).
Если коммиты I
, L
и M
все сделаны автором BBBB, ноJ
и K
принадлежат автору AAAA, что вы собираетесь здесь делать?Если вы сохраняете M
(BBBB) и сохраняете J
, потому что он принадлежит другому автору AAAA, вы также должны оставить L
, даже если это BBBB.Однако, если все I-J
и K-L
и M
имеют значение AAAA
, вы можете свернуть их все в один коммит, родитель которого равен H
:
...--H--M' <-- dev
ваша задача - определить, какие коммиты вы хотите сохранить, и что вы хотите сделать с коммитами слияния.Вы должны сохранять коммиты слияния, если вам нужно сохранить структуру (форк-энд-слияние в H
и M
).Если вы хотите исключить структуру ветвления и слияния, вы должны отменить коммиты слияния, но затем вы должны выяснить, что делать со странными коммитами, такими как I
и L
если они принадлежат другому автору.
Что бы вы ни решили, когда вы, наконец, сделали, способ достичь желаемого результата:
Началосо списком всех коммитов (по хеш-идентификатору), которые вы хотите сохранить, и / или всех коммитов, которые вы хотите отменить.(Достаточно и того, и другого, поскольку мы предполагаем, что вы будете поддерживать устойчивый юниверс Всех Коммитов, пока вы делаете это, то есть не добавляйте new коммитов в репозиторий, пока вы вычисляете эти списки ивнесение изменений в хранилище.)
Затем запустите git filter-branch
.Выберите хотя бы --commit-filter
.Вам могут потребоваться дополнительные фильтры, в зависимости от того, какие другие исторические данные вы намереваетесь удалить здесь.(Например, у каждого коммита есть сообщение журнала: хотите ли вы объединить все сообщения журнала или отбросить те из коммитов, снимок которых вы выбросили? Что равно что вы делаете: вы создаете вымышленную историю. Вы можете составить столько, сколько захотите, оставив только то, что вам нравится, из исходной истории, отбросив все остальное. Что вы держите и что отбрасываете доВы. Ваш новый репозиторий несовместим со старыми репозиториями: изменение хотя бы одного бита в любом месте истории делает оставшуюся историю недействительной и несовместимой. Таким образом, вы можете пойти так далеко, как захотите: это действительно все или ничего!)
В вашем фильтре фиксации - прочитайте документацию git filter-branch
для деталей - используйте skip_commit
, чтобы пропустить коммиты, которые вы не хотите и git commit-tree "$@"
, чтобы сделатькоммиты, которые вы хотите сохранить.Чтобы решить, просто посмотрите, есть ли $GIT_COMMIT
в списке хранения или отмены.
Команда filter-branch позаботится о перечислении каждого коммита, по одному, в правильномСделайте так, чтобы вы могли создавать или исключать коммит из истории, которую вы создаете, на ходу.После того, как ваш фильтр фиксации будет вызываться для каждого такого коммита, он запишет идентификатор хэша последнего скопированного коммита в имя хэша.Оригинальная история теперь фактически исчезла (но все еще доступна через имя refs/original/refs/head/<em>branch</em>
; это имя не будет в каких-либо новых клонах, и вы можете отказаться от него, когда будете готовы; снова посмотритедокументация).