Как раздавить все git коммиты в один?



Как вы раздавите весь свой репозиторий до первого коммита?



Я могу перебазироваться на первый коммит, но это оставит меня с 2 коммитами.
Есть ли способ ссылаться на фиксацию перед первым?

914   15  

15 ответов:

пожалуй, самый простой способ-это просто создать новый репозиторий с текущим состоянием рабочей копии. Если вы хотите сохранить все сообщения, Вы могли бы сначала сделать git log > original.log а затем отредактируйте это для вашего первоначального сообщения фиксации в новом репозитории:

rm -rf .git
git init
git add .
git commit

или

git log > original.log
# edit original.log as desired
rm -rf .git
git init
git add .
git commit -F original.log

В последних версиях Git, вы можете использовать git rebase --root -i.

для каждого коммита, кроме первого, изменить pick to squash.

обновление

я сделал псевдоним git squash-all.
пример использования:git squash-all "a brand new start".

[alias]
  squash-all = "!f(){ git reset $(git commit-tree HEAD^{tree} -m \"${1:-A new start}\");};f"

будьте осторожны: не забудьте предоставить комментарий, в противном случае будет использоваться сообщение фиксации по умолчанию "новый старт".

или вы можете создать псевдоним с помощью следующей команды:

git config --global alias.squash-all '!f(){ git reset $(git commit-tree HEAD^{tree} -m "${1:-A new start}");};f'

Один Лайнер

git reset $(git commit-tree HEAD^{tree} -m "A new start")

Примечание: здесь "A new start" это просто пример, не стесняйтесь используйте свой собственный язык.

TL; DR

не нужно сквош, использовать git commit-tree чтобы создать сироту совершить и пойти с ним.

объяснить

  1. создать один коммит через git commit-tree

    что git commit-tree HEAD^{tree} -m "A new start" это:

    создает новый объект фиксации на основе предоставленного объекта дерева и выдает новый идентификатор объекта фиксации на stdout. Сообщение журнала является считывание со стандартного входа, если только-m или-F варианты приведены.

    выражение HEAD^{tree} означает объект дерева, соответствующий HEAD, а именно кончик текущая ветка. смотрите Дерево-Объекты и Commit-Objects.

  2. сброс текущей ветви к новой фиксации

    затем git reset просто сбросьте текущую ветку на вновь созданную зафиксировать объект.

таким образом, ничего в рабочей области нет прикоснулся, ни там нужно перебазировать / сквош, что делает его очень быстрым. И необходимое время не имеет отношения к размеру репозитория или глубине истории.

вариация: новое РЕПО из шаблона проекта

это полезно для создания "начальной фиксации" в новом проекте с использованием другого репозитория в качестве шаблона/архетипа/семени/скелета. Например:

cd my-new-project
git init
git fetch --depth=1 -n https://github.com/toolbear/panda.git
git reset --hard $(git commit-tree FETCH_HEAD^{tree} -m "initial commit")

это позволяет избежать добавления шаблона РЕПО в качестве пульта дистанционного (origin или иначе) и сворачивает история РЕПО шаблона в вашу первоначальную фиксацию.

если все, что вы хотите сделать, это раздавить все ваши коммиты до корневого коммита, то в то время как

git rebase --interactive --root

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

вот два более быстрых и эффективных решения, когда вы раздавливаете большое количество коммиты:

альтернативное решение #1: сиротские ветви

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

git checkout --orphan new-master master
git commit -m "Enter commit message for your new initial commit"

# Overwrite the old master branch reference with the new one
git branch -M new-master master

документы:

альтернативное решение #2: мягкий сброс

еще одно эффективное решение-просто использовать смешанный или мягкий сброс к корневой фиксации <root>:

git branch beforeReset

git reset --soft <root>
git commit --amend

# Verify that the new amended root is no different
# from the previous branch state
git diff beforeReset

документы:

echo "message" | git commit-tree HEAD^{tree}

это создаст потерянный коммит с деревом HEAD и выведет его имя (SHA-1) на stdout. Тогда просто сбросьте свою ветку там.

