Как лучше раздавить старые коммиты

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

Как мне сделать это, например, следующие коммиты (предполагая, что от 2 месяцев назад означает, что их сотни)?

.... от 2 месяца назад

aabbcc updated
aabbdd updated
aabbee updated
aabbff updated

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

Ответ 1

Чтобы выполнить сквош git, выполните следующие действия:

// X is the number of commits you wish to squash
git rebase -i HEAD~X

Как только вы раздавите свои коммиты - выберите s для squash = он объединит все коммиты в одну фиксацию.

введите описание изображения здесь


У вас также есть флаг -root, если он вам нужен

попробуйте: git rebase -i --root

- root

Rebase all commits reachable from <branch>, instead of limiting them with
an <upstream>.

This allows you to rebase the root commit(s) on a branch.  
When used with --onto, it will skip changes already contained in `<newbase>`   
(instead of `<upstream>`) whereas without --onto it will operate on every 
change. When used together with both --onto and --preserve-merges, all root 
commits will be rewritten to have `<newbase>` as parent instead.`

Ответ 2

Возраст коммитов не имеет значения, компрометирующие коммиты комментируют.

Если rebasing не предпочтительнее для вас, или есть буквально тысячи коммитов, которые вы хотите сквош и не можете их беспокоить, вы могли бы просто reset мягко для первого хеш-сообщения и повторно передать все:

$ git reset aabbff 
$ git commit -m "This commit now contains everything from the tip until aabbff"

У вас тогда будет только одна фиксация, то же самое, что и rebase → squash.

Ответ 3

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

Короче говоря, мое локальное git-репозиторий (в NFS, нет апстрима) работает как резервная копия определенных файлов, и я хотел, чтобы в нем было максимум 50 коммитов. Поскольку существует много файлов и резервные копии создаются довольно часто, мне нужно что-то, что автоматически уничтожает историю, поэтому я создал сценарий, который одновременно создает резервные копии файлов и уничтожает историю.

#!/bin/bash

# Max number of commits preserved
MAX_COMMITS=50

# First commit (HEAD~<number>) to be squashed
FIRST_SQUASH=$(echo "${MAX_COMMITS}-1"|bc)

# Number of commits until squash
SQUASH_LIMIT=60

# Date and time for commit message
DATE=$(date +'%F %R')

# Number of current commits
CURRENT_COMMITS=$(git log --oneline|wc -l)

if [ "${CURRENT_COMMITS}" -gt "${SQUASH_LIMIT}" ]; then

    # Checkout a new branch 'temp' with the first commit to be squashed
    git checkout -b temp HEAD~${FIRST_SQUASH}

    # Reset (soft) to the very first commit in history
    git reset $(git rev-list --max-parents=0 --abbrev-commit HEAD)

    # Add and commit (--amend) all the files
    git add -A
    git commit --amend -m "Automatic squash on ${DATE}"

    # Cherry pick all the non-squashed commits from 'master'
    git cherry-pick master~${FIRST_SQUASH}..master

    # Delete the 'master' branch and rename the 'temp' to 'master'
    git branch -D master
    git branch -m master

fi

Итак, что в основном делает скрипт (я удалил резервную копию):

  1. Если существует более 60 коммитов, он объединяет все коммиты от 50 до 60+ в один коммит.
  2. Создает и проверяет новую ветку на основе коммита
  3. Черри выбирает оставшиеся коммиты от мастера (с 1 по 49) на ветку
  4. Удаляет главную ветку
  5. Переименовывает новую ветку в master.