git reset SHA-1

самый простой способ-использовать команду "сантехника"update-ref для удаления текущей ветви.

вы не можете использовать git branch -D поскольку он имеет предохранительный клапан, чтобы остановить удаление текущей ветви.

Это возвращает вас в состояние "начальная фиксация", где вы можете начать с новой начальной фиксации.

git update-ref -d refs/heads/master
git commit -m "New initial commit"

вот как я закончил это делать, на всякий случай, если это работает для кого-то другого:

помните, что всегда есть риск в таких вещах, и это никогда не плохая идея, чтобы создать ветку сохранения перед запуском.

войдите

git log --oneline

прокрутите до первой фиксации, скопируйте SHA

git reset --soft <#sha#>

заменить <#sha#> w / SHA скопировано из журнала

git status

убедитесь, что все зеленое, в противном случае запустите git add -A

git commit --amend

изменить все текущие изменения на текущую первую фиксацию

теперь принудительно нажмите эту ветку, и она перезапишет то, что есть.

Я читал что-то об использовании трансплантатов, но никогда не исследовал его много.

в любом случае, вы можете раздавить эти последние 2 коммита вручную с чем-то вроде этого:

git reset HEAD~1
git add -A
git commit --amend

во-первых, сквош все ваши коммиты в один коммит, используя git rebase --interactive. Теперь у вас осталось два коммита на сквош. Для этого прочитайте любой из

сквош с помощью трансплантатов

Добавить файл .git/info/grafts, поместите туда хэш фиксации, который вы хотите стать своим корнем

git log теперь начнем с этой фиксации

чтобы сделать его "реальным" запустить git filter-branch

"альтернативное решение №1: сиротские ветви" помогает мне.

" git rebase --interactive --root " застрял в конфликте файлов gitignored.

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

  • автора (имя и адрес электронной почты)
  • автор дата
  • коммитеров (имя и адрес электронной почты)
  • совершено дата
  • Commmit log message

конечно коммит-ша нового / сингла фиксация изменится, потому что она представляет собой новую (не-)историю, становясь родительской/корневой фиксацией.

Это можно сделать, прочитав git log и установка некоторых переменных для git commit-tree. Предполагая, что вы хотите создать одну фиксацию из master в новом филиале one-commit, сохраняя фиксацию данных выше:

git checkout -b one-commit master ## create new branch to reset
git reset --hard \
$(eval "$(git log master -n1 --format='\
COMMIT_MESSAGE="%B" \
GIT_AUTHOR_NAME="%an" \
GIT_AUTHOR_EMAIL="%ae" \
GIT_AUTHOR_DATE="%ad" \
GIT_COMMITTER_NAME="%cn" \
GIT_COMMITTER_EMAIL="%ce" \
GIT_COMMITTER_DATE="%cd"')" 'git commit-tree master^{tree} <<COMMITMESSAGE
$COMMIT_MESSAGE
COMMITMESSAGE
')

Я обычно делаю это так:

  • убедитесь, что все зафиксировано, и запишите последний идентификатор фиксации в случае, если что-то пойдет не так, или создайте отдельную ветку в качестве резервной копии

  • выполнить git reset --soft `git rev-list --max-parents=0 --abbrev-commit HEAD` чтобы сбросить голову до первого фиксации, но оставить свой индекс без изменений. Все изменения, внесенные с момента первой фиксации, теперь будут готовы к фиксации.

  • выполнить git commit --amend -m "initial commit" чтобы изменить фиксацию к первой фиксации и измените сообщение фиксации, или если вы хотите сохранить существующее сообщение фиксации, вы можете запустить git commit --amend --no-edit

  • выполнить git push -f в силу изменений

создать резервную копию

git branch backup

сброс к указанному commit

git reset --soft <root>

добавить все файлы в staging

git add .

фиксация без обновления сообщения

git commit --amend --no-edit

нажмите новую ветку с раздавленными коммитами на репо

git push -f

в строке 6 слова

git checkout --orphan new_root_branch  &&  git commit

Comments

    Ничего не найдено.